提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、pandas是什么?
  • 二、使用步骤
    • 1.引入库
    • 2.读入数据
  • 总结

前言

复习Canny边缘检测算法原理,并借助C++, Opencv简单实现


一、Canny 实现步骤描述

本文Canny边缘检测算法实现步骤如下:

1. 应用高斯模糊滤除图像噪声,算法借助梯度检测边缘,但是梯度检测对噪声敏感,应用高斯滤波器可以滤除图像噪声,提高边缘检测准确率;

2. 应用Sobel算法计算整幅图像的梯度幅值和角度,这里借助opencv cartToPolar()方法实现梯度幅值和角度的计算;

3. 对角度图像中每一角度值从0~360角度值归一化到[0, 45, 90, 135]这四个值;

4. 应用梯度幅值的非极大值抑制算法剔除不满足条件的边缘像素:遍历梯度幅值图像中每一像素点,根据该像素点角度值找到该像素点正、反方向邻近像素点梯度幅值并作比较,如果该像素点的梯度幅值大于邻近正、反方向邻近像素点,则在梯度幅值图像中保留,否则该像素点梯度幅值置为0;

5. 应用高、低阈值判断是否为边缘像素点:(1)如果梯度幅值图像中该点值大于高阈值,判定为边缘像素点;(2)如果梯度幅值图像中该点值小于低阈值,判定为非边缘像素点;(3)如果梯度幅值图像中该点值介于高、低阈值间,则要进行进一步判断:如果该点8邻域像素点有被判定为边缘像素点,则判定该点为边缘像素点, 否则判定为非边缘像素点。

二、代码实现

{// 1. Gaussian blurringMat gauImg;GaussianBlur(*pSrcImg, gauImg, Size(5, 5), 0);if (debug){imshow("gaussian", gauImg);cv::waitKey(0);}Mat grayImg;if (gauImg.channels() == 3)cvtColor(gauImg, grayImg, COLOR_BGR2GRAY);elsegrayImg = gauImg.clone();if (debug){imshow("gray", grayImg);cv::waitKey(0);}// 2. calc gradient angle and magnitudeMat sobxImg, sobyImg, angleImg_orig, angleImg, magImg;Sobel(grayImg, sobxImg, CV_32FC1, 1, 0);Sobel(grayImg, sobyImg, CV_32FC1, 0, 1);if (debug){imshow("sobel x", sobxImg);imshow("sobel y", sobyImg);cv::waitKey(0);}cartToPolar(sobxImg, sobyImg, magImg, angleImg_orig, true);// normal angleImg_orig(angle value: 0~360) to angleImg( angle value: [0, 45, 90, 135])angleImg = Mat(angleImg_orig.size(), CV_8UC1);for (int row = 0; row < angleImg_orig.rows; row++){for (int col = 0; col < angleImg_orig.cols; col++){if ((angleImg_orig.at<float>(row, col) >= 0 && angleImg_orig.at<float>(row, col) < 22.5) ||(angleImg_orig.at<float>(row, col) >= 337.5 && angleImg_orig.at<float>(row, col) < 360) ||angleImg_orig.at<float>(row, col) >= 157.5 && angleImg_orig.at<float>(row, col) < 202.5){angleImg.at<uchar>(row, col) = 0;}else if ((angleImg_orig.at<float>(row, col) >= 22.5 && angleImg_orig.at<float>(row, col) < 67.5) ||(angleImg_orig.at<float>(row, col) >= 202.5 && angleImg_orig.at<float>(row, col) < 247.5)){angleImg.at<uchar>(row, col) = 45;}else if ((angleImg_orig.at<float>(row, col) >= 67.5 && angleImg_orig.at<float>(row, col) < 112.5) ||(angleImg_orig.at<float>(row, col) >= 247.5 && angleImg_orig.at<float>(row, col) < 292.5)){angleImg.at<uchar>(row, col) = 90;}else{angleImg.at<uchar>(row, col) = 135;}}}// 3. non-maximum magnitude edge point suppressionMat nmsImg = Mat::zeros(magImg.size(), CV_8UC1);Mat nmsMagImg = Mat::zeros(magImg.size(), CV_32FC1);for (int row = 1; row < nmsImg.rows - 1; row++){for (int col = 1; col < nmsImg.cols - 1; col++){if (angleImg.at<uchar>(row, col) == 0 &&(magImg.at<float>(row, col) > magImg.at<float>(row, col - 1) &&magImg.at<float>(row, col) > magImg.at<float>(row, col + 1))){nmsMagImg.at<float>(row, col) = magImg.at<float>(row, col);nmsImg.at<uchar>(row, col) = 255;continue;}if (angleImg.at<uchar>(row, col) == 45 &&(magImg.at<float>(row, col) > magImg.at<float>(row - 1, col + 1) &&magImg.at<float>(row, col) > magImg.at<float>(row + 1, col - 1))){nmsMagImg.at<float>(row, col) = magImg.at<float>(row, col);nmsImg.at<uchar>(row, col) = 255;continue;}if (angleImg.at<uchar>(row, col) == 90 &&(magImg.at<float>(row, col) > magImg.at<float>(row - 1, col) &&magImg.at<float>(row, col) > magImg.at<float>(row + 1, col))){nmsMagImg.at<float>(row, col) = magImg.at<float>(row, col);nmsImg.at<uchar>(row, col) = 255;continue;}if (angleImg.at<uchar>(row, col) == 135 &&(magImg.at<float>(row, col) > magImg.at<float>(row - 1, col - 1) &&magImg.at<float>(row, col) > magImg.at<float>(row + 1, col + 1))){nmsMagImg.at<float>(row, col) = magImg.at<float>(row, col);nmsImg.at<uchar>(row, col) = 255;continue;}}}if (debug){imshow("nms", nmsImg);imshow("nms mag", nmsMagImg);cv::waitKey(0);}// 4. filter out edge points by low theshold and high threshold// 4.1 judge strong edge point: nmxMagImg pixel value > hightThres// judge weakge edge point: nmxMagImg pixel value < lowThres// note: if use magImg to judge, result image will like threshold() output image - rough edgeMat result = nmsImg.clone();for (int row = 1; row < result.rows - 1; row++){for (int col = 1; col < result.cols - 1; col++){if (nmsMagImg.at<float>(row, col) >= highThres)// note: must be nmsMagImg, not be magImg{result.at<uchar>(row, col) = 255;}if (nmsMagImg.at<float>(row, col) < lowThres){result.at<uchar>(row, col) = 0;}}}if (debug){imshow("strong edge", result);cv::waitKey(0);}// .4.2 judge medium edge points : lowThres< nmsMagImg pixel value <hightThresfor (int row = 1; row < result.rows - 1; row++){for (int col = 1; col < result.cols - 1; col++){if (nmsMagImg.at<float>(row, col) >= lowThres && nmsMagImg.at<float>(row, col) < highThres){if (result.at<uchar>(row - 1, col - 1) == 255 || result.at<uchar>(row - 1, col) == 255 ||result.at<uchar>(row - 1, col + 1) == 255 || result.at<uchar>(row, col + 1) == 255 ||result.at<uchar>(row + 1, col + 1) == 255 || result.at<uchar>(row + 1, col) == 255 ||result.at<uchar>(row + 1, col - 1) == 255 || result.at<uchar>(row, col - 1) == 255){result.at<uchar>(row, col) = 255;}else{result.at<uchar>(row, col) = 0;}}}}if (debug){imshow("my canny", result);cv::waitKey(0);}}

三、测试结果

1. 原图:

2. 本文实现Canny输出:lowThres=50, hightThres=100


总结

本文只是简单实现了Canny算法,和opencv Canny函数的输出还是有差距的,特别是当高、低阈值比较大时,Opencv Canny函数输出图像保留更多图像边缘信息(个人认为是梯度幅值介于高、低阈值时只是简单依据该像素点8邻域范围内是否有强边缘像素点判定是否为强边缘像素点,导致很多边缘像素点丢失,造成边缘不连续,读者可以在这一方向改进)。

C++ Opencv 实现Canny算法相关推荐

  1. 《OpenCv视觉之眼》Python图像处理十四 :Opencv图像轮廓提取之Scharr算法和Canny算法

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  2. OpenCV 【七】————边缘提取算子(图像边缘提取)——canny算法的原理及实现

    canny边缘检测实现(C++.opencv) 1.作用: 图像边缘信息主要集中在高频段,通常说图像锐化或检测边缘,实质就是高频滤波.我们知道微分运算是求信号的变化率,具有加强高频分量的作用.在空域运 ...

  3. 【OpenCV 4开发详解】Canny算法

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  4. Python+Opencv实现无参数、全自动的Canny算法

    目录 一.什么是Canny边缘检测算法? 二.最优边缘准则是什么? 三.Canny算法实现步骤 四.Canny算法在使用中的问题? 五.无参数.自动化Canny算法代码实现 六.改进算法效果展示 七. ...

  5. Python,Opencv cv2.Canny()边缘检测

    Python,Opencv的Canny边缘检测 1. 效果图 2. 源码 参考 这篇博客将介绍Canny边缘检测的概念,并利用cv2.Canny()实现边缘检测: Canny边缘检测是一种流行的边缘检 ...

  6. OpenCV函数 Canny 检测边缘

    OpenCV函数 Canny 检测边缘. 原理 Canny 边缘检测算法 是 John F. Canny 于 1986年开发出来的一个多级边缘检测算法,也被很多人认为是边缘检测的 最优算法, 最优边缘 ...

  7. 边缘检测(5)Canny算法

    边缘检测 1.Sobel 2.Laplace 3.Roberts 4.Canny Canny canny对边缘检测质量进行分析时,有3个原则: 1.信噪比准则 2.定位精度准则 3.单边缘响应准则   ...

  8. python canny算法_Python 实现 Canny 边缘检测算法

    Canny 边缘检测算法由计算机科学家 John F. Canny 于 1986 年提出的.其不仅提供了算法,还带来了一套边缘检测的理论,分阶段的解释如何实现边缘检测.Canny 检测算法包含下面几个 ...

  9. Python+OpenCV:Canny边缘检测

    Python+OpenCV:Canny边缘检测 理论 Canny边缘检测是目前比较流行的边缘检测算法,它由John F. Canny发明. 1. 这是一个多阶段的算法. 2. 降噪:由于边缘检测容易受 ...

最新文章

  1. Spring事务支持:利用继承简化配置
  2. python官网下载安装教程-各种版本的Python下载安装教程
  3. Padding Oracle Attack填充提示攻击-渗透测试
  4. 谷歌go语言课程讲解资源
  5. 检查坏道右键单击盘符/属性/工具中的查错。
  6. [Java基础]字符缓冲流
  7. php mssql扩展SQL查询中文字段名解决方法
  8. c++ vector常用用法总结
  9. 零基础大数据学习框架
  10. 数据挖掘导论——可视化分析实验
  11. 文件存储-CephFS
  12. 22. vCenter上解决”此主机当前没有管理网络冗余“的警告
  13. 记录第一次面试的体会(字节跳动实习生招聘)
  14. 怎样检测和应对数据集的Outliers
  15. echarts二次渲染时宽高为0图表不显示
  16. md文件打开方式推荐
  17. 国际短信有哪些用途?
  18. ftp服务器型号,ftp服务器的类型及其特点
  19. 上海发布通知:年底前全面清退不符条件的网约车车辆和驾驶员
  20. Error:All flavors must now belong to a named flavor dimension. Learn more at

热门文章

  1. C++静态库与动态库的区别?
  2. 芝加哥面孔数据库(CFD)的人脸模板
  3. 举例说明计算机中常用的变址寻址,堆栈寻址,从形式地址到得到操作数的寻址处理过程。
  4. Apache BookKeeper
  5. linux 文件755权限的意思,Linux文件和目录的777、755、644权限解释
  6. 【元宇宙欧米说】从GameFi的视角讨论Web2到Web3的利弊
  7. 环世界RimWorld for Mac(模拟建造游戏)
  8. 猜客魔盒二次开发盲盒APP趣味功能讲解(一)
  9. Wacom 数位板 和冠 手绘笔 Photoshop MacOS 延时卡顿丢笔解决办法
  10. js实现玫瑰动画效果