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

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

问题描述

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

  Mat myfilter2d(Mat input,Mat filter){

Mat dst = input 。克隆();
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 for(int j = 0 - (filter.cols / 2); j float filtertotal = 0;
for(int k = 0; k for(int l = 0; l if(i + k> = 0&& i + k< input.rows&& j + 1> = 0&& j + 1< input.cols){//不尝试处理离开地图endge的像素
float a = input.at (i + k,j + 1);
float b = filter.at< float>(k,l);
float product = a * b;
filtertotal + = product;
}
}
}
//为这个像素过滤所有处理,写入到dst
st.at< uchar>(i +(filter.rows / 2 ),j +(filter.cols / 2))= filtertotal;

}
}
return dst;
}

任何人看到我的实现有什么错误? (除了很慢)



这是我的执行:

  cvtColor (src,src_grey,CV_BGR2GRAY); 
Mat dst = myfilter2d(src_grey,filter);
imshow(myfilter2d,dst);
filter2D(src_grey,dst2,-1,filter);
imshow(filters2d,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答案我添加了这个代码:

  //标准化内核,所以其sum = 1 
标量mysum = sum );
dst = dst / mysum [0]; //确保它不是0
dst = dst * -1; // show negetive

和filter2d效果更好。某些过滤器会提供完全匹配,而其他过滤器(如Sobel)则会失败。



我接近实际的算法,但还没有。

解决方案

我认为这个问题可能是一个尺度:如果你的输入图像是一个8位图像,大多数时间卷积将产生溢出最大值255的值。



在你的实现中,它看起来像是你获得了环绕的值,但是大多数OpenCV函数通过覆盖到最大(或最小)值来处理溢出。这就解释了为什么OpenCV函数的大部分输出都是白色的,以及为什么你在输出中也得到了同心形状。

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



例如,而不是此过滤器(sum = 10):

  1 1 1 
1 2 1
1 1 1

尝试此过滤器(sum = 1):

  0.1 0.1 0.1 
0.1 0.2 0.1
0.1 0.1 0.1


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() << "\n";
cout << " input data successfully found.  Rows:" << input.rows << " cols:" << input.cols << " channels:" << input.channels() << "\n";

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)

Here is my execution:

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

Here is my kernel:

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}
            };

And here are the (substantially different) results:

Thoughts, anyone?

EDIT: 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

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?

解决方案

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.

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.

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):

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

1 1 1
1 2 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天全站免登陆