精华内容
下载资源
问答
  • 在CIELab颜色空间下使用八方向Sobel算子实现边缘检测,借鉴了论文,效果还不错。就是计算时间很长。之前设置不要积分的,csdn自动设置的这么积分,如果需要可以联系我。wyg19970408@gmail.com。
  • sobel算子

    万次阅读 2017-04-14 09:38:24
    网上查了很资料,都说sobel算子是用来检测边缘的,分别给了两个方向上的卷积核,然后说明做法,就说这就是sobel算子。对于我个人来说,还有很不明白的地方,所以理清下思路。   #2,边缘、边界和sobel算子 这个...
    #1,个人理解
    

    网上查了很多资料,都说sobel算子是用来检测边缘的,分别给了两个方向上的卷积核,然后说明做法,就说这就是sobel算子。对于我个人来说,还有很多不明白的地方,所以理清下思路。

     

    #2,边缘、边界和sobel算子

    这个可以自己去google或者百度找定义,边缘边界不一样,两者没有必然联系也并非毫无联系。因为现实世界的三维空间映射到图像显示的二维空间中会丢失很多信息,也会添进来一部分类似光照、场景等的干扰,所以并不能完全给边缘和边界的关系下一个定义。对图像而言,我们一般是要找出它的边缘,因为这是图像处理中使用较多的一个特征。何为边缘?图像处理中认为,灰度值变化剧烈的地方就是边缘。那么如何判断灰度值变化?如何度量“剧烈”?sobel算子就对这些问题做了自己的规范,而且命名为sobel算子,就是对一副图像的输入到输出边缘信息的整个处理过程。

    sobel算子的思想,Sobel算子认为,邻域的像素对当前像素产生的影响不是等价的,所以距离不同的像素具有不同的权值,对算子结果产生的影响也不同。一般来说,距离越远,产生的影响越小。

    sobel算子的原理,对传进来的图像像素做卷积,卷积的实质是在求梯度值,或者说给了一个加权平均,其中权值就是所谓的卷积核;然后对生成的新像素灰度值做阈值运算,以此来确定边缘信息。

     

    #3,卷积核及计算方法

    若Gx是对原图x方向上的卷积,Gy是对原图y方向上的卷积;

    原图中的作用点像素值通过卷积之后为:

    可以简化成:

    比如,一下矩阵为原图中的像素点矩阵,带入上式中的A,最终得到的G或者|G|是下面(x,y)处的像素值,可以自己去搜索下卷积的含义来理解。

     

    另外,卷积核也可以旋转,用与查找不与x,y轴平行或垂直的方向上的边缘。

     

    #4,阈值处理及平滑处理

    得到像素点新的像素值之后,给定一个阈值就可以得到sobel算子计算出的图像边缘了。

    通常,为了消除噪声对sobel算子的影响,会增加一个预处理的操作,主要是做平滑处理降低噪声的影响。

     

    #5,matlab代码实现

    Gx=[1.0 2.0 1.0;0.0 0.0 0.0;-1.0 -2.0 -1.0];
    Gy=[-1.0 0.0 1.0;-2.0 0.0 2.0;-1.0 0.0 1.0];
    
    img=imread('qiaoba.jpg');
    image=rgb2gray(img);
    
    subplot(2,2,1);   
    imshow(image);    
    title('原图');   
    
    gradx=conv2(Gx,image,'full');  
    gradx=abs(gradx); %计算图像的sobel垂直梯度  
    subplot(2,2,2);  
    imshow(gradx,[]);  
    title('图像的sobel垂直梯度');
    
    grady=conv2(Gy,image,'full');  
    grady=abs(grady); %计算图像的sobel水平梯度  
    subplot(2,2,3);  
    imshow(grady,[]);  
    title('图像的sobel水平梯度');  
    
    grad=gradx+grady;  %得到图像的sobel梯度  
    subplot(2,2,4);  
    imshow(grad,[]);  
    title('图像的sobel梯度'); 
    

    处理结果:

    #5,c++代码实现

     来源:http://blog.csdn.net/dcrmg/article/details/52280768

    #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;
    }
    

     

    #6,sobel算子的优缺点

    优点:计算简单,速度很快;

    缺点:计算方向单一,对复杂纹理的情况显得乏力;

      直接用阈值来判断边缘点欠合理解释,会造成较多的噪声点误判。

    展开全文
  • Sobel算子

    千次阅读 2019-05-30 20:03:30
    Soble边缘检测算法比较简,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,但是很实际应用的场合,sobel边缘却是首选,尤其是对效率要求较高,而对细纹理不太关心的时候。Soble边缘检测...

    原理 

           Soble边缘检测算法比较简,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,但是很多实际应用的场合,sobel边缘却是首选,尤其是对效率要求较高,而对细纹理不太关心的时候。Soble边缘检测通常带有方向性,可以只检测竖直边缘或垂直边缘或都检测。
            算子使用两个3*3的矩阵(图1)算子使用两个3*3的矩阵(图1)去和原始图片作卷积,分别得到横向G(x)和纵向G(y)的梯度值,如果梯度值大于某一个阈值,则认为该点为边缘点。

    Sobel卷积因子

    sobel算子的可分离性 

    我们先来看一个3阶的Sobel边缘检测算子,如下所示:

                                           

     

          显然,3*3的Sobel算子是可分离的,它是Sobel算子的标准形式,可以利用二项式展开式的系数构建窗口更大的Sobel算子,如5*5、7*7等,但是有一点必须要注意,窗口大小要为奇数。

     

            该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像灰度值,其公式如下: 

    图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小。

    可用以下公式计算梯度方向。

    在以上例子中,如果以上的角度Θ等于零,即代表图像该处拥有纵向边缘,左方较右方暗。

           除此之外:由于基础核具有关于0,0,0所在的中轴正负对称,所以通过对基础核的旋转,和图像做卷积,可以获得灰度图的边缘图,同时消去旋转角方向+180°上的边缘,迭代多个方向即可消去多个方向的边缘,但是为消去的边缘会加倍。

    基础核 0°         (顺时针为正)旋转 45°          90°                   135°                      180°                        225°                       270° 

                    

           当内核大小为 3 时, 以上Sobel内核可能产生比较明显的误差(毕竟,Sobel算子只是求取了导数的近似值)。 为解决这一问题,OpenCV提供了 Scharr 函数,但该函数仅作用于大小为3的内核。该函数的运算与Sobel函数一样快,但结果却更加精确,其内核为:

    这里写图片描述

     C++ API

     
    void Sobel(InputArray src, OutputArray dst, int ddepth,
               int dx, int dy, int ksize = 3,
               double scale = 1, double delta = 0,
               int borderType = BORDER_DEFAULT );
    
    @param src 为输入图像,填Mat类型即可。
    @param dst 即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
    @param ddepth 输出图像的深度。
    若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F 
    若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F 
    若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F 
    若src.depth() = CV_64F, 取ddepth = -1/CV_64F
    @param dx x 方向上的差分阶数。
    @param dy y方向上的差分阶数。
    @param ksize 有默认值3,表示Sobel核的大小;必须取1,3,5或7。
    @param scale 计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
    @param delta 表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
    @param borderType 边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息。
    

    梯度计算 

                       

    写了一段代码验证一下,首先创建一个5*7的图像,并且创建一个滤波器,使用filter2D进行卷积,dst为输出图像。

    	Mat A = (Mat_<uchar>(5, 8) <<
    		20, 30, 15, 3, 16, 9, 56, 8,
    		21, 33, 66, 15, 3, 9, 75, 12,
    		11, 0, 3, 2, 6, 12, 35, 54,
    		15, 26, 35, 15, 12, 3, 33, 87,
    		21, 14, 12, 95, 13, 2, 15, 46);
    	Mat kernel = (Mat_<char>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
    	Mat dst;
    	//copyMakeBorder(A, B, 1, 1, 1, 1, BORDER_CONSTANT,0);
    	filter2D(A, dst, CV_16S, kernel);
    	convertScaleAbs(dst, dst);
    	dst = dst(Rect(1, 1, dst.cols - 2, dst.rows - 2));
    
    	waitKey();

     红色方框中对应右边的输出结果。

    测试代码 

    Mat src = imread("test.png", IMREAD_GRAYSCALE);
    imshow("src", src);
    
    //使用高斯滤波消除噪声 
    GaussianBlur(src, src, Size(3, 3), 0.1);
    
    Mat sobelX;
    Sobel(src, sobelX, CV_16S, 1, 0);	//求X方向梯度  
    convertScaleAbs(q_matsobelX, q_matsobelX);
    imshow("效果图窗口X", sobelX);
    
    Mat sobelY;
    Sobel(src, sobelY, CV_16S, 0, 1);//求Y方向梯度
    convertScaleAbs(sobelY, sobelY);
    imshow("效果图窗口Y", sobelY);
    //合并梯度
    Mat dst;
    addWeighted(sobelX, 0.5, sobelY, 0.5, 0, dst);
    imshow("合并效果图窗口", dst);
    
    waitKey();

     

     

     参考:

    https://blog.csdn.net/yanmy2012/article/details/8110316

    https://blog.csdn.net/weixin_41695564/article/details/79965676

     

    展开全文
  • Sobel算子杂谈

    2021-01-06 11:33:52
    Sobel算子是一种数字图像处理种常用的边缘提取算子,更基础内容可以参考冈萨雷斯版《数字图像处理》,这里不做过多介绍。 基本概念 Sobel算子包括检测水平变化的卷积核GxG_xGx​和检测垂直方向变化的卷积核GyG_yGy...

    Sobel算子杂谈

    Sobel算子是一种数字图像处理中常用的边缘提取算子,更多基础内容可以参考冈萨雷斯版《数字图像处理》,这里不做过多介绍。

    基本概念

    Sobel算子包括检测水平变化的卷积核GxG_x和检测垂直方向变化的卷积核GyG_y。比如当选择大小为3的核时:

    Gx=G_x=[101202101]\left[\begin{matrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \\ \end{matrix}\right],
    Gy=G_y=[121000121]\left[\begin{matrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \\ \end{matrix}\right]

    核分离

    Sobel算子是一种典型的可分核,比如:

    Gx=G_x=[101202101]=\left[\begin{matrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \\ \end{matrix}\right]=[121]×\left[\begin{matrix} 1\\ 2\\ 1\\ \end{matrix}\right]\times[101]\left[\begin{matrix} -1 & 0 & 1 \\ \end{matrix}\right]

    Gy=G_y=[121000121]=\left[\begin{matrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \\ \end{matrix}\right]=[101]×\left[\begin{matrix} -1\\ 0\\ 1\\ \end{matrix}\right]\times[121]\left[\begin{matrix} 1 & 2 & 1 \\ \end{matrix}\right]

    以下为可分离核耗时对比测试代码,其中省略了耗时分析部分

    import cv2
    import numpy as np
    
    
    org_img = cv2.imread("Lena.jpg", 0)
    sobel_y = np.mat([[-1, -2, -1], [0, 0, 0], [1, 2, 1]], dtype=np.float32)
    sobel_col = np.mat([[-1], [0], [1]], dtype=np.float32)
    sobel_row = np.mat([1, 2, 1], dtype=np.float32)
    sobel_img1 = cv2.filter2D(org_img, cv2.CV_16S, sobel_y)
    soble_img2 = cv2.sepFilter2D(org_img, cv2.CV_16S, sobel_row, sobel_col)
    # sobel_img3 = cv2.Sobel(org_img, cv2.CV_16S, 0, 1, 3)
    

    经1000次循环测试,使用完整核并通过filter2D()函数计算的平均耗时为0.24ms,使用分离核通过sepfilter2D()函数计算的平均耗时为0.16ms,与理论值3/2符合较好。

    Sobel()函数

    在OpenCV中有单独使用Sobel滤波的函数:其函数签名为

    C++:

    void cv::Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double	delta = 0, int borderType = BORDER_DEFAULT 
    )
    

    Python:

    dst	= cv.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])
    

    需要注意的参数:当ksize = 1时表示使用3×13\times11×31\times3大小的核,当ksize = FILTER_SCHARR (-1)时表示使用3×33\times3的Scharr核,该核比3×33\times3的Sobel核表现更佳。

    性能测试

    综上,目前实现Sobel滤波有filter2D()sepFilter2D()Sobel()三个函数,其实现方式略有不同。因此下面对性能进行测试。

    Python性能表现

    经测试发现在Python环境中,三个函数的表现受输出图像的ddepth影响很大,具体测试结果如下表格,单位为毫秒

    ddepth filter2D() sepFilter2D() Sobel()
    CV_8U 0.17 1.1 1.1
    CV_16S 0.26 0.22 0.34
    CV_32F 0.98 0.68 0.68

    C++实现

    C++实现代码如下,同样省去了测试部分代码

    #include "opencv2\opencv.hpp"
    using namespace cv;
    
    int main()
    {
    	Mat img = imread("Lena.jpg", 0);
    	Mat sobel_img1 = Mat::zeros(img.size(), img.type());
    	Mat sobel_img2 = Mat::zeros(img.size(), img.type());
    	Mat sobel_img3 = Mat::zeros(img.size(), img.type());
    	
        Mat sobel_y= (Mat_<float>(3, 3) << -1,-2,-1,0,0,0,1,2,1);
    	float data1[3][1] = { {-1},{0},{1} };
    	Mat col = Mat(3, 1, CV_32F, data1);
    	float data2[3] = { 1,2,1 };
    	Mat row = Mat(1, 3, CV_32F, &data2);
    
    	filter2D(img, sobel_img1, CV_16S, sobel_y);
    	Sobel(img, sobel_img2, CV_16S, 0, 1, 3);
    	sepFilter2D(img, sobel_img3, CV_16S, row, col);
    	return 0;
    }
    

    在Release模式默认-O2优化,对三种函数的耗时统计如下

    ddepth filter2D() sepFilter2D() Sobel()
    CV_8U 0.17 1.07 1.17
    CV_16S 0.16 0.09 0.09
    CV_32F 0.86 0.45 0.49

    Sobel()函数源码分析

    以下浅尝辄止的探讨一下Sobel()函数的具体实现,OpenCV版本号为4.3.0,函数目录为modules>imgproc>src>deriv.cpp,这里推荐一篇详细的介绍文章

    源码贴在下面,以供参考。

    void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,
                    int ksize, double scale, double delta, int borderType )
    {
        CV_INSTRUMENT_REGION();
    
        CV_Assert(!_src.empty());
    
        int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
        if (ddepth < 0)
            ddepth = sdepth;
        int dtype = CV_MAKE_TYPE(ddepth, cn);
        _dst.create( _src.size(), dtype );
    
        int ktype = std::max(CV_32F, std::max(ddepth, sdepth));
    
        Mat kx, ky;
        getDerivKernels( kx, ky, dx, dy, ksize, false, ktype );
        if( scale != 1 )
        {
            // usually the smoothing part is the slowest to compute,
            // so try to scale it instead of the faster differentiating part
            if( dx == 0 )
                kx *= scale;
            else
                ky *= scale;
        }
    
        CV_OCL_RUN(ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 && ksize == 3 &&
                   (size_t)_src.rows() > ky.total() && (size_t)_src.cols() > kx.total(),
                   ocl_sepFilter3x3_8UC1(_src, _dst, ddepth, kx, ky, delta, borderType));
    
        CV_OCL_RUN(ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() > kx.total() && (size_t)_src.cols() > kx.total(),
                   ocl_sepFilter2D(_src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType))
    
        Mat src = _src.getMat();
        Mat dst = _dst.getMat();
    
        Point ofs;
        Size wsz(src.cols, src.rows);
        if(!(borderType & BORDER_ISOLATED))
            src.locateROI( wsz, ofs );
    
        CALL_HAL(sobel, cv_hal_sobel, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, ddepth, cn,
                 ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, dx, dy, ksize, scale, delta, borderType&~BORDER_ISOLATED);
    
        CV_OVX_RUN(true,
                   openvx_sobel(src, dst, dx, dy, ksize, scale, delta, borderType))
    
        //CV_IPP_RUN_FAST(ipp_Deriv(src, dst, dx, dy, ksize, scale, delta, borderType));
    
        sepFilter2D(src, dst, ddepth, kx, ky, Point(-1, -1), delta, borderType );
    }
    

    这里不做逐行分析,从上到下可以依次看到:异常判断->创建dst->创建滤波核->判断缩放系数scale->判断是否使用OpenCL加速->Array转换Mat->根据borderType调整图像大小->调用sepFilter2D()

    Sobel()会最终调用sepFilter2D()执行滤波操作,从C++的耗时统计中也可以看到两者的耗时几乎一致。而sepFilter2D()最终会调用hal::sepFilter2D(),这样就进入了openCV的HAL部分,因此就不再班门弄斧深入探讨了。

    展开全文
  • 边缘检测sobel算子

    2017-10-20 18:10:00
    网上查了很资料,都说sobel算子是用来检测边缘的,分别给了两个方向上的卷积核,然后说明做法,就说这就是sobel算子。对于我个人来说,还有很不明白的地方,所以理清下思路。 #2,边缘、边界和sobel算子 这...

    sobel算子 - sophia_hxw - 博客园 http://www.cnblogs.com/sophia-hxw/p/6088035.html

    #1,个人理解

    网上查了很多资料,都说sobel算子是用来检测边缘的,分别给了两个方向上的卷积核,然后说明做法,就说这就是sobel算子。对于我个人来说,还有很多不明白的地方,所以理清下思路。

     

    #2,边缘、边界和sobel算子

    这个可以自己去google或者百度找定义,边缘边界不一样,两者没有必然联系也并非毫无联系。因为现实世界的三维空间映射到图像显示的二维空间中会丢失很多信息,也会添进来一部分类似光照、场景等的干扰,所以并不能完全给边缘和边界的关系下一个定义。对图像而言,我们一般是要找出它的边缘,因为这是图像处理中使用较多的一个特征。何为边缘?图像处理中认为,灰度值变化剧烈的地方就是边缘。那么如何判断灰度值变化?如何度量“剧烈”?sobel算子就对这些问题做了自己的规范,而且命名为sobel算子,就是对一副图像的输入到输出边缘信息的整个处理过程。

    sobel算子的思想,Sobel算子认为,邻域的像素对当前像素产生的影响不是等价的,所以距离不同的像素具有不同的权值,对算子结果产生的影响也不同。一般来说,距离越远,产生的影响越小。

    sobel算子的原理,对传进来的图像像素做卷积,卷积的实质是在求梯度值,或者说给了一个加权平均,其中权值就是所谓的卷积核;然后对生成的新像素灰度值做阈值运算,以此来确定边缘信息。

     

    #3,卷积核及计算方法

    若Gx是对原图x方向上的卷积,Gy是对原图y方向上的卷积;

    原图中的作用点像素值通过卷积之后为:

    可以简化成:

    比如,一下矩阵为原图中的像素点矩阵,带入上式中的A,最终得到的G或者|G|是下面(x,y)处的像素值,可以自己去搜索下卷积的含义来理解。

     

    另外,卷积核也可以旋转,用与查找不与x,y轴平行或垂直的方向上的边缘。

     

    #4,阈值处理及平滑处理

    得到像素点新的像素值之后,给定一个阈值就可以得到sobel算子计算出的图像边缘了。

    通常,为了消除噪声对sobel算子的影响,会增加一个预处理的操作,主要是做平滑处理降低噪声的影响。

     

    #5,matlab代码实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    Gx=[1.0 2.0 1.0;0.0 0.0 0.0;-1.0 -2.0 -1.0];
    Gy=[-1.0 0.0 1.0;-2.0 0.0 2.0;-1.0 0.0 1.0];
     
    img=imread('qiaoba.jpg');
    image=rgb2gray(img);
     
    subplot(2,2,1);  
    imshow(image);   
    title('原图');  
     
    gradx=conv2(Gx,image,'full'); 
    gradx=abs(gradx); %计算图像的sobel垂直梯度 
    subplot(2,2,2); 
    imshow(gradx,[]); 
    title('图像的sobel垂直梯度');
     
    grady=conv2(Gy,image,'full'); 
    grady=abs(grady); %计算图像的sobel水平梯度 
    subplot(2,2,3); 
    imshow(grady,[]); 
    title('图像的sobel水平梯度'); 
     
    grad=gradx+grady;  %得到图像的sobel梯度 
    subplot(2,2,4); 
    imshow(grad,[]); 
    title('图像的sobel梯度');

    处理结果:

    #5,c++代码实现

     来源:http://blog.csdn.net/dcrmg/article/details/52280768

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    #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;
    }

     

    #6,sobel算子的优缺点

    优点:计算简单,速度很快;

    缺点:计算方向单一,对复杂纹理的情况显得乏力;

      直接用阈值来判断边缘点欠合理解释,会造成较多的噪声点误判。

    转载于:https://www.cnblogs.com/wxl845235800/p/7700887.html

    展开全文
  • Sobel算子的理解

    万次阅读 多人点赞 2017-11-30 12:41:11
    sobel算子主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测。 原理 算子使用两个33的矩阵(图1)算子使用两个33的矩阵(图1)去和原始图片作卷积,分别得到横向G(x)和纵向G(y)的梯度...
  • 在这里,说下Sobel算子进行边缘检测和上一篇博文中提到的“利用图像在水平和垂直方向上的差分运算对图像进行边缘检测”的相似处和区别! 1 sobel算子也同上一篇博文中提到的边缘检测算法一样,在水平和垂直方向两个...
  • 修改经典sobel算法 经典的不足: 只采用了两个方向模板(水平和垂直),导致检测出来的边缘有断裂现象 认为凡是灰度新值>=阈值的像素点都是边缘点,不合理。 因为对于纹理复杂的车辆图像,边缘检测效果很差,...
  • 提出了一种HSV空间中颜色距离的定义,并根据定义的颜色距离,用Sobel梯度算子的变形对彩色图像在颜色分量上求出分割边界。使用了颜色信息,又结合了空间信息。实验证明该方法具有较高的颜色分辨能力和通用性,能得到...
  • 前面使用很方法来进行边缘分析,其实都有两个缺点: 没有充分利用边缘的梯度方向。 最后输出的二值图,只是简单地截断的阈值处理,如果阈值过大会损失很信息...主要有四步流流程:高斯平滑、Sobel计算、非极大...
  • 计算机图像梯度是很重要特征提取的关键步骤之一,OpenCV提供了两个非常重要的计算梯度函数Sobel与Scharr 对于图像边缘部分,梯度值会比较大,对于图像的平坦区域梯度值一般比较小 Sobel梯度 Sobel梯度算子可以计算X...
  • 一、图像边缘检测算子有很,下面介绍经典的几种:Roberts、Sobel、Prewitt、Kirsch、Laplacian。 1. Roberts(正负45度方向的梯度) 2. Sobel(x,y方向的梯度) 3. Prewitt(x,y方向的梯度) ...
  • Sobel算子检测方法对灰度渐变和噪声较的图像处理效果较好,sobel算子对边缘定位不是很准确,图像的边缘不止一个像素;当对精度要求不是很高时,是一种较为常用的边缘检测方法。是带有方向的。在opencv-python中,...
  • 因为由于车牌区域的边缘是以垂直边缘为主,一般的背景区域不会有密集的垂直边缘,如果求取全方向上的边缘的话,在背景比较复杂的时候,背景区域也会存在更边缘,带来干扰。以Canny算子为例,虽然检测效果看起来更...
  • 图像处理—算子

    2019-09-28 13:09:41
    Robert算子是一阶微分算子,比较简单,计算量小,对细节反应敏感。 Sobel算子是基于一阶导数的微分算子,其中引入了类似局部平均的运算,对于...Canny算子比较复杂,既要计算方向的梯度,又要记录方向和大小,...
  • 1.边缘检测 常见的边缘检测算法: Roberts边缘检测算子 一种斜向偏差分的梯度计算方法,梯度的方向与边缘的...Sobel算子通常对灰度渐变和噪声较的图像处理的比较好。 Prewitt边缘算子 Prewitt算子不仅能检测...
  • 分析传统Sobel算子的不足, 并利用分数阶微分对其进行改进, 提出基于分数阶微分和Sobel算子的四方向边缘检测模型对图像进行梯度运算;运用最大类间差分法自适应选取阈值实现二值化完成边缘检测。实验结果表明, 与传统...
  • DE2-115 学习例子

    2016-04-27 10:53:00
    又快过去一个月了,最近很少写东西,...最主要我把sobel 算子改成方向了,其实也是避免和别人一样,再说sobel算子每个人的版本也不同,这也是为什么那么多人都可以拿相同的东西去发表论文,突然觉得自己非要把实...
  • 基于单方向梯度算子,Robert算子,Sobel算子,Pwitter算子,Laplacian算子,多方向模板,LoG算子编写的matlab增强程序。 原理 1.单方向梯度算子 用差分定义一元函数f(x)一阶微分: 水平方向梯度计算方法为: 垂直...
  • 自学opencv日记,day8

    2019-09-14 21:00:13
    什么是方向导数和梯度 Ps:实战中多用近似计算,用加减计算代替乘除计算以满足对速度的要求。 API: Sobel代码: #include<opencv2/opencv.hpp> #include<iostream> using namespace cv; using ...
  • 好的检测- 算法能够尽可能地标识出图像中的实际边缘。 好的定位- 标识出的边缘要尽可能与实际图像中的实际边缘尽可能接近。 最小响应- 图像中的边缘只能标识一次,并且可能存在的图像噪声不应标识为边缘。 3....
  • 边缘检测算子比较

    2021-02-28 21:25:58
    对灰度渐变和噪声较的图像处理效果比较好,Sobel算子对边缘定位比较准确。 Kirsch: 对灰度渐变和噪声较的图像处理效果较好。 Prewitt: 对灰度渐变和噪声较的图像处理效果较好。 Laplacian: 对图像中...
  • OpenCV Canny边缘检测

    千次阅读 2018-08-13 10:21:53
    目标 在本章中,我们将了解 Canny边缘检测的概念 OpenCV函数用于:cv2.Canny() 理论 ...Canny边缘检测是一种流行的边缘检测算法。它是由约翰·F·坎尼于...然后在水平方向和垂直方向Sobel核对平滑后的图像进行...
  • 然后使用Sobel核在水平和垂直方向上对平滑的图像进行滤波,以在水平方向(Gx)和垂直方向(Gy)上获得一阶导数。从这两张图片中,我们可以找到每个像素的边缘渐变和方向。 渐变方向始终垂直于边缘。将其舍入为代表垂直,...
  • 本文和下文用于开源项目OpenCV的车牌识别的学习... sobel滤波 ,车牌分割的一个重要特征是车牌中的垂直边缘比较,为了提取垂直边缘,采用sobel一阶垂直方向导数;c. 阈值化处理,应用一个OSTU法自动获取阈值滤波...
  • sobel算子计算梯度值和梯度方向 梯度方向一般和边界垂直;梯度方向归为四大类(水平、垂直、对角线)。 3、非极大值抑制 遍历图像,去除所有不是边界的点。实现方法是遍历每个像素,判断每个像素是否是周围具有相同...
  • 因此提出一种基于结构元素尺度的数学形态学边缘检测算法,先用尺度结构元素交替顺序形态开-闭平滑图像以去噪,再用结构元素对不同方向的边缘进行提取,最后把各方向边缘融合得到图像边缘。实验结果表明,...
  • 19.1.2计算图像梯度对平滑后的图像使用Sobel算子计算水平方向和竖直方向的一阶导数(图像梯度)(Gx和Gy)。根据得到的这两幅梯度图(Gx和Gy)找到边界的梯度和方向,公式如下:梯度的方向一般总是与边界垂直。梯度...

空空如也

空空如也

1 2 3 4
收藏数 76
精华内容 30
关键字:

多方向sobel