最近要做计算机视觉HED网络,可是对于计算机视觉(CV)不懂,对于边缘检测也不懂,从0开始学习,把这个学习过程记录一下。其实canny算法和HED网络基本没有关联,只是对于CV入门一下记录一下
上一篇:机器学习(13)--apriori算法(挖掘关联规则的频繁项集算法)
https://blog.csdn.net/qq_36187544/article/details/89184879
下一篇:机器学习(15)--HED网络实现(opencv+python实现边缘检测及源代码百度云资源)https://blog.csdn.net/qq_36187544/article/details/89839398
主要参考:https://www.cnblogs.com/invisible2/p/9177018.html和https://www.cnblogs.com/mightycode/p/6394810.html
首先要了解几个基本概念:
图是由点组成的,而点可以是黑白或者RGB三色组成,所以一个点,可以表示为一个数字(黑白图像)或者3个数字(RGB彩图)(搜索图像通道有更多通道的应用和介绍),比如一个由28×28个点组成的黑白图像就可转换为28×28的矩阵。
图像的卷积滤波:图像是有噪声的,对于去噪就采用信号处理方法,滤波处理,如下经典图,将一个3×3区域与卷积核相乘得到一个新值作为新的图像数据,不断滑动窗口,将整个图像进行卷积操作(当然有很多注意事项,比如如果卷积核所有元素和值大于1,则图像会越来越亮。比如对于边界的处理,如图3×3矩阵卷积后最外围一圈没有改变,可直接放入作为新图像也可省略缩小图像等)
卷积滤波原理稍微有点难懂,记住卷积滤波是进行滤波,作用是去噪。
不同卷积核结果不同:
空卷积核,得到原图:
锐化滤波,加大中心点值:
核加大的锐化滤波,更加精细:
浮雕:
高斯滤波(高斯模糊):
应用高斯函数即正态分布密度函数的规则(主要是二维正态分布),将权重矩阵(卷积核)变为:
这样一来就能达到一个有效去噪的目的。
题外话:在PS中也有高斯模糊的操作,居然是算法做出来的,计算机视觉、数学真的让人惊叹
进入canny算法之前先说一下边缘检测,什么是边缘检测,目的是标识数字图像中亮度变化明显的点。就是把边缘检测出来,下左图为原图,后两张为边缘检测后处理图像:
应用:比如识别二维码,把摄像头打开,一直检测检测,突然检测到了二维码,滴~,识别成功,第一步就是边缘检测,检测到是否有二维码图像,将识别到的矩阵4顶点,截取出来进行下一步识别!
canny算法如下:
步骤 | 作用 | 原理 |
高斯模糊 | 去除噪声 | 噪声集中于高频信号,利用高斯滤波的方法进行过滤 |
计算梯度幅值和方向 | 得到边缘 | 常用边缘差分算子(如Rober,Prewitt,Sobel)计算,使用sobel算子计算梯度。相对于其他边缘算子,Sobel算子得出来的边缘粗大明亮。 |
非最大值抑制 | 边缘细化
| 非最大值抑制能帮助保留局部最大梯度而抑制所有其他梯度值。这意味着只保留了梯度变化中最锐利的位置。 |
双阀值 | 区分边缘像素 | 缘像素点梯度值大于高阀值,则被认为是强边缘点。如果边缘梯度值小于高阀值,大于低阀值,则标记为弱边缘点。小于低阀值的点则被抑制掉。 |
滞后边界跟踪 | 整合弱边缘 | 强边缘点可以认为是真的边缘。弱边缘点则可能是真的边缘,也可能是噪声或颜色变化引起的。 算法:搜索所有连通的弱边缘,如果一条连通的弱边缘的任何一个点和强边缘点连通,则保留这条弱边缘,否则抑制这条弱边缘。搜索时可以用广度优先或者深度优先算法 |
canny算法缺点:canny 算法的检测效果,依赖于几个阈值参数,这些阈值参数的选择,通常都是人为设置的经验值。虽然有这些阈值参数,但是最终的参数只是一组或少数几组固定的组合,所以算法的鲁棒性又会打折扣,很容易遇到边缘检测效果不理想的场景
不同阈值造成的canny结果不一样:
利用cv2模块进行CANNY边缘检测:
import cv2
import numpy as np
img = cv2.imread('image0.jpg',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src',img)
# canny: 1.将彩图转为灰度 2. 高斯 3.canny
# 灰度化
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 高斯滤波
# 参数一: 灰度图像数据 参数二: 模板大小 参数三: sigmaX
imgG = cv2.GaussianBlur(gray,(3,3),0)
# 参数一: 图片数据 参数二: 两个阈值
dst = cv2.Canny(img,50,50) # 图片卷积之后的值 大于 th 就认为是边缘点
cv2.imshow('dst',dst)
cv2.waitKey(0)