Opencv中cvFilter2D卷积函数的计算过程分析
2018-01-14 16:31
288 查看
接上一篇,介绍了矩阵卷积的计算方法,我们选择了用0来补全,但是在Opencv中的CVFilter2D函数是用边缘拷贝的方式。
CvFilter2D函数
尝试
先上代码,
输出的结果
![](https://img-blog.csdn.net/20180114160755095?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI4NDY1OTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
为了不让数据有偶然性,所以卷积核很古怪,大家不要在意,我们只是要研究他的计算过程。
首先我们发现91 这个值就是 1*9+2*8+3*7+4*4+5*5+6*6-1*7-2*8-1*9=91。即对应的元素相乘后,求和。而且卷积核没有旋转180°
然后我们可以看到如果用我上一篇介绍的边缘用0补全,是得不到这个结果的,所以我们肯定Opencv不是用0补全。
那下面的问题就是Opencv到底是怎么补全的
问号里面该填什么
![](https://img-blog.csdn.net/20180114162633376?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI4NDY1OTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
???
![](https://img-blog.csdn.net/20180114162747794?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI4NDY1OTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
???
之后,我们就猜测是不是边缘复制,
![](https://img-blog.csdn.net/20180114162633376?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI4NDY1OTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
==========》
![](https://img-blog.csdn.net/20180114163317383?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzI4NDY1OTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
通过计算后发现,果然是这样。1*9+2*9+1*8+4*9+5*9+6*8-1*4-2*4-1*5=163
其他也逐一验证 。
结论:
1.Opencv中,卷积核不会进行180°的旋转
2.CvFilter2D是边缘拷贝,通过边缘拷贝补全矩阵进行计算。
CvFilter2D函数
void cvFilter2D( const CvArr* src, CvArr* dst, const CvMat* kernel, CvPoint anchor=cvPoint(-1,-1)); src 输入图像. dst 输出图像. kernel 卷积核, 单通道浮点矩阵. 如果想要应用不同的核于不同的通道,先用 cvSplit 函数分解图像到单个色彩通道上,然后单独处理。 anchor 核的锚点表示一个被滤波的点在核内的位置。 锚点应该处于核内部。缺省值 (-1,-1) 表示锚点在核中心。 函数 cvFilter2D 对图像进行线性滤波,支持 In-place 操作。当核运算部分超出输入图像时,函数从最近邻的图像内部象素差值得到边界外面的象素值。
尝试
先上代码,
#include<opencv2\opencv.hpp> using namespace cv; using namespace std; //打印 void ShowMat(CvMat *m) { int i, j; for (i = 0; i<m->rows; i++) { for (j = 0; j<m->cols; j++) { double ImgPixelVal = cvGetReal2D(m, i, j); cout << ImgPixelVal << " "; } cout << endl; } } int main() { //卷积核 float A[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, -1.0, -2.0, -1.0 }; float B[] = { 9,8,7, 4,5,6, 7,8,9 }; CvMat Ma = cvMat(3, 3, CV_32FC1, A);//核矩阵 cout << "卷积核" << endl; ShowMat(&Ma); cout << endl; CvMat Mb = cvMat(3, 3, CV_32FC1, B);//输入 //原矩阵 cout << "原矩阵" << endl; ShowMat(&Mb); cout << endl; CvMat *C = cvCreateMat(3, 3, CV_32FC1); cvFilter2D(&Mb, C, &Ma, cvPoint(1, 1)); //输出后 cout << "卷积后" << endl; ShowMat(C); cout << endl; }
输出的结果
为了不让数据有偶然性,所以卷积核很古怪,大家不要在意,我们只是要研究他的计算过程。
首先我们发现91 这个值就是 1*9+2*8+3*7+4*4+5*5+6*6-1*7-2*8-1*9=91。即对应的元素相乘后,求和。而且卷积核没有旋转180°
然后我们可以看到如果用我上一篇介绍的边缘用0补全,是得不到这个结果的,所以我们肯定Opencv不是用0补全。
那下面的问题就是Opencv到底是怎么补全的
问号里面该填什么
???
???
之后,我们就猜测是不是边缘复制,
==========》
通过计算后发现,果然是这样。1*9+2*9+1*8+4*9+5*9+6*8-1*4-2*4-1*5=163
其他也逐一验证 。
结论:
1.Opencv中,卷积核不会进行180°的旋转
2.CvFilter2D是边缘拷贝,通过边缘拷贝补全矩阵进行计算。
相关文章推荐
- 【流式计算】Twitter Storm源代码分析之Topology的执行过程
- 骰子在限制条件的计算过程分析
- Android窗口管理服务WindowManagerService计算Activity窗口大小的过程分析
- opencv 仿射变换 计算旋转矩阵源码分析
- Android6.0 WMS(五) WMS计算Activity窗口大小的过程分析(一)应用进程
- pspice学习笔记(7)--模拟电路分析计算基本过程
- PCA(主成分分析)的计算过程
- Android窗口管理服务WindowManagerService计算Activity窗口大小的过程分析
- python opencv入门 直方图计算、绘制、分析(22)
- Spark计算过程分析
- mapreduce源码分析作业提交、初始化、分配、计算过程之初始化篇
- 主成分分析PCA--计算过程
- Android窗口管理服务WindowManagerService计算窗口Z轴位置的过程分析
- Android窗口管理服务WindowManagerService计算窗口Z轴位置的过程分析
- 水文分析与计算——频率分析及洪水流量过程
- mapreduce源码分析作业提交、初始化、分配、计算过程之提交篇
- 云计算(二十二)- 分析MapReduce执行过程
- Spark计算过程分析
- OLAP如何实现数据的聚合计算-分析过程
- win7 64位下自行编译OpenCV2.4.10+CUDA toolkit 5.5的整个过程以及需要注意的问题(opencv+cuda并行计算元素的使用)