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()。我們還可以有選擇地輸人一個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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章