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

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算子求水平方向的梯度图

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值