cvFilter2D了解和使用

来源:互联网 发布:python idle mac下载 编辑:程序博客网 时间:2024/06/08 17:12
cvFilter2D()函数接口void cvFilter2D(  const CvArr* src,  CvArr* dst, const CvMat* kernel, CvPoint anchor=cvPoint(-1,-1) ); 
src 代表:输入图像
dst 代表:输出图像
kernel代表: 卷积核, 单通道浮点矩阵。 如果想要应用不同的核于不同的通道,先用 cvSplit 函数分解图像到单个色彩通道上,然后单独处理。
anchor 代表:核的锚点表示一个被滤波的点在核内的位置。 锚点应该处于核内部。默认值 (-1,-1) 表示锚点在核中心。
这里我们创建一个适当大小的矩阵,将系数连同源图像和目标图像一起传递给cvFilter2D()。我们还可以有选择地输人一个CvPoint指出核的中心位置,默认值(cvPoint (-1, -1))会设参考点为核的中心。如果定义了参考点,核的大小可以是偶数,否则只能是奇数。 
源图像src和目标图像dst大小应该相同,有些人可能认为考虑到卷积核的额外的长和宽,源图像src应该大于目标图像dst。但是在OpenCV里源图像src和目标图像dst的大小是可以一样的,因为在默认情况下,在卷积之前,OpenCV通过复制源图像src的边界创建了虚拟像素,这样以便于目标图像dst边界的像素可以被填充。 

这里我们所讨论的卷积核的系数应该是浮点类型的,这就意味着我们必须用CV_32F来初始化矩阵。

下面以《学习OpenCV 》第六章第二题为例进行距离
2、可分核。利用行[ (1/16,2/16,1/16),(2/16,4/16,2/16),1/16,2/16,1/16)]和在中间的参考点创建一个3*3的高斯核。

a:在一幅图像上运行此核并且显示结果。

b:   对a中的卷积矩阵进行可分核处理,并再次显示。

#include <iostream>#include <opencv2/opencv.hpp>#include <opencv2/highgui.hpp>using namespace std;using namespace cv;int main(int argc, const char * argv[]) {    /*1、加载一幅灰度图像*/    const char filename[] = "/Users/linwang/Downloads/30.png";    IplImage * Img = cvLoadImage(filename,CV_LOAD_IMAGE_GRAYSCALE);    /*2、缩小一倍*/    IplImage *out = cvCreateImage(cvSize(Img->width/2,Img->height/2), Img->depth, Img->nChannels);    cvResize(Img, out);        /*3、构造卷积矩阵,生成卷积核*/    float k1[9] = {0.0625,      0.0625 * 2,   0.0625,                   0.0625 * 2,  0.0625 * 4,   0.0625 * 2,                   0.0625,      0.0625 * 2,   0.0625};    CvMat kernel1 = cvMat(3, 3, CV_32FC1,k1);    cout<<kernel1.rows<<" -> "<<kernel1.cols<<" -> "<<kernel1.step<<" -> "<<endl;    for(int i = 0;i<kernel1.rows;i++)    {        float *ptr1 = kernel1.data.fl + i * kernel1.rows;        for (int j = 0; j<kernel1.cols; j++)        {            cout<<" "<<(*(ptr1 + j ));        }        cout<<endl;    }        /*4、制作一个交叉核(1/4,2/4,1/4),即一维行向量*/    float k2[3] = {0.25,0.5,0.25};    CvMat kernel2 = cvMat(1,3,CV_32FC1,k2);    cout<<kernel2.rows<<" -> "<<kernel2.cols<<" -> "<<kernel2.step<<" -> "<<endl;    for(int i = 0;i<kernel2.rows;i++)    {        float *ptr2 = kernel2.data.fl + i * kernel2.rows;        for (int j = 0; j<kernel2.cols; j++)        {            cout<<" "<<(*(ptr2 + j ));        }        cout<<endl;    }        /*5、制作一个下降核(1/4,2/4,1/4),即一维列向量*/    float k3[3] = {0.25,0.5,0.25};    CvMat kernel3 = cvMat(3,1,CV_32FC1,k3);    cout<<kernel3.rows<<" -> "<<kernel3.cols<<" -> "<<kernel3.step<<" -> "<<endl;    for(int i = 0;i<kernel3.rows;i++)    {        float *ptr3 = kernel3.data.fl + i * kernel3.rows;        for (int j = 0; j<kernel3.cols; j++)        {            cout<<" "<<(*(ptr3 + j ));        }        cout<<endl;    }            /*6、Clone一个dst图片*/    IplImage * dst1 = cvCloneImage(out);    cvSetZero(dst1);        IplImage * dst2 = cvCloneImage(out);    cvSetZero(dst2);        IplImage * dst3 = cvCloneImage(out);    cvSetZero(dst3);        IplImage * dst4 = cvCloneImage(out);    cvSetZero(dst4);    /*7、进行过滤*/    cvFilter2D(out, dst1, &kernel1);    cvFilter2D(out, dst2, &kernel2);    cvFilter2D(out, dst3, &kernel3);    cvFilter2D(dst2, dst4,&kernel3);  //相当于分别在水平和竖直方向进行滤波,分核再合并        /*8、图片显示*/    cvShowImage("1/2->Src", out);    cvShowImage("Filter1",  dst1);    cvShowImage("Filter2",  dst2);    cvShowImage("Filter3",  dst3);    cvShowImage("Filter34", dst4);    cvWaitKey(0);        cvReleaseImage(&Img);    cvReleaseImage(&dst1);    cvReleaseImage(&dst2);    cvReleaseImage(&dst3);    return 0;}