Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different result with OPENCV C and C++ API (Border Interpolation difference)

I have performed Closing morphological operation and I am getting different result with the C and C++ API (OpenCV 2.4.2)

Input:

input

With OpenCV 'C':

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

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

With 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 );

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

As you can see, the C++ API yields an output with White/Gray border color. Hence, the results are different for both of these APIs.

I have tried different borderType with the C++ API but it always yields the same result.

How can I get the same output as C API in C++? I need it because it affects the detected contours

Thanks in advance

like image 487
VP. Avatar asked Aug 01 '12 22:08

VP.


2 Answers

Thank you everybody for answering this question. I have found my error. I am going to describe it in brief below. Hope it helps others facing this problem.

1) I had executed the C and C++ commands on a ROI image. Apparently, the way OpenCV 'C' and 'C++' API treat ROI is different.

2) In 'C', a ROI is treated as a completely different image. Hence, when you execute functions such as cvSmooth, cvDilate, etc, where one needs to mentions border Pixel extrapolation methods, the 'C' API does not refer back to the original image for pixels beyond left/right/top/bottom most pixel. It actually interpolates the pixel values according to the method you mentioned.

3) But in 'C++', I have found that it always refers back to the original image for pixels beyond left/right/top/bottom most pixel. Hence, the border pixel extrapolation method mentioned doesn't affect your output if there are pixels in the original image around your ROI.

I think it applies the order pixel extrapolation method to the original image instead of the ROI unlike the 'C' API. I don't know if this a bug; I haven't completely read the OpenCV 2.4.2 C++ API documentation. (Please correct me if I am wrong)

To claim my support, I have posted input/output images below:

Output for 'C' and C++ API:

INPUT:

input <--- input

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);

OUTPUT:

before_gauss <-- before_gauss

after_gauss <--- after_gauss

after_canny <--- after_canny

dilate <--- dilate

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 );

OUTPUT:

before_gauss <-- before_gauss

after_gauss

^^^^^ after_gauss (NOTE: the borders are no more completely black, they are grayish)

after_canny

^^^^^ after_canny

dilate

^^^^^ dilate

SOLUTION:

Create a separate ROI copy and use it for further analysis;

src_ROI.copyTo( new_src_ROI ); 

Use new_src_ROI for further analysis. If anyone has better solution, please post below

like image 64
VP. Avatar answered Oct 26 '22 10:10

VP.


The defaults are not the same between C and C++ - especially the structuring element. In C: the default structuring element is:

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

whereas in C++, the default structuring element is:

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

You should specify all fields(including the anchor) if you want the same results.

like image 20
go4sri Avatar answered Oct 26 '22 08:10

go4sri