OpenCV 结果在 Debug / Release 和其他机器上变化

OpenCV result changes between Debug / Release and on other machine

我有一个程序试图检测图像上的矩形对象(即太阳能组件)。为此,我将 c++ 与 opencv 3 和 Visual Studio 2015 Update 1 结合使用。

通常我的程序使用 GaussianBlur -> morphologyEx -> Canny -> HoughLines -> findContours-> approxPolyDP .因为,我在寻找最佳参数时遇到问题,我尝试 运行 许多参数组合以获得最佳参数设置。

我遇到的问题是我在 "Debug in Visual Studio"、"Debug by using the generated .exe"、"Release in Visual Studio"、"Release by using the generated .exe" 之间得到不同的结果。此外,运行在其他机器上运行 .exe 文件再次改变了结果。

运行同一台机器上相同设置的程序不会改变结果(即它似乎是确定性的)。程序中也没有并发(除了我不知道的opencv中有一些)。

知道为什么不同设置之间存在如此巨大的不匹配吗(在一种设置中以 99% 的准确度检测太阳能模块的参数组合在另一种设置中根本检测不到模块)?

编辑:

我尝试创建一个最小工作示例(见下文),其中包含代码,直到我得到第一个不匹配(以后可能会有更多不匹配)。我试图初始化我找到的每个变量。

标识符paramterset是一个对象的实例,它包含我为找到最佳值而修改的所有参数。我检查了这些参数是否都已初始化,并且在 Debug 和 Relase 中是相同的。

使用这段代码,writeIntermediateResultImage创建的前3张图像(基本上只是使用opencv方法imwrite并且只指定图像存储的路径)是相同的,但形态图像不同(根据我发现的一些 online image comparer,相差 13.43%)。 一个区别是,在释放模式下,形态图像的左边缘和上边缘的某些像素是黑色的,但图像内部也存在其他差异。

编辑:似乎当 运行在发布模式下将代码与生成的 .exe 文件结合使用时,形态算法根本没有应用,但图像只是向左和向下移动,留下黑色顶部和底部的边缘。

编辑:这个转变似乎取决于运行正在使用的机器。在我的笔记本上,我有没有应用形态的移位,在我的桌面上应用了没有移位和黑边的形态。

void findSquares(const Mat& image, vector<vector<Point> >& squares, string srcName)
{
// 1) Get HSV channels
Mat firstStepResult(image.size(), CV_8U);
Mat hsvImage(image.size(), CV_8UC3);

// Convert to HSV space
cvtColor(image, hsvImage, CV_BGR2HSV);
writeIntermediateResultImage("HSV.jpg", hsvImage, srcName);

// Transform Value channel of HSV image to greyscale
Mat channel0Mat(image.size(), CV_8U);
Mat channel1Mat(image.size(), CV_8U);
Mat channel2Mat(image.size(), CV_8U);
Mat hsv_channels[3]{ channel0Mat, channel1Mat, channel2Mat };
split(hsvImage, hsv_channels);

firstStepResult = hsv_channels[parameterset.hsvChannel];
writeIntermediateResultImage("HSVChannelImage.jpg", firstStepResult, srcName);

// 2) Gaussian Denoising
Mat gaussImage = firstStepResult;
GaussianBlur(gaussImage, gaussImage, Size(parameterset.gaussKernelSize, parameterset.gaussKernelSize), 0, 0);
writeIntermediateResultImage("GaussianBlur.jpg", gaussImage, srcName);

// 3) Morphology
Mat morphologyImage = gaussImage;
morphologyEx(morphologyImage, morphologyImage, parameterset.morphologyOperator, Mat(parameterset.dilateKernelSize, parameterset.dilateKernelSize, 0), cv::Point(-1, -1), parameterset.numMorpholgies);
writeIntermediateResultImage("Morphology.jpg", morphologyImage, srcName);
}

我还检查了库路径,并在正确的编译模式下使用了正确的库(使用 [=53= 调试],不使用发布)。

我在我的代码中发现了错误,现在我在每个配置中得到了相同的结果。问题是使用形态学算子的那一行。

morphologyEx(morphologyImage, morphologyImage, parameterset.morphologyOperator, Mat(parameterset.dilateKernelSize, parameterset.dilateKernelSize, 0), cv::Point(-1, -1), parameterset.numMorpholgies);

尽管创建的 Mat 对象 (Mat(parameterset.dilateKernelSize, parameterset.dilateKernelSize, 0)) 在 Debug 中作为结构元素工作,但在 Release 中它有点搞砸了一切。

正在使用

getStructuringElement(MORPH_RECT, Size(parameterset.dilateKernelSize, parameterset.dilateKernelSize))

因为结构元素起到了作用。