简体   繁体   English

与OPENCV C和C ++ API不同的结果(边界插值差异)

[英]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) 我已经执行了Closing形态学操作,我得到了与C和C ++ API不同的结果(OpenCV 2.4.2)

Input: 输入:

输入

With OpenCV 'C': 使用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 结果: http//i47.tinypic.com/33e0yfb.png

With Opencv C++ 使用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 结果: http//i50.tinypic.com/i5vxjo.png

As you can see, the C++ API yields an output with White/Gray border color. 如您所见,C ++ API产生具有白色/灰色边框颜色的输出。 Hence, the results are different for both of these APIs. 因此,这两种API的结果都不同。

I have tried different borderType with the C++ API but it always yields the same result. 我已尝试使用C ++ API使用不同的borderType,但它总是产生相同的结果。

How can I get the same output as C API in C++? 如何在C ++中获得与C API相同的输出? I need it because it affects the detected contours 我需要它,因为它会影响检测到的轮廓

Thanks in advance 提前致谢

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. 1)我在ROI图像上执行了C和C ++命令。 Apparently, the way OpenCV 'C' and 'C++' API treat ROI is different. 显然,OpenCV'C'和'C ++'API处理ROI的方式是不同的。

2) In 'C', a ROI is treated as a completely different image. 2)在'C'中,ROI被视为完全不同的图像。 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. 因此,当您执行cvSmooth,cvDilate等函数时,需要提及边界Pixel外推方法时,'C'API不会返回原始图像,以查看超出左/右/上/下最像素的像素。 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. 3)但是在'C ++'中,我发现它总是返回原始图像,用于超出左/右/上/下最像素的像素。 Hence, the border pixel extrapolation method mentioned doesn't affect your output if there are pixels in the original image around your ROI. 因此,如果ROI周围的原始图像中有像素,则提到的边框像素外推方法不会影响输出。

I think it applies the order pixel extrapolation method to the original image instead of the ROI unlike the 'C' API. 我认为与'C'API不同,它将顺序像素外推方法应用于原始图像而不是ROI。 I don't know if this a bug; 我不知道这是不是一个错误; I haven't completely read the OpenCV 2.4.2 C++ API documentation. 我还没有完全阅读OpenCV 2.4.2 C ++ API文档。 (Please correct me if I am wrong) (如果我错了,请纠正我)

To claim my support, I have posted input/output images below: 为了获得我的支持,我在下面发布了输入/输出图像:

Output for 'C' and C++ API: 'C'和C ++ API的输出:

INPUT: INPUT:

输入 <--- input <---输入

OpenCV 'C' API : 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: OUTPUT:

before_gauss <-- before_gauss < - before_gauss

after_gauss <--- after_gauss <--- after_gauss

after_canny <--- after_canny <--- after_canny

膨胀 <--- dilate <---扩张

OpenCV 'C++' API : 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: OUTPUT:

before_gauss <-- before_gauss < - before_gauss

after_gauss

^^^^^ after_gauss (NOTE: the borders are no more completely black, they are grayish) ^^^^^ after_gauss (注意:边框不再是完全黑色,它们是灰色的)

after_canny

^^^^^ after_canny ^^^^^ after_canny

膨胀

^^^^^ dilate ^^^^^ 扩张

SOLUTION: 解:

Create a separate ROI copy and use it for further analysis; 创建单独的ROI副本并将其用于进一步分析;

src_ROI.copyTo( new_src_ROI ); 

Use new_src_ROI for further analysis. 使用new_src_ROI进行进一步分析。 If anyone has better solution, please post below 如果有人有更好的解决方案,请在下面发布

The defaults are not the same between C and C++ - especially the structuring element. C和C ++之间的默认值不一样 - 尤其是结构元素。 In C: the default structuring element is: 在C中:默认的结构元素是:

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

whereas in C++, the default structuring element is: 而在C ++中,默认的结构元素是:

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

You should specify all fields(including the anchor) if you want the same results. 如果需要相同的结果,则应指定所有字段(包括锚点)。

Check out this sample code from the OpenCV v2.4.2 documentation. 查看OpenCV v2.4.2文档中的示例代码 You might also want to check this code for using the Canny edge detector. 您可能还需要检查此代码以使用Canny边缘检测器。 These will hopefully help you track down the error :) 这些将有助于您追踪错误:)

Also note that morphological closing is an idempotent operator, so it can be applied multiple times without changing the result beyond the initial application. 另请注意,形态闭合是幂等运算符,因此可以多次应用它而不会将结果更改为初始应用程序之外的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM