Sobel算子

【摘要】本文将粗略的介绍Sobel算子。

  Sobel算子是像素图像边缘检测中最重要的算子之一,在机器学习、数字媒体、计算机视觉等信息科技领域起着举足轻重的作用。在技术上,它是一个离散的一阶差分算子,用来计算图像亮度函数的一阶梯度之近似值。在图像的任何一点使用此算子,将会产生该点对应的梯度矢量或是其法矢量。在边缘检测中,常用的一种模板是Sobel 算子。Sobel 算子有两个,一个是检测水平边缘的 ;另一个是检测垂直边缘的 。与Prewitt算子相比,Sobel算子对于像素的位置的影响做了加权,可以降低边缘模糊程度,因此效果更好。由于Sobel算子是滤波算子的形式,用于提取边缘,可以利用快速卷积函数, 简单有效,因此应用广泛。美中不足的是,Sobel算子并没有将图像的主体与背景严格地区分开来,换言之就是Sobel算子没有基于图像灰度进行处理,由于Sobel算子没有严格地模拟人的视觉生理特征,所以提取的图像轮廓有时并不能令人满意。 在观测一幅图像的时候,我们往往首先注意的是图像与背景不同的部分,正是这个部分将主体突出显示,基于该理论,我们给出了下面阈值化轮廓提取算法,该算法已在数学上证明当像素点满足正态分布时所求解是最优的。(百度百科)

【原理】

  对传入的图像像素进行卷积处理,卷积的实质是在求梯度值,或者说给了一个加权平均,其中权值就是所谓的卷积核;然后对生成的新像素灰度值做阈值运算,以此来确定边缘信息。算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。Gx及Gy分别代表经横向及纵向边缘检测的图像,其公式如图1:

        图1 Sobel Gx和Gy方向卷积核

 

原图中的作用点像素值通过卷积之后为,其公式如图2

                  

                      图2 梯度计算公式

可用以下公式计算梯度方向,其公式如图3

                  

                    图3 梯度计算公式  

 

【C++代码】

 

#include "core/core.hpp"   
#include "highgui/highgui.hpp"   
#include "imgproc/imgproc.hpp"   
#include "iostream" 
 
using namespace std;
using namespace cv;
 
int main(int argc, char *argv[])
{
    Mat image = imread("qiaoba.jpg", 0);
    Mat imageX = Mat::zeros(image.size(), CV_16SC1);
    Mat imageY = Mat::zeros(image.size(), CV_16SC1);
    Mat imageXY = Mat::zeros(image.size(), CV_16SC1);
    Mat imageX8UC;
    Mat imageY8UC;
    Mat imageXY8UC;
    if (!image.data)
    {
        return -1;
    }
    GaussianBlur(image, image, Size(3, 3), 0); //高斯滤波消除噪点 
    uchar *P = image.data;
    uchar *PX = imageX.data;
    uchar *PY = imageY.data;
    int step = image.step;
    int stepXY = imageX.step;
    for (int i = 1; i<image.rows - 1; i++)
    {
        for (int j = 1; j<image.cols - 1; j++)
        {
            //通过指针遍历图像上每一个像素 
            PX[i*imageX.step + j*(stepXY / step)] = abs(P[(i - 1)*step + j + 1] + P[i*step + j + 1] * 2 + P[(i + 1)*step + j + 1] - P[(i - 1)*step + j - 1] - P[i*step + j - 1] * 2 - P[(i + 1)*step + j - 1]);
            PY[i*imageX.step + j*(stepXY / step)] = abs(P[(i + 1)*step + j - 1] + P[(i + 1)*step + j] * 2 + P[(i + 1)*step + j + 1] - P[(i - 1)*step + j - 1] - P[(i - 1)*step + j] * 2 - P[(i - 1)*step + j + 1]);
        }
    }
    addWeighted(imageX, 0.5, imageY, 0.5, 0, imageXY);//融合X、Y方向   
    convertScaleAbs(imageX, imageX8UC);
    convertScaleAbs(imageY, imageY8UC);
    convertScaleAbs(imageXY, imageXY8UC);   //转换为8bit图像 
 
    Mat imageSobel;
    Sobel(image, imageSobel, CV_8UC1, 1, 1); //Opencv的Sobel函数 
 
    imshow("Source Image", image);
    imshow("X Direction", imageX8UC);
    imshow("Y Direction", imageY8UC);
    imshow("XY Direction", imageXY8UC);
    imshow("Opencv Soble", imageSobel);
    waitKey();
    return 0;
}
View Code

 

参考文章

http://www.cnblogs.com/sophia-hxw/p/6088035.html

https://baike.baidu.com/item/Sobel%E7%AE%97%E5%AD%90/11000092?fr=aladdin

posted @ 2018-03-26 14:51  扰扰  阅读(1441)  评论(0编辑  收藏  举报