圆形检测
通过python做圆形检测,基本都是一个套路,利用霍夫检测的思路,借用cv包的HoughCircles进行检测,这里要注意该函数的参数,不同的参数应对不同的业务场景,参数说明如下表
我经常修改的参数为minDist,param2,minRadius,maxRadius。一定不要犯懒,都挨个去理解,去试。
贴上我的代码和业务数据:代码也是我在别的地方抄的,随便百度就能找到
import cv2
img = cv2.imread('O:/work/circleimg/1009/yuan4.png')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
th2 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, \
cv2.THRESH_BINARY, 11, 2)
ret, thresh1 = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)
canny = cv2.Canny(thresh1, 40, 80)
canny = cv2.blur(canny, (3, 3))
# 霍夫变换圆检测
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 1000, param1=10, param2=35, minRadius=40, maxRadius=150)
# 输出检测到圆的个数
print(len(circles[0]))
for circle in circles[0]:
if (circle[2] >= 100):
continue
x = int(circle[0])
y = int(circle[1])
r = int(circle[2])
img = cv2.circle(img, (x, y), r, (0, 0, 255), -1)
cv2.imshow('res', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
闭合轮廓检测
因为业务场景要求不一定是圆形可以当作圆,闭合的曲线也可以作为圆,所以就探索了新的思路。这里我贴一个链接,应该能给你一些启发思路 我的思路来源于对cv.findContours函数的参数和返回值的发现。
- 该函数的第二个参数(轮廓的检索方式)可选很多,参数说明,因为考虑到实际的场景,封闭的圆一定在轮廓上存在层级关系的,所以我这里选择了cv.RETR_TREE,这样该函数的第二个返回值hierarchy就会保存层级关系,层级关系解释
- 通过层级关系以及轮廓数量,就可以筛选掉很多图片了,但是也有特例,就是数字6和9通过图片可以看到,这两张图片和封闭的轮廓一毛一样,而且层级关系也是相同的,于是通过第三参数(轮廓的近似办法)cv.CHAIN_APPROX_SIMPLE,参数说明和cv.findContours函数的第一个返回值进行判断。我判断的依据是:如果是曲线是闭合轮廓且没有其他的分支(反例,6和9),那么拟合该曲线的内外轮廓的坐标数差值相比于其他的曲线是更小的。经过实际证明确实是这样,不同的业务有不同的思路。上代码:
import cv2 as cv
import os
import numpy as np
# 定义圆形轮廓层级结构
x = [[[-1, -1, 1,-1], [-1, -1, 2,0], [-1, -1, -1,1]]]
x = np.array(x)
def circle(j):
src = cv.imread('O:/work/circleimg/1009/'+str(j))
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
_, thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
contours, hierarchy = cv.findContours(gray, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
# 轮廓数量为3 且符合x标准
print(j)
if len(contours)==3 and (hierarchy == x).all():
if abs(len(contours[1])-len(contours[2]))<40:
print("有缘")
else:
print("无缘")
else:
print("无缘")
cv.drawContours(src,contours,-1,(0,0,255),2)
cv.imshow("edged", src)
cv.waitKey(0)
cv.destroyAllWindows()
for i in os.listdir('O:/work/circleimg/1009/'):
circle(i)
简要说明:
- 变量x是我的数据图像取得固定圆形封闭轮廓层级关系,你的可能有所不同需要调试一番
- 图像预处理也需要注意,如果有需要可进行7x7的中值滤波