Opencv CvInvoke.Canny()-在不同的计算机上提供不同的结果

Opencv CvInvoke.Canny()-在不同的计算机上提供不同的结果,opencv,image-processing,emgucv,opencvsharp,canny-operator,Opencv,Image Processing,Emgucv,Opencvsharp,Canny Operator,当尝试在完全相同的图像文件上执行一些二进制操作时,但在不同的计算机和显示器上,使用CvInvoke.Canny()方法时会得到不同的结果。 在调用此方法之前,我使用了几种操作方法,例如:CvInvoke.Threshold(),CvInvoke.core(),CvInvoke.deflate()等等。。。 所有这些的结果总是相等的。 就在我打电话的时候: UMat inputImageUMAT = new Image<Gray, byte>(inputImageBitmap).ToU

当尝试在完全相同的图像文件上执行一些二进制操作时,但在不同的计算机和显示器上,使用
CvInvoke.Canny()
方法时会得到不同的结果。
在调用此方法之前,我使用了几种操作方法,例如:
CvInvoke.Threshold()
CvInvoke.core()
CvInvoke.deflate()
等等。。。 所有这些的结果总是相等的。
就在我打电话的时候:

UMat inputImageUMAT = new Image<Gray, byte>(inputImageBitmap).ToUMat();
UMat imageUmat = new UMat();
CvInvoke.Threshold(imageInputUMAT, imageUmat, threshold, 255, 
Emgu.CV.CvEnum.ThresholdType.Binary);

// clear noises with Erode & Dilate:
CvInvoke.Erode(imageUmat, imageUmat, null, new Point(-1, -1), 1, 
BorderType.Constant, CvInvoke.MorphologyDefaultBorderValue);
CvInvoke.Dilate(imageUmat, imageUmat, null, new Point(-1, -1), 1, 
BorderType.Constant, CvInvoke.MorphologyDefaultBorderValue);

//use image pyr to remove noise:
UMat pyrDown = new UMat();
CvInvoke.PyrDown(imageUmat, pyrDown);
CvInvoke.PyrUp(pyrDown, imageUmat);

 // set cannyEdges to hold the outlines of the shapes detected in the image 
(according to threshold) 
UMat cannyEdges = new UMat();
CvInvoke.Canny(imageUmat, cannyEdges, threshold, threshold);
阈值210机器1的结果:
阈值210机器2的结果:
--两个结果之间有1个像素的差异

正常。
我不能说我已经100%地理解了这个问题的原因,但我确实让它在所有计算机之间保持稳定。
问题是,起初我使用静态方法
CvInvoke.Canny()
,并发送输入和输出
Umat
,它可能不知道原始图像是什么类型,然后(通过访问一些
windows
dll或优先级之类的东西),它导致每台计算机做出不同的决策,因此,不同的
Umat
翻译导致不同的结果。
(…可能)

但是
当我将输入图像加载到
image
中,并使用自己的
Canny
方法(以及其他方法)时,无论在哪台计算机上运行,一切都毫无疑问是稳定的
因此,工作代码是:

UMat inputImageUMAT = new Image<Gray, byte>(inputFileName).ToUMat();
Image<Gray, Byte> binaryImage = inputImageUMAT.ToImage<Gray,Byte>().ThresholdBinary(new Gray(threshold), new Gray(255));
binaryImage = binaryImage.Erode(1);
binaryImage = binaryImage.Dilate(1);
binaryImage = binaryImage.PyrDown();
binaryImage = binaryImage.PyrUp();
binaryImage = binaryImage.Canny(1, 0, 3, true);
UMat inputImageUMAT=新图像(inputFileName).ToUMat();
Image binaryImage=inputImageUMAT.ToImage().ThresholdBinary(新灰度(阈值),新灰度(255));
二进制图像=二进制图像侵蚀(1);
二进制图像=二进制图像。放大(1);
binaryImage=binaryImage.PyrDown();
binaryImage=binaryImage.PyrUp();
binaryImage=binaryImage.Canny(1,0,3,true);

我已经写信给EMGU的支持,下面是他们令人惊讶的答案:

我检查了你的代码,它正在使用UMat。这意味着代码将在可用时使用OpenCL(GPU)来加速处理,并在没有兼容OpenCL驱动程序/设备的工作站上使用CPU。
我怀疑OpenCL路径产生的结果与CPU路径略有不同。在调用代码中的任何Emgu CV函数之前,您是否可以执行以下命令,并检查这是否会使结果在所有机器上保持一致:

CvInvoke.UseOpenCL=false

上面的代码将禁用OpenCL并强制所有代码在其上运行 中央处理器


毫不奇怪,他们是对的当我将代码更改为:
CvInvoke.Canny(imageUmat,cannyEdges,threshold,threshold,3,true)时,它确实解决了这个问题-仍然存在差异。能否将代码限制为仅在保证相同的图像上调用CvInvoke.Canny(无
jpg
压缩,仅无损格式)使用diff向我们显示2个图像(&show us 2 images)?在同一台计算机上,输出是否也会从一次运行更改为另一次运行?不同的解码器实现可能会导致不同的结果。为了确保情况并非如此,我建议不要对输入文件使用任何压缩。因此,只需在调用
Canny
之前保存图像,并将结果输入两台机器上的
Canny
,将输出保存为图像并将其放入您的问题中。非常感谢@dmitriz。-我添加了文件,并跳过了所有的压缩过程-有什么不同的建议吗?
UMat inputImageUMAT = new Image<Gray, byte>(inputFileName).ToUMat();
Image<Gray, Byte> binaryImage = inputImageUMAT.ToImage<Gray,Byte>().ThresholdBinary(new Gray(threshold), new Gray(255));
binaryImage = binaryImage.Erode(1);
binaryImage = binaryImage.Dilate(1);
binaryImage = binaryImage.PyrDown();
binaryImage = binaryImage.PyrUp();
binaryImage = binaryImage.Canny(1, 0, 3, true);