Pergunta

Estou batendo a cabeça há muito tempo neste

Estou fazendo imagens. Até agora, binarei minhas imagens, o que significa que, de uma imagem em escala de cinza, todos os pixels sob um determinado valor são descartados. Isso me dá apenas algumas regiões da imagem original, com muitos "zero pixels" em todas essas regiões.

Em seguida, o comprimento codificou minhas regiões em "Blobs". As execuções são um método de compactação para dados. Por exemplo, suponha que você tenha binarizado um quadrado, você terá apenas algumas corridas descrevendo toda a imagem. As execuções são definidas por coordenadas x, y e um comprimento.

Ao recriar a imagem, para cada execução, vá para x, Y coordenar e adicione pixels no eixo X para o comprimento da corrida.

Agora eu tenho que fazer as corridas e criar uma cadeia dela que descreva o contorno da região. Eu não sei como fazer isso.

Eu tenho um monte de x, y, comprimento e tenho que "navegar" pelas bordas para formar um corrente. Normalmente, na imagem, esse processo é feito com a imagem original, mas não posso mais usar a imagem original aqui, então tenho que calculá -la com as execuções.

Sei que isso parece uma grande parede de texto, mas não sei como fazer essa pergunta melhor.

Quaisquer dicas ou indicadores de implementação idêntica seriam impressionantes.

EDITAR

Graças ao desenrolar, vou vincular algumas imagens:

alt text
(fonte: tudelft.nl)

Neste exemplo, eles processam a imagem B no contorno C (que eu chamo de cadeia). No entanto, eu gostaria de gerar o contorno a partir de d, os comprimentos de execução

Foi útil?

Solução 3

Bem, eu perdi esse contrato, mas a resposta foi usar o Técnica de codificação da cadeia Freeman

O fato de serem comprimentos de execução que a codificação não tem nada a ver com o algoritmo, ao contrário de eu pensar anteriormente.

Outras dicas

À primeira vista, não vejo um algoritmo prático para isso. A solução de um homem pobre seria expandir a imagem original do comprimento codificado. Então, se suas linhas se parecem com a seguinte:

A 3B 10A C 8D
C 4D 3A 6C 9A

onde os caracteres retornam o valor de pixel real (por exemplo, a = 0, b = 127, ...). Você pode escrever os valores de pixel em uma matriz bidimensional (ou outraestrutura de dados de sua escolha). É assim:

ABBBAAAAAAAAAACDDDDDDDD
CDDDDAAACCCCCCAAAAAAAAA

Posteriormente, gerar sua corrente, exclua a matriz e mantenha as informações da cadeia. Claro que isso é caro então pode ser Você pode fazer isso antes de codificar a imagem original.

Aqui está uma solução perfeitamente simples e prática (C ++):

#include <iostream>
#include <vector>

struct Run { int x, w; };
enum { EAST, NORTHEAST, NORTH, NORTHWEST, WEST, SOUTHWEST, SOUTH, SOUTHEAST };

int main() {

    const Run data[] = {
        { 7, 2 },
        { 5, 6 },
        { 5, 7 },
        { 5, 7 },
        { 6, 6 },
        { 0, 12 },
        { 0, 12 },
        { 0, 11 },
        { 1, 7 },
        { 3, 4 },
        { 3, 4 },
        { 3, 5 },
        { 3, 7 },
        { 3, 7 },
        { 5, 5 }
    };

    std::vector<Run> runs(data, data + 15);
    std::vector<int> before;
    std::vector<int> after;
    unsigned int i;
    int j;

    for (i = 0; i < runs.size() - 1; ++i) {

        if (runs[i].x < runs[i + 1].x) {

            for (j = 0; j < runs[i + 1].x - runs[i].x - 1; ++j)
                before.push_back(WEST);
            before.push_back(NORTHWEST);

        } else if (runs[i].x > runs[i + 1].x) {

            before.push_back(NORTHEAST);
            for (j = 0; j < runs[i].x - runs[i + 1].x - 1; ++j)
                before.push_back(EAST);

        } else {

            before.push_back(NORTH);

        }

        int first_right(runs[i].x + runs[i].w);
        int second_right(runs[i + 1].x + runs[i + 1].w);

        if (first_right < second_right) {

            after.push_back(SOUTHEAST);
            for (j = 0; j < second_right - first_right - 1; ++j)
                after.push_back(EAST);

        } else if (first_right > second_right) {

            for (j = 0; j < first_right - second_right - 1; ++j)
                after.push_back(WEST);
            after.push_back(SOUTHWEST);

        } else {

            after.push_back(SOUTH);

        }

    }

    for (j = 0; j < runs.back().w - 1; ++j)
        after.push_back(WEST);

    std::reverse(before.begin(), before.end());
    after.insert(after.end(), before.begin(), before.end());

    for (j = 0; j < int(after.size()); ++j) {
        switch (after[j]) {
        case EAST:      std::cout << "EAST\n";      break;
        case NORTHEAST: std::cout << "NORTHEAST\n"; break;
        case NORTH:     std::cout << "NORTH\n";     break;
        case NORTHWEST: std::cout << "NORTHWEST\n"; break;
        case WEST:      std::cout << "WEST\n";      break;
        case SOUTHWEST: std::cout << "SOUTHWEST\n"; break;
        case SOUTH:     std::cout << "SOUTH\n";     break;
        case SOUTHEAST: std::cout << "SOUTHEAST\n"; break;
        }
    }

}

Isso funciona iterando as corridas, testando os pontos de extremidade esquerda e direita para a direção em que estão pulando e adicionando o número apropriado de elementos de corrente a dois vetores: um em ordem direta, para o lado direito e outro em ordem inversa , para a esquerda. Em seguida, ele conecta as duas cadeias adicionando o número apropriado de links para a última linha de varredura, depois reverte a corrente lateral esquerda e anexa -a à direita para produzir a cadeia final.

Espero que seja isso que você está procurando!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top