1. 程式人生 > >Sobel函式原理和應用

Sobel函式原理和應用

用來表達微分的最常用的操作是Sobel微分運算元。Sobel運算元包含任意階的微分以及融合偏導。

http://blog.csdn.net/tonyshengtan/article/details/43698711 這個帖關於Sobel的卷積運算元怎麼推導的有很詳細的介紹;

下面我們看一下函式原型

CVAPI(void) cvSobel( const CvArr* src, CvArr* dst,
                    int xorder, int yorder,
                    int aperture_size CV_DEFAULT(3));

其中高src和dst分別是輸入影象和輸出影象,xorder和yorder是求到的階數。通常只可能用到0,1,最多是2。值為0表示在這個方向上沒有求導。

aperture_size引數是方形濾波器的寬(或高)並且應該是奇數。目前,該引數支援1,3,5,7。

如果願影象src是八位的。為避免益處,目標影象的深度必須是IPL_DEPTH_16S。

Sobel導數有一個非常好的性質,即可以定義任意大小的核,並且這些核可以用快速且迭代的方式構造。大核對導數有更好的逼近,因為小核對噪聲更敏感。

Sobel導數並不是真正的導數,因為Sobel運算元定義於一個離散空間上。Sobel運算元真正表示的是多項式擬合,也就是說,x方向上的二階Sobel導數並不是真正的二階導數。它是對拋物線的擬合。

練習:用一個3✖️3的中孔,對影象執行並顯示一階x和y方向的導數,然後將中孔大小增加到5 ✖️ 5 , 9 ✖️ 9 描述結果;

#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/4.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);
    cvShowImage("1/2 Src", out);
    
    /*3、Sobel分別在x方向求導數*/
    IplImage *dst_x = cvCloneImage(out);
    cvSetZero(dst_x);
    cvSobel(out, dst_x, 1, 0, 3);
    cvShowImage("Sobel_X_3", dst_x);
    
    /*4、Sobel分別在y方向求導數*/
    IplImage *dst_y = cvCloneImage(out);
    cvSetZero(dst_y);
    cvSobel(out, dst_y, 0, 1, 5);
    cvShowImage("Sobel_Y_5", dst_y);
    
    /*5、Sobel在x和y同時求導數*/
    IplImage * dst_xy = cvCloneImage(out);
    cvSetZero(dst_xy);
    cvSobel(out, dst_xy, 1, 1 ,9);
    cvShowImage("Sobel_XY_9", dst_xy);
    
    cvWaitKey(0);
    cvReleaseImage(&Img);
    cvReleaseImage(&dst_x);
    cvReleaseImage(&dst_y);
    cvReleaseImage(&dst_xy);
    
    return 0;
}