2013-02-22 11 views
13

Mogę używać funkcji FindChessboardCorners dla obrazów mniejszych niż 15 Mega pikseli takich jak 2k x 1.5k. jednak gdy używam go na obrazie z DSLR, rozdzielczość na 3700x5300, to nie działa.FindChessboardCorners nie może wykryć szachownicy na bardzo dużych obrazach dzięki obiektywowi o długiej ogniskowej.

Próbowałem użyć funkcji resize(), aby bezpośrednio zmniejszyć rozmiar obrazu, a następnie zadziała.

Oczywiście w kodzie źródłowym OpenCV jest jakiś kod lub błąd.

Czy możesz mi pomóc rozwiązać ten problem lub wskazać mi łatkę?

Znalazłem kogoś, kto opublikował podobny problem w 2006 roku, here, więc wygląda na to, że problem nadal występuje.

Kod użyłem jest jak

found = findChessboardCorners(viewGray, boardSize, ptvec, 
           CV_CALIB_CB_ADAPTIVE_THRESH + CV_CALIB_CB_FILTER_QUADS + CV_CALIB_CB_NORMALIZE_IMAGE + CV_CALIB_CB_FAST_CHECK); 

Aktualizacja

Właśnie tutaj wyjaśnienie. Myślę, że algorytm działa na dużą rozdzielczość obrazu, ale zawodzi, gdy szachownica zajmuje większą część obrazu. Na przykład, gdy używam soczewki o stałej długości 50 mm w tej samej pozycji kamery, FindChessboardCorners nigdy się nie zawiedzie. Po tym, jak zmienię ją na stałą soczewkę 100 mm, funkcja przestaje wykrywać wzór. Myślę, że odnosi się do proporcji lub ogniskowej.

Zdjęcie poniżej przedstawia wynik obiektywu 100 mm.

Aktualizacja 2

dodałem filtr wyostrzania do dużego obrazu, a zacznie rozwiązać problem.

pierwsze użyłem

//do a sharpen filter for the large resolution image 
if (viewGray.cols > 1500) 
{ 
    Mat temp ; 
    GaussianBlur(viewGray,temp, Size(0,0), 105) ; //hardcoded filter size, to be tested on 50 mm lens 
    addWeighted(viewGray, 1.8, temp, -0.8,0,viewGray) ; //hardcoded weight, to be tested. 
//imwrite("test"+ imageList[k][i], viewGray) ; 

} 

found = findChessboardCorners(viewGray, boardSize, ptvec, 
CV_CALIB_CB_ADAPTIVE_THRESH + CV_CALIB_CB_FILTER_QUADS + CV_CALIB_CB_NORMALIZE_IMAGE + CV_CALIB_CB_FAST_CHECK); 

Zamieszczone obraz:

jpg obraz w oryginalnej rozdzielczości 3744 x 5616, jeśli siła ta strona nawróconego, a następnie upewnij się, że używasz na odpowiedniej rozdzielczości .

A jpg image at original resolution 3744 x 5616, if this site force convert, then make sure you are using at the correct resolution.

+0

mógłbyś przesłać obraz? Czy powoduje to awarię lub po prostu zwraca wartość false? – Sassa

+0

@ Chris, przesłał zdjęcie –

+0

może być problem z obrazem? z jakiego rodzaju f-stopu korzystasz? może niska głębia ostrości może zmylić algorytm? spójrz na prawy dolny róg, jest nieco rozmazany, prawda? – Alex

Odpowiedz

21

Kilka punktów.

  1. Zmniejszenie rozmiaru, jak zauważyłeś, pomaga wykrywaczowi. To dlatego, że filtry wykrywania naroży używane w OpenCV do znalezienia narożników mają ustalony rozmiar, a rozmiar maski splotu może być zbyt mały, aby wykryć rogi - obraz w pełnym rozmiarze może faktycznie wyglądać "gładko" w tej skali, szczególnie gdzie jest lekko rozmazany. Jednak dzięki zmniejszeniu skali możesz wyrzucić dokładność lokalizacji narożnika.
  2. Z tego samego powodu pomaga również wyostrzanie. Jednak jest to również sprzeczne z dokładnością, ponieważ dodaje stronniczości do pozycji subpikselowych w rogach - nawet w idealnym przypadku bez szumu. Aby przekonać się, że tak jest, rozważ analog 1D: intensywność obrazu wokół rogu (w 1D, ostre przejście czarno-białe) wygląda idealnie jak sigmoidalna krzywizna (rampa z gładkimi narożnikami), a ty chcesz znaleźć lokalizację punktu przegięcia. Ostrzenie sprawia, że ​​krzywa jest bardziej stroma, co generalnie przesuwa położenie tego punktu.Sytuacja się pogarsza, gdy weźmie się pod uwagę, że ostrzenie generalnie wzmaga hałas.
  3. Najprawdopodobniej prawidłowym sposobem postępowania jest rozpoczynanie z mniejszą rozdzielczością (to znaczy zmniejszanie rozmiaru), a następnie skalowanie w górę odnalezionych narożników i używanie ich jako wstępnych oszacowań dla przebiegu cvFindCornersSubpix w pełnej rozdzielczości.
+1

Dzięki Franco, punkt 3 może mi pomóc. –

+1

Nie ma za co. Zauważyłem też na twoim zdjęciu, że cel wydaje się być przyklejony do jakiegoś rodzaju lub pianki lub listwy przypodłogowej. Gorąco polecam użycie czegoś bardziej sztywnego i płaskiego - szczególnie jeśli chce się skorzystać z pełnej rozdzielczości nowoczesnego sensora DSLR. Zobacz moją odpowiedź tutaj: http://stackoverflow.com/questions/12794876/how-to-verify-correctness-of-calibration-of-a-webcam –

+0

to specjalna płyta bazowa podobna do pianki, ale myślę, że jest ładna mieszkanie. Wypróbowałem twój punkt 3 sugestii i ma taki sam efekt jak filtr ostry, ale myślę, że wybieram twoją metodę, ponieważ spowodowałoby to szybsze znalezienie rzutu skorupy w niższej rozdzielczości, co ma kluczowe znaczenie dla wysokiej rozdzielczości. Problemem jest obiektyw o stałej ogniskowej 100 mm, którego używam, głębia ostrości na tym obiektywie jest zbyt krótka, co powoduje duże rozmycie, spróbowałbym użyć mniejszej tęczówki i sprawdzić, czy to się poprawia. –

1

Jeśli masz dostęp do źródła OpenCV i możesz je odbudować, być może możesz debugować zachowanie cvFindChessboardCorners.

Musisz #defineDEBUG_CHESSBOARD, a następnie będziesz mieć pomoc w zrozumieniu algorytmu.

Myślę, że OpenCV 2.4 ma taką możliwość (patrz na przykład https://github.com/Itseez/opencv/blob/2.4/modules/calib3d/src/calibinit.cpp).

Ponadto, nawet jeśli nie wydaje się mieć zastosowanie do przypadku, OpenCV doc daje wymóg celu kalibracji:

Note: Funkcja wymaga spacji (jak kwadrat grubości obramowanie, im szersze, tym lepsze) wokół planszy, aby wykrywanie było bardziej niezawodne w różnych środowiskach. W przeciwnym razie, jeśli nie ma granicy , a tło jest ciemne, zewnętrzne czarne kwadraty nie mogą być odpowiednio posegmentowane i dlatego algorytm grupowania i porządkowania nie działa.

http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#findchessboardcorners

+0

Ma białą obwódkę wokół szachownicy. Moja rada tutaj polega na użyciu próbki kalibracyjnej na https://github.com/Itseez/opencv/blob/master/samples/cpp/calibration.cpp. Pokaże Ci, kiedy zostaną znalezione rogi. Modyfikuję if (found) {... drawChessboardCorners (...);} i zawarłem blok inny, który jest po prostu cout-s, gdy nie zostaną znalezione rogi, dzięki czemu mogę śledzić obrazy w bardziej przyzwoity sposób. – rbaleksandar

Powiązane problemy