Detecção de um círculo em dados de imagem ruidosos

17

Eu tenho uma imagem que se parece com a abaixo: insira a descrição da imagem aqui

Estou tentando encontrar o raio (ou diâmetro) do círculo. Eu tentei usar a transformação circular de Hough (via matlab's imfindcircles(bw,[rmin rmax],'ObjectPolarity','bright')) e ajustando-me a um círculo ou elipse (função caseira que funciona muito bem para dados menos ruidosos, veja abaixo).

Eu também tentei algum processamento de imagem para obter um círculo mais claro, por exemplo, veja abaixo:

se = strel('disk', 2);
bw = imdilate(bw, se);
bw = bwareaopen(bw,100000); 
bw =  edge(bw); 

insira a descrição da imagem aqui

No entanto, quando eu alimento a imagem processada para qualquer uma das técnicas (ajuste de Hough e circle \ elipse), nenhuma delas consegue detectar o círculo de maneira decente.

Aqui está um trecho de código do localizador de círculos que eu escrevi (matlab) [row col] = find (bw); contorno = bwtraceboundary (bw, linha (1), col (1)], 'N', conectividade, num_points);

    x = contour(:,2);
    y = contour(:,1);

    % solve for parameters a, b, and c in the least-squares sense by
    % using the backslash operator
    abc = [x y ones(length(x),1)] \ -(x.^2+y.^2);
    a = abc(1); b = abc(2); c = abc(3);

    % calculate the location of the center and the radius
    xc = -a/2;
    yc = -b/2;
    radius  =  sqrt((xc^2+yc^2)-c);

Abordagens alternativas serão apreciadas ...

bla
fonte
A transformação Hough procura um círculo, não um disco cheio. você precisaria fazer a detecção de arestas primeiro para converter o disco preenchido em um círculo vazio. quais são as propriedades dos seus círculos? o tamanho é constante? eles podem ser elipses? os pontos podem ser distribuídos de maneira diferente?
Endolith 06/11/12
Eu tentei (veja o exemplo editado), é muito barulhento ou não é circular o suficiente? Além disso, o tamanho é constante e pode ter uma elipticidade diminuta (embora, na realidade, seja uma janela perfeitamente circular) devido a um erro de ângulo da câmera.
bla
se o tamanho ea forma é constante, você pode tentar algo como correlação cruzada de um modelo de disco cheio com a imagem dot originais
endolith
Além da minha resposta, acho que você pode estar tentando fazer isso em um estágio muito posterior do seu pipe de processamento de imagem. Você poderia nos falar mais sobre o problema e mostrar algumas etapas anteriores?
Andrey Rubshtein

Respostas:

13

Aqui está a minha solução, é próxima da idéia do @ Yoda, mas eu mudei alguns passos.

  • Marque todos os pixels de forma que haja pelo menos 6 pixels na vizinhança 7x7
  • Remova todos os blobs, mas o maior
  • Preencher orifícios
  • Aplicar detecção de borda
  • Encontre um círculo usando a transformação Hough

insira a descrição da imagem aqui insira a descrição da imagem aqui insira a descrição da imagem aqui insira a descrição da imagem aqui insira a descrição da imagem aqui

Aqui está o código Matlab relevante. Estou usando a transformação Hough para o arquivo .m de círculos no meu código.

function FindCircle()
    close all;
    im = imread('C:\circle.png');
    im = im(:,:,2);

    ims = conv2(double(im), ones(7,7),'same');
    imbw = ims>6;
    figure;imshow(imbw);title('All pixels that there are at least 6 white pixels in their hood');

    props = regionprops(imbw,'Area','PixelIdxList','MajorAxisLength','MinorAxisLength');
    [~,indexOfMax] = max([props.Area]);
    approximateRadius =  props(indexOfMax).MajorAxisLength/2;

    largestBlobIndexes  = props(indexOfMax).PixelIdxList;
    bw = false(size(im));
    bw(largestBlobIndexes) = 1;
    bw = imfill(bw,'holes');
    figure;imshow(bw);title('Leaving only largest blob and filling holes');
    figure;imshow(edge(bw));title('Edge detection');

    radiuses = round ( (approximateRadius-5):0.5:(approximateRadius+5) );
    h = circle_hough(edge(bw), radiuses,'same');
    [~,maxIndex] = max(h(:));
    [i,j,k] = ind2sub(size(h), maxIndex);
    radius = radiuses(k);
    center.x = j;
    center.y = i;

    figure;imshow(edge(bw));imellipse(gca,[center.x-radius  center.y-radius 2*radius 2*radius]);
    title('Final solution (Shown on edge image)');

    figure;imshow(im);imellipse(gca,[center.x-radius  center.y-radius 2*radius 2*radius]);
    title('Final solution (Shown on initial image)');

end
Andrey Rubshtein
fonte
1
O que a transformação Hough está fazendo aqui que a resolve e encontra o círculo azul? Está projetando muitos círculos de raios diferentes em posições diferentes da imagem e encontrando o que melhor se encaixa?
Spacey
@ Mohammad, é o detector de círculo usual. Ele usa binning e votação.
Andrey Rubshtein
Você também pode usar a Transformada de simetria radial rápida (FRST) após a primeira etapa desta resposta.
precisa saber é o seguinte
10

É bastante simples fazê-lo usando o processamento de imagens. A seguir, uma prova de conceito no Mathematica . Você terá que traduzi-lo para o MATLAB.

  • Primeiro, apare os eixos e mantenha apenas a parte da imagem. Eu chamo essa variável img.
  • Binarize a imagem e dilate-a, seguida por uma transformação de preenchimento. Também removo pequenos componentes perdidos que não estão conectados ao blob principal. Deve fornecer algo como o seguinte:

    filled = Binarize@img ~Dilation~ 3 // FillingTransform // DeleteSmallComponents
    

  • Em seguida, encontre o centróide desse blob e o raio de disco equivalente do blob (openCV, MATLAB todos têm comandos equivalentes para fazer isso)

    {center, radius} = 1 /. ComponentMeasurements[filled, {"Centroid", "EquivalentDiskRadius"}]
    
  • É isso aí! Agora plote a imagem original e um círculo com o centro e o raio acima para ver como ela se encaixa:

    Show[img, Graphics[{Red, Circle[center, radius]}]]
    

Lorem Ipsum
fonte
Resposta incrível! Você pode expandir a transformação de dilatação e enchimento?
Spacey
@Mohammad Dilation é uma operação básica e seria facilmente explicada pelo artigo da wiki. A transformação de preenchimento preenche "furos" ou, em outras palavras, conjuntos de pixels cercados por pixels de maior valor. Veja a seção "Mais informações" aqui
Lorem Ipsum
Desculpe, eu digitei errado. Estou um pouco familiarizado com a transformação de dilatação, na verdade estava pensando se você poderia expandir a 'transformação de preenchimento'. Que conjunto de regras ele está usando exatamente? Não consigo encontrar informações relacionadas a isso. Talvez seja por outro nome?
Spacey
@ yoda, obrigado pela resposta, mas se você ler a pergunta, perceberá que tentei dilatação e adaptação. A imagem produzida antes de detectar as bordas é semelhante à sua. Eu fico em forma, não é preciso. O mesmo se aplica ao seu ajuste, você pode ver que a parte superior do círculo ajustado é muito grande, presumivelmente porque você leva em consideração o ponto de ruído na parte superior acima do círculo. Eu também tentei ajustar uma elipse (como declarado na pergunta), o problema é que o ajuste não é bom o suficiente. Acho que a melhor maneira seria usar a melhor parte do círculo (um arco) para fazer o ajuste.
bla
@nate Não entendo o que você quer dizer com "parte superior do círculo ajustado" e "parte melhor do círculo". Você pode usar métricas diferentes ... caixa delimitadora, comprimento do eixo principal, comprimento do eixo menor, distância média do centróide, distância média do centróide, etc. Tudo depende do que você deseja.
Lorem Ipsum