Correspondência de modelo invariável de escala e rotação

12

Estou procurando um método para correspondência invariável de modelos de escala e rotação. Eu já tentei alguns, mas eles não funcionaram tão bem para os meus exemplos ou levaram para sempre a execução. A detecção de SIFT e SURF falhou totalmente. Também tentei implementar uma função de correspondência de modelo Log-Polar, mas nunca terminei (não sabia exatamente como fazê-lo).

Nestes artigos (o primeiro está em alemão)

http://cvpr.uni-muenster.de/teaching/ss08/seminarSS08/downloads/Wentker-Vortrag.pdf

http://www.jprr.org/index.php/jprr/article/viewFile/355/148

Eu li sobre esse método. O mapeamento das coordenadas polares funcionou, mas não sei se está certo. As imagens são assim.

source_log_polar.png http://www.shareimages.com/images/pics/0/0/3/62394-pZSfl5WenZysnpyVnKg-source_log_polar.png

template_log_polar.png

E depois de combinar essas duas imagens com a função de correspondência de modelo do OpenCV, obtive esse resultado

match_log_polar.png

Agora eu não sei como continuar.

Meus modelos são sempre símbolos simples na construção de plantas e nas próprias plantas. Os símbolos podem diferir em tamanho e orientação.

Por exemplo, meu projeto simples:

insira a descrição da imagem aqui

E meu modelo

insira a descrição da imagem aqui

Neste exemplo, existe apenas um modelo, mas nos modelos deve encontrar todas as ocorrências, mesmo as com tamanhos e / ou orientações.

Alguém tem uma abordagem de como eu poderia resolver isso?

Editar:

Uma adição à abordagem de Andrey. O algoritmo de captura de distância para um perfil radial. (Usando o EmguCV)

private float[] getRadialProfile( Image<Gray, byte> image, Point center, int resolution )
 {

 var roi = image.ROI;

 if ( !roi.Contains( center ) )
  {
   return null;
  }

 var steps = resolution;
 var degreeSteps = 360 / (double)resolution;
 var data = image.Data;
 var peak = 0.0f;
 var bottom = double.MaxValue;
 var bottomIndex = 0;
 var width = roi.Width;
 var height = roi.Height;
 var minX = roi.X;
 var minY = roi.Y;

 float[] distances = new float[resolution];
 for ( var i = 0; i < steps; i++ )
  {
   var degree = i * degreeSteps;
   var radial = degree * Math.PI / 180.0;
   var dy = Math.Sin( radial );
   var dx = Math.Cos( radial );

   var x = (double)center.X;
   var y = (double)center.Y;

   while ( true )
    {
    x += dx;
    y += dy;
    if ( x >= minX + width || y >= minY + height || x <= minX || y <= minY )
     {
      x = -1;
      y = -1;
      break;
     }
    var pixel = data[(int)y, (int)x, 0];
    if ( pixel == 0 )
     {
      break;
     }
    }

    float distance = 0.0f;
    if ( x != -1 && y != -1 )
    {
      distance = (float)Math.Sqrt( Math.Pow( (center.X - x), 2 ) + Math.Pow( (center.Y - y), 2 ) );
    }

    distances[i] = distance;
    if ( distance > peak )
    {
      peak = distance;
    }
    if ( distance < bottom )
    {
      bottom = distance;
      bottomIndex = i;
    }
   }

    // Scale invariance. Divide by peak
   for ( var i = 0; i < distances.Length; i++ )
   {
     distances[i] /= peak;
   }

    // rotation invariance, shift to lowest value
   for ( var i = 0; i < bottomIndex; i++ )
   {
     distances.ShiftLeft(); // Just rotates the array nothing special
   }

   return distances;
}
Arndt Bieberstein
fonte
bem-vindo ao dsp.SE. Tentaremos ajudá-lo, mas fornecer informações mais precisas seria bom. O que você quer dizer com SIFT e SURF "falhou totalmente"? O que eles detectaram / combinaram? Além disso, eu pessoalmente não conheço a correspondência de modelos Log-Polar, mas, se você tentou, onde estava exatamente o problema?
Penelope
As detecções dos recursos SIFT e SURF não encontraram nenhum recurso na imagem do modelo. Parecia que o modelo tinha muito menos informações (apenas aquele pequeno arco e uma linha). Para a correspondência Log-Polar, encontrei um artigo onde está descrito, mas não a matemática exata por trás dele. Vou procurá-lo e adicioná-lo.
Arndt Bieberstein
Ei, muitas pessoas aqui não entendem alemão, eu acho: D Mas, para todo o resto: você pode editar sua própria postagem para adicionar novas informações no lugar certo, em vez de nos comentários. Além disso, você ainda não disse exatamente com o que tinha problemas.
Penelope
3
O autor de " German Article" possui um artigo em inglês - www-cs.engr.ccny.cuny.edu/~wolberg/pub/icip00.pdf (graças ao google)
SergV

Respostas:

6

Eu acho que você pode resolver seu problema de uma maneira muito mais fácil. Considerando que você está lidando com projetos, não deve se preocupar com conectividade de borda, ruído e muitas outras coisas que o SIFT e o SURF foram criados para acomodar. Seu modelo é uma forma oca com formas de aresta específicas.

Assim, minha recomendação é:

  • Percorra o perímetro e encontre um perfil das distâncias das arestas ao redor do centro do modelo. Este é o perfil radial do modelo. Divida pela maior distância, para ser invariante na escala. Gire o vetor para que a menor distância seja a primeira, para ser invariante na rotação. (Se o seu modelo não tiver uma distância dominante, você poderá alterar a etapa 2 posteriormente)

insira a descrição da imagem aqui

  • Encontre blobs na imagem. Calcule o perfil radial descrito na parte (1) e compare os dois vetores por correlação normalizada. Se o seu modelo não tiver uma distância dominante, a correlação se tornará uma correlação cruzada normalizada e a seleção máxima). Aqueles que ultrapassam algum limiar são considerados correspondências.

Aqui está um código do Matlab para você começar - escrevi a parte que encontra o perfil da distância para um blob específico e o calculei para o modelo:

function Doors
    im = imread('http://i.stack.imgur.com/Tf8EV.png');
    im = im(:,:,1);
    template = imread('http://i.stack.imgur.com/PlP4i.png');
    template = template(:,:,1);

    blobs = regionprops(template>0,'Area','Image');
    largestBlob = GetLargestBlob(blobs);
    [prof,edgeImage] = GetBlobRadialProfile(largestBlob);

    figure;
    subplot(1,2,1);plot(prof); title('Radial profile')
    subplot(1,2,2);imshow(edgeImage); title('Template');

end

function [prof,edgeImage] = GetBlobRadialProfile(blob)
    paddedImage = padarray( blob.Image,[8 8]);
    erodedImage = imerode(paddedImage,strel('disk',1));
    edgeImage = xor(erodedImage,paddedImage);

    c = regionprops(paddedImage,'Centroid');
    cx  = c.Centroid(1);
    cy  = c.Centroid(2);

    [y,x] = find(edgeImage);
    rad = (x(:)-cx).^2 + (y(:)-cy).^2;
    [~,minIndex] = min(rad);
    contour = bwtraceboundary(edgeImage, [y(minIndex), x(minIndex)],'N');
    prof = (contour(:,2)-cx).^2 + (contour(:,1)-cy).^2;
    prof = prof./max(prof);
end

function largestBlob = GetLargestBlob(blobs)    
    area = [blobs.Area];
    [~,index] = max(area);
    largestBlob = blobs(index);
end
Andrey Rubshtein
fonte
Eu acho que isso não funciona com formas não fechadas? Ou simplesmente pulo esses "buracos" na forma.
Arndt Bieberstein
@ArndtBieberstein, Sim, funciona apenas para formas fechadas. Eu acho que deveria haver algum método para estendê-lo.
Andrey Rubshtein
Como o OpenCV não contém a função bwtraceboundary, escrevi o meu e apenas "pulei" os buracos e preenchi com zeros. Aqui está um pequeno exemplo de como os resultados agora parecem. 5 parcelas para cada modelo. Os pontos vermelhos são os pontos de partida. Exemplo de gráfico
Arndt Bieberstein
@ArndtBieberstein, very nice! Talvez você possa compartilhar os resultados conosco quando terminar.
Andrey Rubshtein
Certamente, o Código não é tão bom ou eficiente, mas funciona. Vou anexá-lo abaixo da minha pergunta. Ele é escrito em C # (estou usando EmguCV)
Arndt Bieberstein
3

Aqui está a idéia básica do que sei que pode ser feita, com base em uma palestra do professor Anurag Mittal, do IIT Madras.

A idéia é a detecção de objetos com base na forma, mas obviamente também pode ser estendida para outros lugares.

  1. Calcule os bordos usando o detector de borda de Berkeley.
  2. Conecte as arestas obtidas. "Detecção global de limites de objetos".
  3. Correspondência de formas usando a distância do chanfro ou a distância de Houstoff.

Seu artigo sobre o mesmo está disponível em: Detecção de Objetos Deformáveis ​​com Base em Contorno de Vários Estágios.

Por outro lado, acho que o SIFT deve funcionar, pois os algoritmos de detecção de canto funcionariam no recurso de modelo que você tem por lá.

Nota: SIFT não é completamente invariável para rotação. Não é capaz de lidar com rotações> 60 graus ou mais. Portanto, formar vários modelos é uma boa ideia.

Como nas transferências de Fourier-Mellin baseadas em log-polar: Elas causam perda de informações devido à forma como a amostragem ocorre para as transformações.

Naresh
fonte
Este método parece realmente promissor! Não consigo abrir seu link, mas pesquisei sua abordagem no Google. Eu não sabia que SIFT que SIFT não é completamente diferente da rotação! Resposta muito boa! +1
Arndt Bieberstein
1
Eu dificilmente encontrei algo sobre o Chamfer Distance e como ele funciona, para quem também está procurando por este, tente este link.
Arndt Bieberstein
@Naresh SIFT não é invariável para a rotação de grandes rotações fora do plano. Não no mesmo plano.
-Jays
1

Eu não pensei muito nisso, mas tenho certeza de que uma solução robusta pode ser encontrada sem muitos problemas usando o clássico Fourier Descriptors (FD). Acho que seu problema pode ser um bom candidato para isso. Não pense que você precisa fazer a detecção de bordas porque possui desenhos de linhas pretas. Basta iniciar a varredura de varredura até atingir os pixels e faça o seguinte:

Apenas trate os perímetros da sua sala como se fossem um sinal 1D, onde a amplitude do sinal é a distância normal do centróide do objeto, amostrada a uma taxa constante. Então, faça um modelo FD simples para a porta. Em seguida, verifique o parâmetro de cada sala com uma espécie de filtro convexo, procurando uma borda ascendente, um pico e uma queda, que define uma janela de início / parada do "sinal" para capturar. Faça um FFT ou algo similar no FD capturado no "sinal" e compare com o modelo FD. Talvez a etapa de comparação do modelo possa ser uma correlação simples com um limite para acionar uma correspondência. Como apenas suas portas têm bordas arredondadas, esse deve ser um problema de correspondência de FD bastante fácil.

Pense nisso como usar FDs para recuperar imagens ou músicas de um banco de dados. Muitos white papers sobre isso.

Este é um bom tutorial sobre o uso de FDs para aproximar formas: duvido que você precise, mas também é possível transformar suas imagens em uma estrutura de coordenadas polares para lidar com rotações, como proposto neste artigo: Recuperação de imagens com base em formas usando descritor genérico de Fourier

vê como eles parametrizam a detecção do perímetro da maçã? A mesma ideia que a sua porta.

BTW, tenho certeza de que o mapeamento de todo o esquema para coordenadas polares não ajudará a invariância rotacional - você precisaria fazer isso sobre o centróide de cada porta, que é exatamente o que seu problema deve começar. É por isso que eu acho que você deseja capturar apenas candidatos a porta e talvez mapeá-los para coordenadas polares para combinar com o modelo de porta FD, como foi feito no documento acima.

deixe-me saber como será, se você tentar essa abordagem.

Ariel Bentolila
fonte
0

Talvez você ache este código do Matlab que escrevi útil: Mosaicos Fractal

Ele implementa o artigo "Registro robusto de imagens usando a transformação log-polar" ( pdf ) em uma aplicação artística que exigia mais robustez do que os métodos tradicionais que encontrei.

user2348114
fonte