2012-08-01 6 views
6

ja przeprowadziliśmy Zamknięcie operacji morfologicznej i otrzymuję inny wynik z API C i C++ (OpenCV 2.4.2)inny wynik z OpenCV C i C++ API (różnica Border interpolacja)

Wejście:

input http://i48.tinypic.com/35jm9n5.png

z OpenCV 'C':

//Set ROI 
//Perform Gaussian smoothing 
//Perform Canny edge analysis 
cvMorphologyEx(src, dst, temp, Mat(), MORPH_CLOSE, 5); 

WYNIK: http://i47.tinypic.com/33e0yfb.png

Z OpenCV C++

//Set ROI 
//Perform Gaussian smoothing 
//Perform Canny edge analysis 
cv::morphologyEx(src, dst, cv::MORPH_CLOSE, cv::Mat(), cv::Point(-1,-1), 5); 

WYNIK: http://i50.tinypic.com/i5vxjo.png

Jak widać, C++ API plony wyjście z biały/szary kolor obramowania. W związku z tym wyniki są różne dla obu tych interfejsów API.

Próbowałem różnych borderType z C++ API, ale zawsze daje taki sam wynik.

Jak uzyskać ten sam wynik co C API w C++? Muszę, bo to wpływa na wykryte kontury

góry dzięki

+0

Czy możesz dołączyć oryginalny obraz? –

+0

@ HåvardGeithus: Input: http://i47.tinypic.com/9kthzm.png; Obraz wejściowy jest sprytnym wyjściem krawędzi, jak pokazano. –

Odpowiedz

5

Dziękuję wszystkim za odpowiedź na to pytanie. Znalazłem mój błąd. Opiszę to krótko poniżej. Mam nadzieję, że pomoże to innym stawić czoła temu problemowi.

1) Wykonałem polecenia C i C++ na obrazie ROI. Wygląda na to, że sposób w jaki OpenCV "C" i "C++" traktuje ROI jest inny.

2) W "C" ROI jest traktowane jako zupełnie inny obraz. W związku z tym, gdy wykonuje się takie funkcje, jak cvSmooth, cvDilate itp., W których należy podać graniczne metody ekstrapolacji pikseli, interfejs API "C" nie odwołuje się do oryginalnego obrazu dla piksli poza lewym/prawym/górnym/na dole większości pikseli.W rzeczywistości interpoluje wartości pikseli zgodnie ze wspomnianą metodą.

3) Ale w "C++", stwierdziłem, że zawsze odnosi się do oryginalnego obrazu dla pikseli poza lewym/prawym/górnym/na dole większości pikseli. Dlatego wspomniana metoda ekstrapolacji pikseli obramowania nie ma wpływu na wynik, jeśli na oryginalnym obrazie wokół wskaźnika ROI znajdują się piksele.

Myślę, że stosuje się metodę ekstrapolacji pikseli zamówienia do oryginalnego obrazu zamiast ROI, w przeciwieństwie do API "C". Nie wiem, czy to błąd; Nie do końca przeczytałem dokumentację API OpenCV 2.4.2 C++. (Proszę mnie poprawić, jeśli się mylę)

Aby odebrać moje poparcie, jakie pisał obrazów wejściowych/wyjściowych poniżej:

wyjście do 'C' i C++ API:

INPUT:

input http://i48.tinypic.com/35jm9n5.png < --- wejście

OpenCV 'C' API:

IplImage *src = cvLoadImage("input.png", 0); 
cvSetImageROI(src, cvRect(33,19,250,110)); 
cvSaveImage("before_gauss.png", src); 
cvSmooth(src, src, CV_GAUSSIAN); 
cvSaveImage("after_gauss.png", src); 
IplConvKernel *element = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_RECT); 
cvCanny(src, src, 140, 40); 
cvSaveImage("after_canny.png", src); 
cvDilate(src, src, element, 5); 
cvSaveImage("dilate.png", src); 

wyjściowych:

before_gauss http://i45.tinypic.com/345lybm.png < - before_gauss

after_gauss http://i45.tinypic.com/2rg1jm0.png < --- after_gauss

after_canny http://i46.tinypic.com/2ymhyqw.png < --- after_canny

dilate http://i48.tinypic.com/5u4ec1.png < --- rozszerzają

OpenCV 'C++' API:

cv::Mat src = cv::imread("input.png", 0); 
cv::Mat src_ROI = src(cv::Rect(33,19,250,110)); 
cv::imwrite("before_gauss.png", src_ROI); 
cv::GaussianBlur(src_ROI, src_ROI, cv::Size(3,3),0); 
cv::imwrite("after_gauss.png", src_ROI); 
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3), cv::Point(1,1)); 
cv::Canny(src_ROI, src_ROI, 140, 40); 
cv::imwrite("after_canny.png", src_ROI); 
cv::dilate(src_ROI, src_ROI, element, cv::Point(1,1), 5); 
cv::imwrite("dilate.png", src_ROI); 

WYJŚCIE:

before_gauss http://i45.tinypic.com/345lybm.png < - before_gauss

after_gauss http://i50.tinypic.com/28gxzrb.png

^^^^^ after_gauss (Uwaga: Granice nie są bardziej całkowicie czarne, są szarawe)

after_canny http://i45.tinypic.com/2la7ecp.png

^^^^^ after_canny

dilate http://i50.tinypic.com/jhqxbm.png

^^^^^ Jednokładność

ROZWIĄZANIE:

Stwórz osobną kopię ROI i używać go do dalszej analizy;

src_ROI.copyTo(new_src_ROI); 

Użyj new_src_ROI do dalszej analizy. Jeśli ktoś ma lepsze rozwiązanie, opublikuj poniżej:

0

domyślne nie są takie same między C i C++ - zwłaszcza element strukturę. w C: element domyślną strukturę jest:

cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_RECT)

natomiast w C++, element domyślny strukturę jest:

getStructuringElement(MORPH_RECT, Size(1+iterations*2,1+iterations*2));

Należy określić wszystkie pola (łącznie z kotwicą), jeśli chcą takich samych rezultatów.

+0

Element strukturyzacji był także moją pierwszą myślą. –

+0

@ go4sri: Tym razem skonstruowałem element strukturyzacji jako cv :: getStructuringElement (cv :: MORPH_RECT, cv :: Size (3, 3), cv :: Point (1,1)); i nadal otrzymuję inny wynik: http://i45.tinypic.com/2j4x47q.png; następnie próbowałem tylko rozszerzenia Dylatacja: http: //i48.tinypic.com/10o20ky.png; Jak widać, z każdej strony jest biała ramka. To nie powinno być prawda? Próbowałem zmienić borderType, ale zawsze daje ten sam wynik: –

+0

@ HåvardGeithus: Morfologiczne zamknięcie: cv :: morfologiaEx (src, src, cv :: MORPH_CLOSE, structuringElement, cv :: Point (1, 1), 5); –

0

Zapoznaj się z tym sample code z dokumentacji OpenCV v2.4.2. Możesz również sprawdzić, czy korzystasz z detektora krawędzi Canny: this code. Miejmy nadzieję, że pomoże Ci to wyśledzić błąd :)

Należy również pamiętać, że zamknięcie morfologiczne jest operatorem idepotentnym, więc można go stosować wiele razy bez zmiany wyniku poza początkową aplikację.