简体   繁体   English

OpenCV 拉普拉斯算子 output 在 C++ 中排除负值,但在 ZA7F5F32326B963827111 中不排除

[英]OpenCV Laplacian output in C++ excludes negative values, but not in Python

Performing the same Laplacian operation in C++ and Python appears to produce different results.C++Python中执行相同的拉普拉斯运算似乎会产生不同的结果。 Notably, the C++ variant does not report negative slopes in the result matrix.值得注意的是, C++变体不会在结果矩阵中报告负斜率。

I am using (C++):我正在使用(C++):

Laplacian(img.clone(), img, CV_16S, 1, 1, 0, BORDER_DEFAULT);

and (Python):和(Python):

img = cv2.Laplacian(img, ddepth=cv2.CV_16S, ksize=1, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)

By processing the C++ data into a more friendly text format:通过将 C++ 数据处理成更友好的文本格式:

outfile.open("cpp.csv");
outfile.close();
for (size_t i = 0; i < img.size().width; i++) {
    outfile.open("cpp.csv", std::ios_base::app);
    for (size_t j = 0; j < img.size().height; j++) {
        outfile << (int16_t)img.at<uchar>(j, i);
        if (j < img.size().height - 1) {
            outfile << ",";
        }
    }
    outfile << std::endl;
    outfile.close();
}

I can then compare the values with Numpy .然后我可以将这些值与Numpy进行比较。

cpp = np.loadtxt("./cpp.csv", delimiter=',')
print("python lap min:", np.min(img))
print("c++    lap min:", np.min(cpp))

This output shows us that the CPP code is not recording negative values:这个 output 向我们展示了 CPP 代码没有记录负值:

 python lap min: -133 c++ lap min: 0.0

So what is happening here?那么这里发生了什么? Surely I have made some sort of error, because there must be negative values in a Laplacian transformation somewhere if the image luminosity values are not static.我肯定犯了某种错误,因为如果图像亮度值不是 static,那么在某个地方的拉普拉斯变换中肯定有负值。

Image Source图片来源

The source image for each test case is a 1920x1080 full color PNG image with distinct light and dark areas.每个测试用例的源图像是 1920x1080 全彩 PNG 图像,具有明显的明暗区域。 I'm using a photo of the moon.我正在使用月亮的照片。 The image is converted to CV_8UC1 prior to the Laplace transformation.图像在拉普拉斯变换之前转换为 CV_8UC1。

Strict Typing严格打字

I have explicitly told C++ to store data with the int16_t type, which is implicitly signed by default, rather than just an int .我已经明确告诉C++使用int16_t类型存储数据,该类型默认是隐式签名的,而不仅仅是一个int This typing matches the output from the Laplacian storage matrix ( CV_16S ).此类型匹配来自拉普拉斯存储矩阵 ( CV_16S ) 的 output。 Adding an explicit "signed" to "int16_t" produces the same result.将显式“签名”添加到“int16_t”会产生相同的结果。 My understanding is that the at function requires uchar typing similar to this SO answer .我的理解是, at function 需要uchar键入类似于此 SO 答案 This is where I was wrong!!!这就是我错了!!!

Version Note版本说明

Python OpenCV version: 4.1.1 (or 4.4.0, see edit section) Python OpenCV 版本:4.1.1(或 4.4.0,见编辑部分)

C++ OpenCV version: 3.4.1 (or 4.4.0, see edit section) C++ OpenCV 版本:3.4.1(或 4.4.0,见编辑部分)

The documentation for these versions ( 3.4.1 and 4.1.1 ) shows no appreciable difference between the two.这些版本( 3.4.14.1.1 )的文档显示两者之间没有明显差异。

Similar Questions类似的问题

Laplacian variation between C++ and Python appears common on SO, but nothing had anything useful for this. C++Python之间的拉普拉斯变体在 SO 上似乎很常见,但对此没有任何用处。 I read:我读:

Edit - Upgrading C++ OpenCV lib编辑 - 升级 C++ OpenCV 库

I built OpenCV v.4.4 from git, and compiled the C++ version of the code with pkg-config --cflags --libs opencv4 .我从 git 构建OpenCV v.4.4,并使用pkg-config --cflags --libs opencv4编译了C++版本的代码The same error persists.同样的错误仍然存在。 ( cv2.getBuildInformation() says the Python is running 4.4 as well). cv2.getBuildInformation()表示 Python 也在运行 4.4)。

Edit2 - context from a Git issue: Edit2 - 来自 Git 问题的上下文:

I found a similar issue on the github repo ( here ) where the solution was storing the Laplacian result as a new Mat .我在 github repo( here )上发现了一个类似的问题,其中解决方案是将 Laplacian 结果存储为新的Mat My original code uses Laplacian(img.clone(), img, ...) which should produce a "deep copy" of the img matrix in place, avoiding the problem reported by the OP.我的原始代码使用Laplacian(img.clone(), img, ...)应该在适当的位置产生img矩阵的“深拷贝”,避免 OP 报告的问题。 I tested my code with a unique matrix anyway Laplacian(outputimg, img, ...) and saw no change in results.无论如何,我用一个唯一的矩阵测试了我的代码Laplacian(outputimg, img, ...)并没有看到结果的变化。

Edit3 - Generalizing the problem Edit3 - 概括问题

I processed the original code, this time replacing the Laplacian filter with either a Sobel and a custom filter2D filter.我处理了原始代码,这次用 Sobel 和自定义filter2D过滤器替换了拉普拉斯过滤器。 The same result is observed, Python produces good values while C++ does not.观察到相同的结果, Python产生良好的值,而C++没有。

Edit4 - Post-answer cleanup Edit4 - 回答后清理

Since this was a simple typing error, I have crossed out most of the extraneous information.由于这是一个简单的打字错误,我已经删除了大部分无关信息。 This leaves it my original attempts readable, but it makes it obvious that they were not useful in the end.这使得我最初的尝试可读,但很明显它们最终没有用。

Your C++ implementation is calling Mat::at<uchar> which means "interpret the data at this location as uchar (ie uint8_t )" but your data is of course short (ie int16 ), not uchar .您的 C++ 实现正在调用Mat::at<uchar> ,这意味着“将此位置的数据解释为uchar (即uint8_t )”,但您的数据当然short (即int16 ),而不是uchar From the docs on Mat::at , note that they specify:Mat::at上的文档中,请注意它们指定:

If matrix is of type CV_16S then use Mat.at<short>(y,x) .如果矩阵是CV_16S类型,则使用Mat.at<short>(y,x)

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

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