Wykrywanie koła w hałaśliwych danych obrazu

17

Mam obraz, który wygląda jak ten poniżej: wprowadź opis zdjęcia tutaj

Próbuję znaleźć promień (lub średnicę) koła. Próbowałem użyć okrągłej transformacji Hougha (przez matlaba imfindcircles(bw,[rmin rmax],'ObjectPolarity','bright')) i dopasowując się do koła lub elipsy (funkcja stworzona przez dom, która działa całkiem dobrze dla mniej hałaśliwych danych, patrz poniżej).

Próbowałem także przetwarzania obrazu, aby uzyskać wyraźniejszy okrąg, na przykład patrz poniżej:

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

wprowadź opis zdjęcia tutaj

Jednak gdy przesyłam przetworzony obraz do dowolnej techniki (dopasowanie Hougha i elipsy koła) żadna z nich nie zdoła wykryć koła w przyzwoity sposób.

Oto fragment kodu wyszukiwarki okręgu, którą napisałem (matlab) [row col] = find (bw); kontur = bwtraceboundary (mc, wiersz (1), col (1)], 'N', connectivity, 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);

Docenione zostaną alternatywne podejścia ...

bla
źródło
Przekształcenie Hougha szuka koła, a nie wypełnionego dysku. najpierw musisz wykonać wykrywanie krawędzi, aby przekonwertować wypełniony dysk na pusty okrąg. jakie są właściwości twoich kręgów? czy rozmiar jest stały? czy mogą być elipsami? czy kropki mogą być rozmieszczone inaczej?
endolith,
Próbowałem (patrz zredagowany przykład), czy to jest zbyt głośne, czy nie wystarczająco okrągłe? Dodatkowo rozmiar jest stały i może mieć niewielką eliptyczność (choć w rzeczywistości jest to idealnie okrągłe okno) z powodu błędu kąta kamery.
bla
jeśli rozmiar i kształt są stałe, możesz wypróbować coś w rodzaju korelacji krzyżowej wypełnionego szablonu dysku z oryginalnym obrazem kropkowym
endolith
Oprócz mojej odpowiedzi, myślę, że możesz próbować to zrobić na zbyt późnym etapie przetwarzania obrazu. Czy możesz powiedzieć nam więcej o problemie i pokazać kilka wcześniejszych kroków?
Andrey Rubshtein

Odpowiedzi:

13

Oto moje rozwiązanie, jest zbliżone do pomysłu @ Yody, ale zmieniłem kilka kroków.

  • Zaznacz wszystkie piksele tak, aby w ich otoczeniu 7x7 było co najmniej 6 pikseli
  • Usuń wszystkie obiekty BLOB, ale największe
  • Wypełnij dziury
  • Zastosuj wykrywanie krawędzi
  • Znajdź krąg za pomocą transformacji Hougha

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

Oto odpowiedni kod Matlaba. Korzystam z transformacji Hougha dla pliku .m kręgów w moim kodzie.

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
źródło
1
Co robi tutaj transformacja Hougha, która rozwiązuje problem i znajduje niebieskie koło? Czy wyświetla wiele okręgów o różnych promieniach w różnych pozycjach na obrazie i znajduje takie, które najlepiej pasuje?
Spacey,
@Mohammad, jest to zwykły wykrywacz okręgu. Wykorzystuje binowanie i głosowanie.
Andrey Rubshtein
Możesz także użyć szybkiej radialnej transformacji symetrii (FRST) po pierwszym kroku tej odpowiedzi.
Geniedesalpages
10

Wykonanie tego przy użyciu przetwarzania obrazu jest dość proste. Poniżej znajduje się dowód koncepcji w Mathematica . Musisz to przetłumaczyć na MATLAB.

  • Najpierw przytnij osie i zachowaj tylko część obrazową. Nazywam tę zmienną img.
  • Binaryzuj obraz i rozszerz go, a następnie wypełnij transformację. Usuwam również zbłąkane małe elementy, które nie są podłączone do głównego obiektu blob. Powinien dać ci coś takiego:

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

  • Następnie znajdź środek ciężkości tego obiektu blob i równoważny promień dysku obiektu blob (wszystkie openCV, MATLAB mają równoważne polecenia, aby to zrobić)

    {center, radius} = 1 /. ComponentMeasurements[filled, {"Centroid", "EquivalentDiskRadius"}]
    
  • Otóż ​​to! Teraz wykreśl oryginalny obraz i okrąg z powyższym środkiem i promieniem, aby zobaczyć, jak pasuje:

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

Lorem Ipsum
źródło
Świetna odpowiedź! Czy możesz rozwinąć transformację dylatacyjną i wypełniającą?
Spacey,
Dylatacja @Mohammad jest podstawową operacją i można ją łatwo wyjaśnić w artykule wiki. Transformacja wypełniająca wypełnia „dziury” lub innymi słowy zestawy pikseli otoczonych pikselami o większej wartości. Zobacz sekcję „Więcej informacji” tutaj
Lorem Ipsum,
Ach przepraszam, źle wpisałem. Jestem nieco zaznajomiony z transformacją dylatacji, zastanawiałem się, czy możesz rozwinąć tę „transformację wypełniającą”. Jakiego zestawu reguł używa dokładnie? Nie mogę znaleźć informacji z tym związanych. Być może ma inną nazwę?
Spacey,
@yoda, dziękuję za odpowiedź, ale jeśli przeczytasz pytanie, zauważysz, że próbowałem rozszerzyć i pasować. Obraz utworzony przed wykryciem krawędzi jest podobny do twojego. Czuję się trochę sprawny, to nie jest dokładne. To samo dotyczy twojego dopasowania, możesz zobaczyć, że górna część dopasowanego koła jest zbyt duża, prawdopodobnie dlatego, że bierzesz pod uwagę hałaśliwy punkt w górnej części nad okręgiem. Próbowałem również dopasować elipsę (jak stwierdzono w pytaniu), problem polega na tym, że dopasowanie nie jest wystarczająco dobre. Myślę, że lepszym sposobem może być użycie lepszej części koła (łuku) do dopasowania.
bla
@ kwiecisty Nie rozumiem, co masz na myśli przez „górną część dopasowanego koła” i „lepszą część koła”. Możesz użyć różnych wskaźników ... obwiedni, długości głównej osi, długości osi pomocniczej, średniej odległości od środka ciężkości, środkowej odległości od środka ciężkości itp. Wszystko zależy od tego, czego chcesz.
Lorem Ipsum