Muszę znaleźć kwadraty na obrazie przy użyciu OpenCV (bez problemu w Matlabie lub innym, ogólnie rzecz biorąc, oczekuję kilku pomysłów).
Rozważ poniższy obraz testowy:
Muszę dokładnie znaleźć te kolorowe kwadraty na powyższym obrazku (nie białe długie paski).
Co zrobiłem:
Zastosowałem wspólną metodę (która jest dostarczana z próbkami OpenCV), tj. Znajdź kontury we wszystkich płaszczyznach kolorów, przybliż ją i sprawdź liczbę elementów = 4. Działa do pewnego stopnia, że wykryto kilka kwadratów, szczególnie ciemnych.
Następnym krokiem było przewidywanie . tzn. to ustawienie jest ustalone . Jeśli więc niektóre zostaną uzyskane, mogę przewidzieć pozostałe. Działa również w pewnym stopniu. Ale dokładność była bardzo zła.
Ale wydaje mi się, że przewidywanie nie jest tutaj dobrą metodą i nie zawsze zapewnia dokładne odpowiedzi podane w pierwszym kroku.
Czego potrzebuję :
1) Czy istnieją inne lepsze metody dokładniejszego wykrywania tych kwadratów? Lub wiele metod?
Ważną kwestią jest to, że czas nie jest tutaj problemem . Algorytm może być powolny, to nie ma znaczenia. Ale dokładność jest głównym kryterium.
Czasami obrazy mogą być znacznie bardziej rozmyte.
Jednym z głównych problemów, z którymi się spotkałem, jest to, że niektóre kwadraty mają prawie podobny kolor jak tło (sprawdź kolumnę 3 pierwszy i drugi kwadrat).
Poszukuję pomysłów, z góry dziękuję
AKTUALIZACJA :
Poniżej znajduje się maksymalny dokładny wynik, jaki otrzymałem:
Oczywiście obraz wynikowy jest nieco przeskalowany.
AKTUALIZACJA 2:
W mojej odpowiedzi podałem znacznie lepsze rozwiązanie: https://dsp.stackexchange.com/a/7526/818
źródło
Odpowiedzi:
Pierwsza próba użycia Matlaba:
Wyniki w następujących regionach:
Jak widać, wybranie progu, który daje największą liczbę regionów (T = 120), dałoby już 7 poprawnych lokalizacji, niektóre scalone lokalizacje, jeden fałszywie dodatni i dwa fałszywie ujemne.
To była dość prosta próba, ale myślę, że pokazuje, że to podejście działa. Dodanie pewnych elementów w celu rozbicia podłużnych regionów lub zrobienie tego dla każdego kanału koloru osobno to tylko kilka rzeczy, które możesz zrobić, aby to poprawić.
Byłoby to również pomocne, jeśli podałeś jeszcze kilka zdjęć testowych.
źródło
Próbowałem czegoś innego, aby poprawić mój wynik. Poniżej znajduje się założenie, że pierwszy krok (pomarańczowy) jest zawsze wykrywany w kroku 1. I jest to praktyczne ze względu na jego wysoki kontrast koloru w porównaniu do tła. Nawet pokazany przeze mnie wynik poprawnie go wykrył
Krok 1: Znajdź jak najwięcej kwadratów
Podzieliłem obraz na płaszczyzny R, G, B, H, S, V i ustawiłem próg obrazu dla różnych wartości progowych, takich jak wielokrotności 25. Dla każdego obrazu znalazłem w nim kwadraty i umieściłem je na „obrazie maski” . Znalazłem też średnią wysokość i szerokość kwadratu.
obraz maski (Wykryto ogółem 7/12 kwadratów):
Krok 2: Utwórz siatkę kwadratów
Następnie znalazłem centroidy tych kwadratów na obrazku maski. Posortowałem je i znalazłem środek ciężkości pierwszego kwadratu (pomarańczowy). Z dokładnej analizy wynika, że odstęp między dwoma kwadratami jest kwadratem zarówno w kierunku poziomym, jak i pionowym. W ten sposób utworzyłem siatkę kwadratów jak poniżej i nazwałem ją ideal_squares (to tylko nazwa, to nie znaczy, że to wynik, którego potrzebuję):
ideal_squares:
Krok 3: Przypisz idealny_ obraz
Teraz mamy centroidy ideal_squares i oryginalne centroidy. Znalazłem prawidłowe dopasowania dla każdego oryginalnego centroidu z ideal_centroidów (biorąc odległość euklidesową między nimi). Następnie użyłem Scipy interpolate.griddata do interpolacji i odwzorowałem ideal_image zgodnie z wartościami centroidów (jest to prawie to samo, co wypaczenie wykonane w tych pytaniach i odpowiedziach: Jak usunąć defekty wypukłości w kwadracie sudoku i transformacji obrazu w OpenCV ). Więc poniżej mam wynik:
Wyjście:
Krok 4: LUB działaj powyżej wyjścia z obrazem maski z pierwszego kroku
Teraz możesz zobaczyć, że wszystkie kwadraty zostały wykryte, ale z problemem wymienionym poniżej:
Problem:
Spójrz na wynik kroku 3, tj. Odwzorowany obraz kwadratowej siatki. Z wyjątkiem dwóch centralnych kwadratów, wszystkie pozostałe kwadraty są obcinane. Jest to problem związany z tym mapowaniem. Nie jestem pewien, gdzie jest problem z scipy.interpolate.griddata () lub cv2.remap (). Myślałem, że cały obraz będzie wypaczony, ale tak nie jest. Wypacza tylko obraz wewnątrz podanych przez nas centroidów. Jeśli mogę to naprawić, wynik będzie OK.
Jeśli więc ktoś zna dobry pomysł, zapraszamy!
źródło
Uwaga: Ta metoda będzie bardzo powolna.
Wygeneruj maskę, która wygląda jak kontury idealnego obiektu. Podobnie do tego:
następnie przesuń (pozycję, skalę, obrót) maskę nad obrazem i dopasuj ją do konturu obrazu rzeczywistego (być może nieco rozmazanego, aby uzyskać łagodniejszą reakcję), aby obliczyć, jak są one podobne (pozycja, skala, obrót) z najwyższą odpowiedzią na podobieństwo powinna być (pozycja, skala, obrót) rzeczywistego obiektu.
Metoda nie ma nic przeciwko wtapianiu się kwadratów w tło lub nawet częściowej okluzji obiektu, ponieważ uwzględnia cały obiekt.
Osobiście z powodzeniem zastosowałem tę metodę do śledzenia pyska myszy i wąsów, ale miałem pewne domniemania, że była blisko ostatniej znanej pozycji itp. Ale myślę, że możesz zmniejszyć przestrzeń poszukiwań, stosując pewne założenia, takie jak: możliwe rozmiary obiektu w kamerze, jak daleko może być od środka, czy obrót <10 stopni itp.
źródło
Krok 1: Jakikolwiek końcowy obraz binarny otrzymujesz z analizy w płaszczyźnie B, G, R, H, S, V, na tym obrazie wykonaj algorytm zliczania kropel.
Krok 2: Znajdź największą kroplę na podstawie powierzchni lub długości konturu. Ponieważ twoje plamy będą głównie typami równoległoboków, czyli obszarami lub konturami, każdy to zrobi.
Krok 3: Z największą kroplą (ponieważ największa kropelka jest najlepszą kroplą przypominającą kwadraty z prawdziwego świata), spróbuj znaleźć orientację kropli ... możesz to uzyskać dopasowując najlepiej dopasowany prostokąt LUB możesz uzyskać punkty narożne ... uzyskaj nachylenie łączących je linii (zarówno w kierunku poziomym, jak i pionowym).
Krok 4: Po uzyskaniu dwóch stoków narysuj dwie linie przebiegające przez oś kropli. dla osi można uśrednić punkty narożne lub użyć środka ciężkości (środka masy) ... Wybrałbym średnią punktów narożnych ...
Krok 5: Ponieważ w każdym kierunku poziomym i pionowym odstępy są równe (idealnie poziome i pionowe odstępy są również równe, ponieważ pochodzi z idealnego kwadratu, ale nie zakładamy, że ..) wystarczy zlokalizować możliwe centroidy drugiego równoległoboki
LINIA DOLNA: Jeśli jakikolwiek kwadrat zostanie wykryty idealnie, możesz wykonać całą siatkę. Po prostu utrzymuj środki znakowania w odstępach 2H (H = pozioma szerokość największego obiektu blob) wzdłuż poziomej osi największego obiektu blob i w odstępie 2 V (V = wysokość pionowa największego obiektu blob) pionowo wzdłuż osi pionowej obiektu blob.
Niektóre zdjęcia do wsparcia
źródło
Naprawdę nie wiem, jakie przewidywałeś wcześniej, ale czy próbowałeś skupić się na białych długich paskach jako korzeniu. Następnie (jeśli 3 kolumny kwadratów mają równe rozmiary), możesz wykryć wysokość kwadratu (odległość między dwoma paskami) i możesz wykryć maksymalny i minimalny obszar (wysokość i szerokość) na obrazie.
Następnie spróbuj wykryć najczęstszy kolor w całym kwadracie i ustawić go na obszarze „innym niż kwadrat”. Reszta to kwadraty, których szukasz.
źródło
Sugerowałbym użycie transformaty Hougha, która jest bardzo solidnym algorytmem do znajdowania prostych kształtów parametrycznych, np. Linii, okręgów itp. Wykrywanie linii byłoby najlepsze w twoim przypadku. Można było znaleźć przynajmniej boki długich białych sripów; następnie za pomocą dowolnego algorytmu do wyodrębniania narożników (Harris, a może nawet SIFT lub SURF) można znaleźć rogi wzdłuż tych linii, nawet korzystając z faktu, że kwadraty są w przybliżeniu jednakowo rozmieszczone.
źródło
Próbowałem ten problem przy użyciu opencv, python. Podejście polega na zamaskowaniu obrazu na podstawie kolorów, a następnie znalezieniu odpowiednich konturów.
Kod: https://github.com/rbhambriiit/computer_vision/blob/master/find_color_box
[Nieodebrane 1 pole, ale powinno to nastąpić poprzez dostrojenie funkcji maskowania]
źródło