【学习opencv】Sobel算子原理及其实现

来源:互联网 发布:我的世界java手机版 编辑:程序博客网 时间:2024/06/01 10:38

Sobel算子原理及其实现

原理:

Sobel算子理论上是对图像进行一阶求导,而后为了方便计算设计了3x3的卷积模板。Sobel算子可以计算水平Gx和垂直方向Gy的梯度变换.

Gx方向的卷积模板:

Gy方向的卷积模板:

这里写图片描述

opencv还提供了一个scharr函数,比Sobel算子更为精准,也是3x3的模板。

这里写图片描述

实现:

实现较为简单,只需要遍历像素矩阵,对每一个3x3的像素矩阵与模板矩阵进行卷积运算即可,这里需要注意的是opencv自带的sobel算子在进行卷积运算时没有求绝对值,是对输出的图像做饱和处理,即大于255则输出为255,小于0则输出为0。

#include<iostream>#include<opencv2\opencv.hpp>using namespace std;using namespace cv;int main(){    Mat src = imread("facetest\\face0.jpg",0);    //GaussianBlur(src, src, Size(5,5), 0);    medianBlur(src,src,3);    Mat gx(src.size(),src.type(),Scalar(0));    Mat gy(src.size(), src.type(), Scalar(0));    Mat scharr_y(src.size(),src.type(),Scalar(0));    int Gx[9] = {-1,0,1,-2,0,2,-1,0,1};//gx方向的滤波模板    int Gy[9] = {1,2,1,0,0,0,-1,-2,-1};//gy方向的滤波模板    int scharrx [9]= {-3,0,3,-10,0,10,-3,0,3};    int scharry[9] = {-3,-10,-3,0,0,0,3,10,3};    if (!src.isContinuous())    {        cout << "不连续内存!!" << endl;        return 0;    }    //是连续内存用指针访问    uchar *px = gx.data;    uchar *py=gy.data;    uchar *s = src.data;    uchar *pscharr_y = scharr_y.data;    int sstep = src.step[0];    int xstep = gx.step[0];    int ystep = gy.step[0];    int scstep = scharr_y.step[0];    for (int i = 1; i <src. rows-1; i++)    {        for(int j=1;j<src.cols-1;j++)        {            py[i*ystep + j] = abs(Gy[0] * s[(i - 1)*sstep + j - 1]                 + Gy[1] * s[(i - 1)*sstep + j]                +Gy[2]*s[(i-1)*sstep+j+1]                +Gy[3]*s[i*sstep+j-1]                +Gy[4]*s[i*sstep+j]                +Gy[5]*s[i*sstep+j+1]                +Gy[6]*s[(i+1)*sstep+j-1]                +Gy[7] * s[(i + 1)*sstep + j ]                +Gy[8] * s[(i + 1)*sstep + j + 1]);            pscharr_y[i*scstep + j] = abs(scharry[0]*s[(i-1)*sstep+j-1]                + scharry[1] * s[(i - 1)*sstep + j]                + scharry[2] * s[(i - 1)*sstep + j + 1]                + scharry[3] * s[i*sstep + j - 1]                + scharry[4] * s[i*sstep + j]                + scharry[5] * s[i*sstep + j + 1]                + scharry[6] * s[(i + 1)*sstep + j - 1]                + scharry[7] * s[(i + 1)*sstep + j]                + scharry[8] * s[(i + 1)*sstep + j + 1]);        }    }    medianBlur(gy,gy,3);    medianBlur(scharr_y,scharr_y,3);    imshow("gy",gy);    imshow("scharr_y", scharr_y);    imshow("src",src);    waitKey(0);}

效果:

左边的图为用Sobel算子求水平方向的梯度图