Sobel算子-边界检测

绝地灬酷狼 2022-03-31 02:23 420阅读 0赞

OpenCV官方教程

原理

Sobel算子

  • 近似计算图像梯度
  1. Horizontal 方向的变化: I I I是输入图像,算出的 G x : G_x: Gx​: [ − 1 0 + 1 − 2 0 + 2 − 1 0 + 1 ] ∗ I \left[ \begin{matrix} -1 & 0 & +1 \\ -2& 0 & +2 \\ -1 & 0 & +1 \end{matrix} \right]*I ⎣⎡​−1−2−1​000​+1+2+1​⎦⎤​∗I
  2. Vertical 方向的变化: I I I是输入图像, G y : G_y: Gy​:

    [ − 1 − 2 − 1 0 0 0 + 1 + 2 + 1 ] ∗ I \left[ \begin{matrix} -1 & -2 & -1 \\ 0 &0 & 0 \\ +1& +2 & +1 \end{matrix} \right] *I ⎣⎡​−10+1​−20+2​−10+1​⎦⎤​∗I

  3. 输入图像每个像素点的梯度 G = G x 2 + G y 2 G=\sqrt{G_x^2+G_y^2} G=Gx2​+Gy2​​

  4. 有时候使用以下来近似: G = ∣ G x ∣ + ∣ G y ∣ G=|G_x|+|G_y| G=∣Gx​∣+∣Gy​∣

Scharr

  • 比Sobel更加精确

20190101210902893.png


例程

  1. #include <opencv2/opencv.hpp>
  2. #include <iostream>
  3. using namespace cv;
  4. using namespace std;
  5. int main(int argc, char** argv)
  6. {
  7. Mat image, src,src_gray;
  8. Mat grad;
  9. const String window_name = "Sobel Demo";
  10. int ksize = 1;
  11. int scale = 1;
  12. int delta = 0;
  13. int ddepth = CV_16S; //进行Sobel操作可能有负值,所以改变深度
  14. String ImageName = "../res/lena.jpg";
  15. image = imread(ImageName,cv::IMREAD_COLOR);
  16. if(image.empty())
  17. {
  18. cout << "can't load the image" << endl;
  19. return -1;
  20. }
  21. for(;;)
  22. {
  23. cv::GaussianBlur(image,src,Size(3,3),0,0); //先滤波,去除噪声
  24. cv::cvtColor(src,src_gray,cv::COLOR_BGR2GRAY);// 转成灰度图像
  25. Mat grad_x, grad_y;
  26. Mat abs_grad_x,abs_grad_y;
  27. Sobel(src_gray,grad_x,ddepth,1,0,ksize,scale,delta); //对x方向进行Sobel操作
  28. Sobel(src_gray,grad_y,ddepth,0,1,ksize,scale,delta);// 对y方向进行 Sobel操作
  29. cv::convertScaleAbs(grad_x,abs_grad_x); //得到结果的绝对值,
  30. cv::convertScaleAbs(grad_y,abs_grad_y);
  31. cv::addWeighted(abs_grad_x,0.5,abs_grad_y,0.5,0,grad); //再将x和y方向的结果结合到一起
  32. imshow(window_name,grad);
  33. char key =(char)waitKey(0);
  34. if(key == 27)
  35. {
  36. return 0 ;
  37. }
  38. if(key =='K' || key == 'k')
  39. {
  40. ksize = ksize < 30 ? ksize+2 :-1;
  41. }
  42. if(key == 's' || key == 'S')
  43. {
  44. scale ++;
  45. }
  46. if(key == 'd' || key == 'D')
  47. {
  48. delta++;
  49. }
  50. if(key == 'r' || key == 'R') //默认参数
  51. {
  52. scale = 1;
  53. ksize = -1;
  54. delta = 0;
  55. }
  56. }
  57. return 0;
  58. };

结果:
在这里插入图片描述


OpenCV API

  • void cv::Sobel
    (
    InputArray src,     //输入图像
    OutputArray dst,     //输出图像(和src一样大小、通道数)
    int ddepth,     //输出图像的深度,见下图
    int dx,       // 为1 则是 x方向上的求导,否则为0
    int dy,       //为1 则是 y方向上的求导,否则为0
    int ksize = 3,      //Sobel核的大小 ,必须是1,3,5,7
    double scale = 1,      //算出结果 乘以这个值,比例因子
    double delta = 0,     // 最后处理结果,加上这个值
    int borderType = BORDER_DEFAULT     //边界处理
    )
    在这里插入图片描述
  • void cv::convertScaleAbs :计算绝对值再转成8位
    (
    InputArray src,    //
    OutputArray dst,    //
    double alpha = 1,    //
    double beta = 0     //
    )
    计算公式: d s t ( I ) = s a t u r a t e _ c a s t < u c h a r > ( ∣ s r c ( I ) ∗ a l p h a + b e t a ∣ ) dst(I)=saturate\_cast(|src(I)∗alpha+beta|) dst(I)=saturate_cast(∣src(I)∗alpha+beta∣)
  • void cv::addWeighted:按权重计算两个图像的和
    (
    InputArray src1,    //
    double alpha,    //
    InputArray src2,    //
    double beta,    //
    double gamma,    //
    OutputArray dst,    //
    int dtype = -1     // optional depth of the output array
    )
    计算公式: d s t = s a t u r a t e ( s r c 1 ∗ a l p h a + s r c 2 ∗ b e t a + g a m m a ; ) dst = saturate(src1*alpha + src2*beta + gamma;) dst=saturate(src1∗alpha+src2∗beta+gamma;)

发表评论

表情:
评论列表 (有 0 条评论,420人围观)

还没有评论,来说两句吧...

相关阅读

    相关 sobel算子

      彻底理解数字图像处理中的卷积-以Sobel算子为例[https://www.cnblogs.com/freeblues/p/5738987.html][https_www