我注意到C ++中filter2D的OpenCV实现与相应内核的直接实现之间存在差异。我读过以下问题:
Opencv - how does the filter2D() method actually work?
该问题的作者试图获得filter2D函数的工作实现。他声称使用标准化版本的过滤器会产生正确的结果。我测试了他的假设,发现只有当所有系数都是正数时,归一化才能给出正确的答案。因此,可以使用filter2D函数成功实现平均滤波器。[我们仍然必须规范化内核]。
然而,对于具有负系数的滤波器,例如Sobel,Laplacian和任何边缘检测滤波器,情况并非如此。这个问题的作者遇到了和我一样的问题。
https://stackoverflow.com/users/2669614/bovaz
上面提到的用户回复了链接的问题。他声称如果内核系数的总和等于零,filter2D可能会修改它的实现。是这样的吗?为什么C +中filter2D的实现会给出直接实现的不同结果?我已经在Python中检查过filter2D,并且在C ++中直接实现相应的内核会产生相同的结果。
答案 0 :(得分:0)
主要是因为缩放和溢出问题。 filter2D的文档没有提及(至少我没有找到)溢出值是否被剪裁或适当缩放到最小 - 最大范围。 这在方向滤波器的情况下更为重要,其中系数是正的和负的并且在代数之后 功能' myfilter2D'在上面的链接上显示的不会扩展到最小 - 最大范围,应该是这种情况。
如果您可以发布示例代码,那么它将更容易提供帮助。
我的建议是将矩阵转换为浮点数(使用缩放)并执行代数运算,因为这会保留结果值,并且值不会因溢出或饱和而丢失。 im2double() - >"执行代数运算" - > im2uchar()用于显示
void im2uchar( Mat & src, Mat & dest){
double minVal, maxVal;
minMaxLoc(src, &minVal, &maxVal); //find minimum and maximum intensities
src.convertTo(dest, CV_8U, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal));
}
void im2float( Mat & src, Mat & dest){
double minVal, maxVal;
minMaxLoc(src, &minVal, &maxVal); //find minimum and maximum intensities
src.convertTo(dest, CV_32F, 1.0/(maxVal - minVal), -minVal * 1.0/(maxVal - minVal));
}