canny

canny的目标有3个

  • 低错误率 检测出的边缘都是真正的边缘
  • 定位良好 边缘上的像素点与真正的边缘上的像素点距离应该最小
  • 最小响应 边缘只能标识一次,噪声不应该标注为边缘

canny分几步

  • 滤掉噪声 比如高斯滤波
  • 计算梯度 比如用索贝尔算子算出梯度
  • 非极大值抑制

    上一步算出来的边缘可能比较粗糙,假设边缘是一条很细的线的话,上面处理完的结果你可以理解为得到一条比较粗的线条,所谓非极大值抑制,就是要在局部像素点中找到变换最剧烈的一个点,这样就得到了更细的边缘.
  • 双阈值检测和连接边缘

前面2步我们应该很熟悉了,不熟悉的参考https://www.cnblogs.com/sdu20112013/p/11608469.htmlhttps://www.cnblogs.com/sdu20112013/p/11600436.html

非极大值抑制

在求解梯度这一步,我们可以得到梯度的模长和方向

这一步为我们下面做nms(非极大值抑制)打下了基础,索贝尔算子处理后的图像得到的边缘可能是很粗糙的,反映到图像上也就是边缘比较宽,我们采用nms把非极大值的点的灰度都置为0,这样就可以滤掉很多非边缘的像素点.

如下图所示,C表示为当前非极大值抑制的点,g1-4为它的8连通邻域点,图中蓝色线段表示上一步计算得到的角度图像C点的值,即梯度方向,第一步先判断C灰度值在8值邻域内是否最大,如是则继续检查图中梯度方向交点dTmp1,dTmp2值是否大于C,如C点大于dTmp1,dTmp2点的灰度值,则认定C点为极大值点,置为1,因此最后生成的图像应为一副二值图像,边缘理想状态下都为单像素边缘.



这一步里有一点需要注意的就是dTmp1,dTmp2,这两个像素点是不存在的,是通过双线性插值法算出来的. 在John Canny提出的Canny算子的论文中,非最大值抑制就只是在0、90、45、135四个梯度方向上进行的,每个像素点梯度方向按照相近程度用这四个方向来代替.实际检测过程里,为了更准确地过滤出属于边缘的像素点,会做双线性插值得到dTmp1,dTmp2.再去做前面所说的nms过程去判断一个像素点是否属于边缘.

推荐2篇讲的比较好的:https://blog.csdn.net/kezunhai/article/details/11620357 https://www.cnblogs.com/techyan1990/p/7291771.html

关于如何得到梯度方向的像素点,如下图所示

这样的话就达到了将"粗大的边缘"过滤地更加细腻.

这一步之后,得到的边缘还包含很多由噪声及其他原因造成的假边缘.

双阈值检测和边缘连接

经过nms以后,已经很接近真实边缘了.但还是有一些由于噪声或者别的一些原因造成的假的边缘.我们通过2个阈值来作进一步的过滤.

Hysteresis: The final step. Canny does use two thresholds (upper and lower): - If a pixel gradient is higher than the upper threshold, the pixel is accepted as an edge .If a pixel gradient value is below the lower threshold, then it is rejected.If the pixel gradient is between the two thresholds, then it will be accepted only if it is connected to a pixel that is above the upper threshold.

Canny recommended a upper:lower ratio between 2:1 and 3:1.

  • 对于梯度大于高阈值的点,认为是真的边缘上的像素点.
  • 对于梯度小于低阈值的点,认为是假的边缘像素点,是噪声造成的,去掉这些点.
  • 对于梯度介于高低阈值之间的点,如果它周围的邻域像素点有"真边缘点"(也就是梯度大于高阈值的点),则认为这点也是"真边缘点".

    推荐的高低阈值比在2:1到3:1之间

实际工程里,这两个参数要针对你自己的图像数据去调整,太低有可能造成假边缘太多,太高有可能造成想要保留的边缘也被滤掉了.

canny api

参数3,4表示低阈值和高阈值,L2gradient默认false,表示是否用开平方的方式计算梯度的大小.

opencv示例

from __future__ import print_function
import cv2 as cv
import argparse
max_lowThreshold = 100
window_name = 'Edge Map'
title_trackbar = 'Min Threshold:'
ratio = 3
kernel_size = 3
def CannyThreshold(val):
low_threshold = val
#img_blur = cv.blur(src_gray, (3,3))
detected_edges = cv.Canny(src_gray, low_threshold, low_threshold*ratio, kernel_size)
mask = detected_edges != 0
dst = src * (mask[:,:,None].astype(src.dtype))
cv.imshow(window_name, dst) src = cv.imread("/home/sc/disk/keepgoing/opencv_test/sidetest.jpeg")
src = cv.GaussianBlur(src, (3, 3), 0)
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
cv.namedWindow(window_name)
cv.createTrackbar(title_trackbar, window_name , 0, max_lowThreshold, CannyThreshold)
CannyThreshold(0)
cv.waitKey()

注意阈值的不同造成的影响,可以看到阈值很低的时候线条更多,当然"伪边缘"更多,当阈值很高的时候,"伪边缘"减少了,但也丢失了更多的细节.所以需要根据自己实际的图片数据去调参.

opencv目标检测之canny算法的更多相关文章

  1. 第三十五节,目标检测之YOLO算法详解

    Redmon, J., Divvala, S., Girshick, R., Farhadi, A.: You only look once: Unified, real-time object de ...

  2. OpenCV:OpenCV目标检测Boost方法训练

    在古老的CNN方法出现以后,并不能适用于图像中目标检测.20世纪60年代,Hubel和Wiesel( 百度百科 )在研究猫脑皮层中用于局部敏感和方向选择的神经元时发现其独特的网络结构可以有效地降低反馈 ...

  3. OpenCV:OpenCV目标检测Adaboost+haar源代码分析

    使用OpenCV作图像检测, Adaboost+haar决策过程,其中一部分源代码如下: 函数调用堆栈的底层为: 1.使用有序决策桩进行预测 template<class FEval> i ...

  4. 目标检测:SSD算法详解

    一些概念   True    Predict  True postive False postive  预测为正类 False negivate True negivate  预测为负类    真实为 ...

  5. 【58】目标检测之YOLO 算法

    YOLO 算法(Putting it together: YOLO algorithm) 你们已经学到对象检测算法的大部分组件了,在这个笔记里,我们会把所有组件组装在一起构成YOLO对象检测算法.   ...

  6. OpenCV:OpenCV目标检测Hog+SWindow源代码分析

    参考文章:OpenCV中的HOG+SVM物体分类 此文主要描述出HOG分类的调用堆栈. 使用OpenCV作图像检测, 使用HOG检测过程,其中一部分源代码如下: 1.HOG 检测底层栈的检测计算代码: ...

  7. 【目标检测】RCNN算法详解

    网址: 1. https://blog.csdn.net/zijin0802034/article/details/77685438 (box regression 边框回归) 2. https:// ...

  8. 第二十九节,目标检测算法之R-CNN算法详解

    Girshick, Ross, et al. “Rich feature hierarchies for accurate object detection and semantic segmenta ...

  9. 目标检测算法之R-CNN算法详解

    R-CNN全称为Region-CNN,它可以说是第一个成功地将深度学习应用到目标检测上的算法.后面提到的Fast R-CNN.Faster R-CNN全部都是建立在R-CNN的基础上的. 传统目标检测 ...

随机推荐

  1. YARN底层基础库

      YARN基础库是其他一切模块的基础,它的设计直接决定了YARN的稳定性和扩展性,YARN借用了MRV1的一些底层基础库,比如RPC库等,但因为引入了很多新的软件设计方式,所以它的基础库更多,包括直 ...

  2. C# - AutoMapper之不同类型的转换

    一.Dto & Model约定 class TestDto { public string Name { get; set; } public int Age { get; set; } pu ...

  3. vue+vscode+nodejs 开发环境搭建

    nodejs安装配置 1.下载 地址:https://nodejs.org/en/ 2.默认安装 安装完成后,执行npm -v 出现版本号则表示安装成功. 3.配置 在node安装目录下新建两个文件夹 ...

  4. Codeforces Round #506 (Div. 3) 1029 F. Multicolored Markers

    CF-1029F 题意: a,b个小正方形构造一个矩形,大小为(a+b),并且要求其中要么a个小正方形是矩形,要么b个小正方形是矩形. 思路: 之前在想要分a,b是否为奇数讨论,后来发现根本不需要.只 ...

  5. c博客作业00--我的第一篇博客

    1.你对网络专业或计算机专业了解是怎样? 一开始以为计算机网络专业就是搞跟计算机有关的东西,后来查了网络才知道,网络专业主要学计算机科学基础理论软硬件系统及应用知识 .网络工程的专业及应用知识. 2. ...

  6. mysql 主主从配置

    配置主服务器:主服务器1 Ip:  192.168.0.1 主服务器2 Ip:  192.168.0.2 主服务器1配置 2.1.修改mysql配置文件 vim /etc/my.conf Server ...

  7. 林大妈的JavaScript进阶知识(三):HTML5 History API

    HTML5中新增了History API,它用于管理浏览器路由跳转的一个url栈.History是window对象的一部分,它也是一个对象,因此称它是BOM(类似DOM,Browser Object ...

  8. C++ lambda的演化

    翻译自https://www.bfilipek.com/2019/02/lambdas-story-part1.html与https://www.bfilipek.com/2019/02/lambda ...

  9. C# 表达式树遍历(二)

    一.前言 上一篇我们对表达式树有了初步的认识,这里我们将对表达式树进行遍历,只有弄清楚了他的运行原理,我们才可以对他进行定制化修改. 表达式系列目录 C# 表达式树讲解(一) C# 表达式树遍历(二) ...

  10. Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵动态限流规则

    Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵动态限流规则 前面几篇文章较为详细的介绍了Sentinel的使用姿势,还没看过的小伙伴可以访问以下链接查看: &l ...