python-Canny边缘检测+直线检测+圆检测+轮廓检测
-
- 一、Canny边缘检测
- 二、直线检测
-
- 三、圆检测
- 四、轮廓检测
一、Canny边缘检测
"""
Canny边缘检测理论
1.降噪
为避免受到噪声干扰,通常需要对图像进行滤波,一般使用5*5的滤波器
2.计算梯度
对平滑后的图像进行水平和垂直方向的Sobel滤波,得到水平方向的一阶导Gx与垂直方向一阶导数Gy
数梯度方向总是垂直于边缘,边缘梯度等于Gx的平方与Gy的平方之和开根号
3.非极大值抑制
在得到梯度的大小和方向后,对图像进行全扫描,取出可能不构成边缘的像素,为此判断在每个像素处
像素的梯度方向是否为邻域的最大值
4.双阈值处理
这个阶段决定边缘
需要确定两个阈值,minValue和maxValue,任何强度梯度大于maxValue的边肯定是边,任何小于minValue
的边是非边,位于两个阈值直接的,则根据其连接性对边缘或非边缘进行分类,如果它们连接到"确定边缘"像素
则它们被认为是边缘的一部分,否则被丢弃
方法:
cv2.Canny()
格式:
edges= cv2.Canny(img,threshold1,threshold2[,edges[,apertureSize[,L2gradient]]])
edages:计算得到的边缘图像
img:8位输入图像
threshold1:第一个阈值
threshold2:第二个阈值
apertureSize:Sobel算子的大小
L2gradient:是否计算图像的梯度的表示,默认位False,如果为True,会使用更精确的L2范数进行计算(即两个
方向导数平方和再开方),否则用L1范数(直接将两个导数的绝对值相加)
"""
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('img_2.png',0)
edge=cv2.Canny(img,60,100)
plt.subplot(1,2,1)
plt.imshow(img,cmap='gray')
plt.title('img')
plt.subplot(1,2,2)
plt.imshow(edge,cmap='gray')
plt.title('canny')
plt.show()

二、直线检测
1.霍夫变换
"""霍夫变换
lines = cv2.HoughLines(img,rho,theta,threshold[,lines[,srn[,stn[,min_thetal[,max_theta]]]])
img:输入一个二值图像,即图像输入之前应用阈值或使用Canny边缘检测
rho:表示p的精度
thera:表示θ的精度
threshold:阈值
"""
import cv2
import numpy as np
img = cv2.imread('img_2.png',0)
edage=cv2.Canny(img,50,110)
lines=cv2.HoughLines(edage,1,np.pi/180,90)
for l in lines:
rho,theta=l[0]
x=np.cos(theta)
y=np.sin(theta)
x0=x*rho
y0=y*rho
x1=int(x0+1000*(-y))
y1 = int(y0 + 1000 * (x))
x2 = int(x0 - 1000 * (-y))
y2 = int(y0 - 1000 * (x))
cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 1)
cv2.imshow('line',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.概率霍夫变换
"""
概率霍夫变换
lines = cv2.HoughLines(img,rho,theta,threshold[,lines[,srn[,stn[,minLineLength[,maxLineGap]]])
img:输入一个二值图像,即图像输入之前应用阈值或使用Canny边缘检测
rho:表示p的精度
thera:表示θ的精度
threshold:阈值
minLineLength:线的最短长度
maxmaxLineGap:线的最大间隔
"""
import cv2
import numpy as np
img = cv2.imread('img_2.png',0)
edge =cv2.Canny(img,50,100)
line = cv2.HoughLinesP(edge,1,np.pi/180,100,minLineLength=80,maxLineGap=20)
for l in line:
x1,y1,x2,y2=l[0]
cv2.line(img,(x1,y1),(x2,y2),(255,0,0),1)
cv2.imshow('line',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

三、圆检测
"""
circle=cv2.HoughCircles(img,method,dp,minDist[,circles[,param1[,param2[,minRadius[,maxRadius]]]]]])
img:输入图像(灰度图)
method:指定检测方法,霍夫梯度法
dp:累加器图像的反比分辨,可默认
min_Dist:检测圆心之间的最小距离,一般为src_gray.rows/8
param1:Canny函数的高阈值
param2:圆心检测阈值
minRadius:能检测到的最小圆半径,默认为0
maxRadius:能检测到的最大圆半径,默认为0
"""
import cv2
import numpy as np
img =cv2.imread('img_2.png',0)
img =cv2.medianBlur(img,3)
img =cv2.GaussianBlur(img,(17,19),0)
img1=cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
circle=cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)
circle=np.uint16(np.around(circle))
for c in circle[0,:]:
cv2.circle(img1,(c[0],c[1]),c[2],(0,0,255),2)
cv2.circle(img1,(c[0],c[1]),2,(255,0,0),3)
cv2.imshow('circle',img1)
cv2.waitKey(0)
cv2.destroyAllWindows()

四、轮廓检测
"""
轮廓检测:
cv2.findContours(img,mode,method,contours=None,hierarchy=None,offset=None)
img:输入的二值图片,若输入的为彩色图片,必须先进行灰度化和二值化
mode:表示轮廓的检索模式,有以下四种:
cv2.RETR_EXTERNAL 表示只检测外轮廓
cv2.RETR_LIST: 检测的轮廓不建立等级关系
cv2.RETR_CCOMP:建立两个等级的轮廓,上面一层为外边界,里面一层为内孔的边界信息
cv2.RETR_TREE:建立一个等级数结构轮廓
method:表示轮廓的近似方法,有一下四种:
cv2.CHAIN_APPROX_NONE 存储所有轮廓点,相邻的两个点的像素位置差不超过1
cv2.CHAIN_APPROX_SIMPLE(通常选择这个) 压缩水平方向,垂直方向,对角线的元素,只保留终点坐标,
例如一个矩形轮廓只需4个点来保存轮廓信息
cv2.CHAIN_APPROX_TC89_L1和cv2.CHAIN_APPROX_TC89_KCOS
返回值:
cv2.findContours()返回两个值,一个是轮廓本身contours,还有一个是每条轮廓对应的属性hierarchy
轮廓绘制:
cv2.drawContours(img,contours,contoursIdx,color,thickness=None,
lineType=None,hierarchy=None,maxLevel=None,offset=None)
img:为三通道图像
contours:为轮廓本身
contoursIdx:指定绘制哪条轮廓
thickness表示轮廓线的宽度,如果是-1,则为填充模式
"""
import cv2
img = cv2.imread('img_2.png')
img1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
contour = cv2.findContours(img1,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[0]
cv2.drawContours(img,contour,-1,(0,0,255),2)
cv2.imshow('contour',img)
cv2.waitKey(0)
cv2
