一、直线检测
1.1 概念
霍夫直线变换:用来做直线检测;前提条件-边缘检测已经完成;平面空间到极坐标空间转换。
不知道图像(边缘检测后的图像)中有没有直线,那么就将边缘检测后的图像由平面坐标转到极坐标表示,找到极坐标下亮的点,然后将这些点再反向映射到平米空间就可得到直线。完成霍夫直线检测
1.2 实战
1.2.1 手动cv.HoughLines
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
'''边缘检测'''
def canny_demo(image):
# 1.高斯模糊:最后两个参数给定一个就可以自动求取另一个,所以只给其中一个赋值就可以
blur=cv.GaussianBlur(image,(3,3),0)
#2.灰度处理
gray=cv.cvtColor(blur,cv.COLOR_BGR2GRAY)
#3.求取梯度,也可以不用梯度,直接将灰度图传入cv.canny
grad_x=cv.Sobel(gray,cv.CV_16SC1,1,0)
grad_y = cv.Sobel(gray, cv.CV_16SC1, 0, 1)
#4.求边缘
edge_output=cv.Canny(grad_x,grad_y,50,150)#参数:x梯度,y梯度 ,低阈值,高阈值
cv.imshow('canny-demo',edge_output)
return edge_output
'''直线检测'''
def huf_line_detect():
img = cv.imread(r'D:\Project\Opencv\Learning01\line.jpg')
edge_output=canny_demo(img)
lines=cv.HoughLines(edge_output,1,np.pi/180,200)#参数:边缘图像,半径,角度,高值
for line in lines:
rho,theta=line[0]
a=np.cos(theta)
b=np.sin(theta)
x0=a+rho
y0=b+rho
x1=int(x0+1000*(-b))
y1=int(y0+1000*(a))
x2=int(x0-1000*(-b))
y2=int(y0-1000*(a))
# 绘制直线:参数图像,点1,点2,颜色,直线宽度
cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv.imshow('img',img)
img = cv.imread(r'D:\Project\Opencv\Learning01\line.jpg')
cv.imshow('origin',img)
huf_line_detect()
cv.waitKey(0)
1.2.2 调用API(推荐)cv.HoughLinesP
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
'''边缘检测'''
def canny_demo(image):
# 1.高斯模糊:最后两个参数给定一个就可以自动求取另一个,所以只给其中一个赋值就可以
blur=cv.GaussianBlur(image,(3,3),0)
#2.灰度处理
gray=cv.cvtColor(blur,cv.COLOR_BGR2GRAY)
#3.求取梯度,也可以不用梯度,直接将灰度图传入cv.canny
grad_x=cv.Sobel(gray,cv.CV_16SC1,1,0)
grad_y = cv.Sobel(gray, cv.CV_16SC1, 0, 1)
#4.求边缘
edge_output=cv.Canny(grad_x,grad_y,50,150)#参数:x梯度,y梯度 ,低阈值,高阈值
cv.imshow('canny-demo',edge_output)
return edge_output
'''直线检测'''
def line_detect_huf():
img = cv.imread(r'D:\Project\Opencv\Learning01\line.jpg')
edge_output=canny_demo(img)
lines=cv.HoughLinesP(edge_output,1,np.pi/180,100,minLineLength=50,maxLineGap=10)
for line in lines:
x1,y1,x2,y2=line[0]
cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv.imshow('img', img)
img = cv.imread(r'D:\Project\Opencv\Learning01\line.jpg')
cv.imshow('origin',img)
line_detect_huf()
cv.waitKey(0)
二、圆检测
2.1 概念
霍夫圆变换原理:从平面坐标到极坐标转换三个参数C(x0,y0,r)其中x0,y0是圆心,。假设平面坐标的任意一个圆上的点,转换到极坐标中C(x0,y0,r)处有最大值,霍夫变换正是利用这个原理。
现实考量:
因为霍夫圆检测对噪声比较敏感,所以首先要对图像做中值滤波。
基于效率考量,OpenCV中实现的霍夫变换圆检测是基于图像梯度的实现,分为两步:1.边缘检测,可能发现圆心;2.基于第一步的基础上从候选圆心开始计算最佳半径大小。
2.2 实战
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
'''圆检测'''
def circle_detect():
img = cv.imread(r'D:\Project\Opencv\Learning01\monney.jpg')
#边缘保留滤波
dst=cv.pyrMeanShiftFiltering(img,10,100)
gray=cv.cvtColor(dst,cv.COLOR_BGR2GRAY)
#霍夫圆检测,跟直线检测一样可以不用梯度图
circles=cv.HoughCircles(gray,cv.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)
circles=np.uint16(np.around(circles))
for circle in circles[0,:]:
cv.circle(img,(circle[0],circle[1]),circle[2],(0,0,255),2)
cv.circle(img, (circle[0], circle[1]), 2, (255, 0, 0), 2)
cv.imshow('img',img)
img = cv.imread(r'D:\Project\Opencv\Learning01\monney.jpg')
cv.imshow('origin',img)
circle_detect()
cv.waitKey(0)
出现多余的圆是因为霍夫检测对噪声非常敏感,所以可以使用一些滤波调整,将噪声去除。