当前位置:   article > 正文

[传统图像处理]边缘检测之----Sobel算子_sobel的作用

sobel的作用

一、作用:

sobel算子是图像边缘检测的最重要的算子之一。

Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。

二、原理:

Sobel算子输入的图像是灰度图,所以正常图片进行sobel算子提取边缘前,先要把图片转成灰度图。

边缘是指在图像上像素灰度变化最显著的地 方,边缘检测算子则利用图像边缘灰度的突变来检 测边缘。Sobel算子包含两组3×3的滤波器,分别对水平垂直方向上的边缘敏感。

水平方向和垂直方向的Sobel算子分别如下:

具体与图像的运算如下:

然后分别用这两个算子对输入图像进行卷积操作,得到x,y方向上各点的卷积结果,即垂直梯度Gx和水平梯度Gy。

然后作一个平方和运算:

或者:

如果某点梯度 G 大于某一阈值,则认为该点(x,y)为边缘点。

代码:

python:

  1. # coding=utf-8
  2. import cv2
  3. img = cv2.imread("D:/fangzi.jpg", 0)
  4. cv2.imshow('origin',img)
  5. #Sobel函数求完导数后会有负值,还有会大于255的值。而原图像是uint8,即8位无符号数,
  6. #所以Sobel建立的图像位数不够,会有截断。因此要使用16位有符号的数据类型,即cv2.CV_16S。
  7. x = cv2.Sobel(img, cv2.CV_16S, 1, 0)#垂直方向梯度
  8. y = cv2.Sobel(img, cv2.CV_16S, 0, 1)#水平方向梯度
  9. absX = cv2.convertScaleAbs(x) #转回原来的uint8格式,否则图像无法显示。
  10. absY = cv2.convertScaleAbs(y) #转回原来的uint8格式,否则图像无法显示。
  11. #两个方向的梯度加起来形成最终的梯度
  12. dst = cv2.addWeighted(absX, 1, absY, 1, 0)
  13. cv2.imshow("absX", absX)
  14. cv2.imshow("absY", absY)
  15. cv2.imshow("Result", dst)
  16. cv2.waitKey(0)

效果:

输入:

垂直方向:

水平方向:

最终结果:

这张图可以太简单了,我们来看看复杂的:

垂直方向:

水平方向:

最终结果:

c++:

  1. #include<opencv2/opencv.hpp>
  2. #include<iostream>
  3. using namespace std;
  4. using namespace cv;
  5. int main()
  6. {
  7. Mat m_img = imread("D:\\fangzi.jpg");
  8. Mat src(m_img.rows, m_img.cols, CV_8UC1, Scalar(0));
  9. cvtColor(m_img, src, CV_RGB2GRAY); //转成灰度图
  10. Mat dstImage(src.rows, src.cols, CV_8UC1, Scalar(0));
  11. for (int i = 1; i < src.rows - 1; i++)
  12. {
  13. for (int j = 1; j < src.cols - 1; j++)
  14. {
  15. dstImage.data[i*dstImage.step + j] = sqrt((src.data[(i - 1)*src.step + j + 1] //step 为图象像素行的实际宽度
  16. + 2 * src.data[i*src.step + j + 1]
  17. + src.data[(i + 1)*src.step + j + 1]
  18. - src.data[(i - 1)*src.step + j - 1] - 2 * src.data[i*src.step + j - 1]
  19. - src.data[(i + 1)*src.step + j - 1])*(src.data[(i - 1)*src.step + j + 1]
  20. + 2 * src.data[i*src.step + j + 1] + src.data[(i + 1)*src.step + j + 1]
  21. - src.data[(i - 1)*src.step + j - 1] - 2 * src.data[i*src.step + j - 1]
  22. - src.data[(i + 1)*src.step + j - 1]) + (src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]
  23. + src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]
  24. - 2 * src.data[(i + 1)*src.step + j]
  25. - src.data[(i + 1)*src.step + j + 1])* (src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]
  26. + src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]
  27. - 2 * src.data[(i + 1)*src.step + j]
  28. - src.data[(i + 1)*src.step + j + 1]));
  29. }
  30. }
  31. Mat grad_y(src.rows, src.cols, CV_8UC1, Scalar(0));
  32. {
  33. for (int i = 1; i < src.rows - 1; i++)
  34. {
  35. for (int j = 1; j < src.cols - 1; j++)
  36. {
  37. grad_y.data[i*grad_y.step + j] = abs((src.data[(i - 1)*src.step + j + 1]
  38. + 2 * src.data[i*src.step + j + 1]
  39. + src.data[(i + 1)*src.step + j + 1]
  40. - src.data[(i - 1)*src.step + j - 1] - 2 * src.data[i*src.step + j - 1]
  41. - src.data[(i + 1)*src.step + j - 1]));
  42. }
  43. }
  44. }
  45. Mat grad_x(src.rows, src.cols, CV_8UC1, Scalar(0));
  46. {
  47. for (int i = 1; i < src.rows - 1; i++)
  48. {
  49. for (int j = 1; j < src.cols - 1; j++)
  50. {
  51. grad_x.data[i*grad_x.step + j] = sqrt((src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]
  52. + src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]
  53. - 2 * src.data[(i + 1)*src.step + j]
  54. - src.data[(i + 1)*src.step + j + 1])* (src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]
  55. + src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]
  56. - 2 * src.data[(i + 1)*src.step + j]
  57. - src.data[(i + 1)*src.step + j + 1]));
  58. }
  59. }
  60. }
  61. imshow("origin", src);
  62. imshow("gradient", dstImage);
  63. imshow("Vertical gradient", grad_y);
  64. imshow("Horizontal gradient", grad_x);
  65. waitKey(0);
  66. return 0;
  67. }

效果:

输入:

水平梯度:

垂直梯度:

最终结果:

优缺点:

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

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

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

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号