python - C++ 中的 OpenCV 拉普拉斯输出不包括负值,但在 Python 中不包括
问题描述
C++
在中执行相同的拉普拉斯运算Python
似乎会产生不同的结果。值得注意的是,该C++
变体不会在结果矩阵中报告负斜率。
我正在使用(C++):
Laplacian(img.clone(), img, CV_16S, 1, 1, 0, BORDER_DEFAULT);
和(Python):
img = cv2.Laplacian(img, ddepth=cv2.CV_16S, ksize=1, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
通过将 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();
}
然后我可以将这些值与Numpy
.
cpp = np.loadtxt("./cpp.csv", delimiter=',')
print("python lap min:", np.min(img))
print("c++ lap min:", np.min(cpp))
此输出显示 CPP 代码未记录负值:
python lap min: -133 c++ lap min: 0.0
那么这里发生了什么?我肯定犯了某种错误,因为如果图像亮度值不是静态的,那么在某个地方的拉普拉斯变换中肯定有负值。
图片来源
每个测试用例的源图像是 1920x1080 全彩 PNG 图像,具有明显的明暗区域。我正在使用月亮的照片。图像在拉普拉斯变换之前转换为 CV_8UC1。
严格打字
我已明确告知C++
要使用默认隐式签名的类型存储数据int16_t
,而不仅仅是int
. 这种类型与拉普拉斯存储矩阵 ( CV_16S
) 的输出相匹配。将显式“签名”添加到“int16_t”会产生相同的结果。我的理解是该at
功能需要uchar
键入类似于此 SO answer。 这就是我错了!!!
版本说明
Python OpenCV 版本:4.1.1(或 4.4.0,见编辑部分)
C++ OpenCV 版本:3.4.1(或 4.4.0,见编辑部分)
这些版本(3.4.1和4.1.1)的文档显示两者之间没有明显差异。
类似问题
C++
和之间的拉普拉斯变体Python
在 SO 上似乎很常见,但对此没有任何用处。我读:
编辑 - 升级 C++ OpenCV 库
我OpenCV
从 git 构建了 v.4.4,并C++
使用pkg-config --cflags --libs opencv4
. 同样的错误仍然存在。(cv2.getBuildInformation()
说 Python 也在运行 4.4)。
Edit2 - Git 问题的上下文:
我在 github repo ( here ) 上发现了一个类似的问题,其中的解决方案是将 Laplacian 结果存储为新的Mat
。我的原始代码使用Laplacian(img.clone(), img, ...)
应该在适当的位置产生矩阵的“深拷贝” img
,避免了 OP 报告的问题。无论如何,我用一个独特的矩阵测试了我的代码,Laplacian(outputimg, img, ...)
结果没有看到任何变化。
Edit3 - 概括问题
我处理了原始代码,这次用 Sobel 和自定义filter2D
过滤器替换了拉普拉斯过滤器。观察到相同的结果,Python
产生良好的值而C++
没有。
Edit4 - 回答后清理
由于这是一个简单的打字错误,我已经删除了大部分无关信息。这使得我最初的尝试可读,但很明显它们最终没有用。
解决方案
您的 C++ 实现正在调用Mat::at<uchar>
,这意味着“将此位置的数据解释为uchar
(ie uint8_t
)”,但您的数据当然是short
(ie int16
),而不是uchar
. 从上的文档中Mat::at
,请注意它们指定:
如果矩阵是类型,
CV_16S
则使用Mat.at<short>(y,x)
.
推荐阅读
- linux - 如何确定数组元素(字符串)的内容是否包含另一个变量的字符串 - awk 命令:匹配或 ~/../?
- javascript - Amchart 将背景图像添加到 XYChart
- azure-functions - Azure Function 应用程序在开发机器上立即停止
- javascript - 最后添加的项目不显示栏
- graphql - 如何转换带有突变的graphql查询的获取请求?
- php - 如何在 postgresql 中使用 bcrypt 重新散列我的用户密码而不在 php 中迭代它们?
- excel - Excel VBA - Mac 上的访问控制
- unity3d - 检查克隆是否等于原始事物 Unity
- javascript - 我无法在js中使用reduce获取对象a的数组b
- java - 如何将 ArrayList 转换为 JSON 对象以便能够在 Java 中遍历它?