Opencv - filter2D() 方法实际上是如何工作的? [英] Opencv - how does the filter2D() method actually work?

查看:15
本文介绍了Opencv - filter2D() 方法实际上是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我确实查找了 Filter2D 的源代码,但找不到.Visual c++ 也不能.这里有filter2D算法的专家吗?我知道 它应该如何工作,但不知道它实际上是如何工作的.我做了自己的filter2d()函数来测试东西,结果与opencvs filter2D()有很大的不同.这是我的代码:

I did look for the source code to Filter2D but could not find it. Neither could Visual c++. Are there any experts on the filter2D algorithm here? I know how it's supposed to work but not how it actually works. I made my own filter2d() function to test things, and the results are substantially different from opencvs filter2D(). Here's my code:

Mat myfilter2d(Mat input, Mat filter){

Mat dst = input.clone();
cout << " filter data successfully found.  Rows:" << filter.rows << " cols:" << filter.cols << " channels:" << filter.channels() << "
";
cout << " input data successfully found.  Rows:" << input.rows << " cols:" << input.cols << " channels:" << input.channels() << "
";

for (int i = 0-(filter.rows/2);i<input.rows-(filter.rows/2);i++){
    for (int j = 0-(filter.cols/2);j<input.cols-(filter.cols/2);j++){  //adding k and l to i and j will make up the difference and allow us to process the whole image
        float filtertotal = 0;
        for (int k = 0; k < filter.rows;k++){
            for (int l = 0; l < filter.rows;l++){
                if(i+k >= 0 && i+k < input.rows && j+l >= 0 && j+l < input.cols){  //don't try to process pixels off the endge of the map
                    float a = input.at<uchar>(i+k,j+l);
                    float b = filter.at<float>(k,l);
                    float product = a * b;
                    filtertotal += product;
                }
            }
        }
        //filter all proccessed for this pixel, write it to dst
        st.at<uchar>(i+(filter.rows/2),j+(filter.cols/2)) = filtertotal;

    }
}
return dst;
}

有人发现我的实现有什么问题吗?(除了慢)

Anybody see anything wrong with my implementation? (besides being slow)

这是我的执行:

  cvtColor(src,src_grey,CV_BGR2GRAY);
  Mat dst = myfilter2d(src_grey,filter);
  imshow("myfilter2d",dst);
  filter2D(src_grey,dst2,-1,filter);
  imshow("filter2d",dst2);

这是我的内核:

float megapixelarray[basesize][basesize] = {
            {1,1,-1,1,1},
            {1,1,-1,1,1},
            {1,1,1,1,1},
            {1,1,-1,1,1},
            {1,1,-1,1,1}
            };

以下是(完全不同的)结果:

有什么想法吗?

感谢 Brians 的回答,我添加了以下代码:

Thanks to Brians answer I added this code:

//normalize the kernel so its sum = 1
Scalar mysum = sum(dst);
dst = dst / mysum[0];   //make sure its not 0
dst = dst * -1;  //show negetive

filter2d 效果更好.某些过滤器提供了完全匹配,而其他过滤器,如 Sobel,惨遭失败.

and filter2d worked better. Certain filters give an exact match, and other filters, like the Sobel, fail miserably.

我正在接近实际的算法,但还没有.其他人有什么想法吗?

I'm getting close to the actual algorithm, but not there yet. Anyone else with any ideas?

推荐答案

我认为问题可能是规模问题:如果你的输入图像是 8 位图像,大多数时候卷积会产生溢出的值最大值 255.

I think the issue is probably one of scale: if your input image is an 8-bit image, most of the time the convolution will produce a value that overflows the maximum value 255.

在您的实现中,您似乎获得了环绕值,但大多数 OpenCV 函数通过限制为最大值(或最小值)来处理溢出.这就解释了为什么 OpenCV 函数的大部分输出都是白色的,以及为什么你的输出中也会出现同心形状.

In your implementation it looks like you are getting the wrapped-around value, but most OpenCV functions handle overflow by capping to the maximum (or minimum) value. That explains why most of the output of OpenCV's function is white, and also why you are getting concentric shapes in your output too.

为了解决这个问题,通过将每个值除以过滤器的总和来规范化您的 megapixelarray 过滤器(即确保过滤器值的总和为 1):

To account for this, normalize your megapixelarray filter by dividing every value by the entire sum of the filter (i.e. make sure that the sum of the filter values is 1):

例如,代替这个过滤器(sum = 10):

For example, instead of this filter (sum = 10):

1 1 1
1 2 1
1 1 1

试试这个过滤器(总和 = 1):

Try this filter (sum = 1):

0.1 0.1 0.1
0.1 0.2 0.1
0.1 0.1 0.1

这篇关于Opencv - filter2D() 方法实际上是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆