Chciałbym rozpoznać granice sześciokątnej płytki na zdjęciu, jak na zdjęciu poniżej:
Wydaje mi się, że standardowym podejściem do kwadratowej siatki jest najpierw wykrycie narożników (np. Sprytnych), a następnie wyodrębnienie najdłuższych linii za pomocą transformaty Hougha lub czegoś podobnego.
Nie wydaje się to optymalnym rozwiązaniem z kafelkami sześciokątnymi, ponieważ długość linii zewnętrznych jest krótsza i trudno jest oddzielić je od innych linii.
Czy istnieje algorytm pozwalający rozwiązać ten problem? Szczególnie fajnie byłoby mieć rozwiązanie w opencv, ale interesują mnie również ogólne pomysły.
aktualizacja:
Dzięki pythonowi i opencv mogłem otrzymać ten wynik:
Oto mój kod:
import cv2
import numpy as np
imgOrig = "test1";
img = cv2.imread(imgOrig+".jpg");
lap = cv2.Laplacian(img, cv2.IPL_DEPTH_32F, ksize = 3)
imgray = cv2.cvtColor(lap,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
size = img.shape
m = np.zeros(size, dtype=np.uint8)
for i, cnt in enumerate(contours):
if cv2.contourArea(cnt) >= 1:
color = (255,255,255)
cv2.drawContours(m, cnt, -1, color, -1)
cv2.imwrite(str(imgOrig)+"contours.jpg", m);
Laplacian obrazu wygląda następująco:
Spróbuję zoptymalizować parametry tego podejścia, a następnie spróbuję interpolować granice czterech sekcji.
Odpowiedzi:
1. podejście:
Skorzystaj z metod haartrainingowych OpenCV zgodnie z tym samouczkiem http://note.sonots.com/SciSoftware/haartraining.html - to powinno dać najlepsze wyniki, ale do tej pory nie pracowałem z haartrainingiem ...
Drugie podejście:
Sugerowałbym użycie metod „bezmarkerowego śledzenia” poszczególnych płytek planszy. Możesz to zaimplementować również za pomocą OpenCV ..
Przygotowanie
W tym celu potrzebujesz kilku zdjęć każdego rodzaju kafelka. Zrób zdjęcie wszystkich rodzajów kafelków (każdy jako jedno zdjęcie), z jednorodnym tłem z kafelka z widokiem z góry na środku obrazu.
Następnie użyj detektora cech (OpenCV ma do tego wiele algorytmów, ale SIFT / SURF są niewolnymi algorytmami; sugerowałbym użycie „SZYBKIEGO”), aby znaleźć wyraźne punkty na obrazach.
Użyj deskryptora funkcji, aby opisać funkcję znalezioną na obrazie (użyj np. „KRÓTKI”).
Wykrycie
Teraz możesz wykryć kafelki na obrazie, stosując te same algorytmy detektora / deskryptora funkcji do tego obrazu. Po nabyciu funkcji / deskryptorów możesz zastosować FlannBasedMatcher, aby znaleźć kafelki.
Oto przykład kodu / samouczek OpenCV: http://docs.opencv.org/doc/tutorials/features2d/feature_homography/feature_homography.html#feature-homography
Notatki
Metoda Matchera da ci tylko jedno dopasowanie i może mieć problemy, jeśli na planszy znajduje się więcej niż jeden kafelek tego typu. Możesz obejść ten problem, maskując tylko niektóre części obrazu wejściowego. Sugeruję to zrobić, używając współrzędnych pikseli wykrytych funkcji. Jeśli - w jakiś sposób - najpierw wykryjesz kontur i rozmiar kafelków, możesz z grubsza oszacować położenie i rozmiar kafelków na obrazie. Filtruj wykrytą listę funkcji (np. Tylko funkcje w promieniu x pikseli od oczekiwanego punktu środkowego płytki) przed dopasowaniem, a następnie użyj najsilniejszego dopasowania. W rezultacie otrzymasz dokładną pozycję kafelka na obrazie (w tym jego orientację). Jeśli wykrycie konturu mapy jest zbyt skomplikowane, możesz pozwolić użytkownikowi „wskazać” kafelki narożne, aby oznaczyć kontur ręcznie ...
Alternatywne podejście
Możesz także użyć tej metody, aby znaleźć tylko dowolny kafelek według jego obrysu. Narysuj przykładowy „schematyczny” obraz szarości płytki (sześciokąta) bez żadnego obrazu. Zauważ, że obszary „ciemne” i „jasne” na tym obrazie muszą być poprawne na schemacie, a nie tylko niektóre „linie”. Prawdopodobnie będziesz musiał z tym eksperymentować. Możesz spróbować uśrednić wiele zdjęć różnych kafelków, aby wygenerować „średni” obraz kafelka. Upewnij się, że narożniki są w tej samej pozycji (odpowiednio przesuń / skaluj obrazy) i wyostrz obraz po zakończeniu (wyraźne rogi / krawędzie powinny być widoczne) i w razie potrzeby dostosuj nieco kontrast.
źródło
Opiszę moje obecne podejście, które polega na wykorzystaniu zasad gry, przetwarzania obrazu i wykrywania funkcji.
Odpowiednie zasady gry
Realizacja
Najpierw używam transformacji Hougha, aby wyodrębnić pozycję planszy. Obraz źródłowy wygląda podobnie do ostatecznego obrazu, o którym mowa, ale z grubszymi liniami i przefiltrowałem mniejsze granice. Używam tylko wykrywania bardzo długich linii (rząd wielkości: około 60 procent szerokości / wysokości obrazu) i bardzo małego progu dla dopasowania linii. Patrzę też na linie na zewnętrznym 40 procentach obrazu i biorę medianę wykrytych linii na górze, dole, lewej i prawej stronie. Wynik pokazano na obrazku poniżej:
Potrzebuję tylko przybliżonego przybliżenia, więc jest w porządku. Odtąd badam tylko obraz wewnątrz linii Hougha, a także dodatkowe miejsce ze względu na niepewność transformacji Hougha.
Następnie używam wykrywania funkcji, jak zaproponował Stefan K. w swojej odpowiedzi, aby wykryć cechy obrazu, których gracze nie mogą zabrać, tj. Zamki, płytki lokalizacji i góry. Używam do tego algorytmu ORB w opencv-python i BruteForce-Hamming-Matcher (nie byłem jeszcze w stanie uruchomić FlannBased Matchera). ORB jest niezmienną skalą i rotacją. Aby wykryć wiele wystąpień tych samych funkcji (np. Zamków), podzieliłem obraz na części, które się pokrywają. Działa to dobrze, ponieważ rozdzielczość obrazu jest wystarczająco duża, a zdjęcie jest robione bezpośrednio z góry (nadal wymaga testów). To także trochę powolne. Wykrywanie kafelka lokalizacji (tawerny) pokazano jako przykład na obrazku poniżej
W tej chwili próbuję znaleźć transformację homografii, aby wyodrębnić dokładną pozycję i orientację wykrytych funkcji.
Mam nadzieję, że uda mi się zrekonstruować siatkę na podstawie tych informacji (położenie gór, zamku, kafelków lokalizacji, a w większości przypadków wody). Eksperymenty z prądami wyglądają obiecująco, choć trzeba dokładnie dopracować i odpowiednio przygotować obrazy obiektów.
źródło