常见检测:检测椭圆、斑点
来自本人笔记: https://github.com/masterAllen/LearnOpenCV/blob/main/docs/常见检测:检测椭圆、斑点
斑点检测
OpenCV 自带了斑点检测的类,SimpleBlobDetector。可以根据如下方式检测,具体原理看 图片:
1. 颜色、大小:blobColor=0 表示黑色的点,颜色只适用于二值图像;minArea, maxArea 表示斑点的大小范围;
2. 圆形程度:minCircularity, maxCircularity;这个是通过(4pi)*(面积/周长平方)来获取的,如正方形就是 0.785;
3. 凸性:minConvexity, maxConvexity;这个是斑点面积/凸包的面积;
4. 惯性比:minInertiaRatio, maxInertiaRatio;这个其实就是衡量伸长程度,是斑点主轴与次轴长度的比值,圆形是 1,直线是 0;
import cv2
img = cv2.imwrite('./test.png', -1)
# 创建一个SimpleBlobDetector对象
params = cv2.SimpleBlobDetector_Params()
# 设置过滤器的参数
params.filterByArea = True
params.minArea = 1500
# Filter by Circularity
params.filterByCircularity = True
params.minCircularity = 0.1
blob_detector = cv2.SimpleBlobDetector.create(params)
keypoints = blob_detector.detect(img)
检测椭圆:findEllipse,EdgeDrawing
其实斑点检测有的时候也能用于椭圆检测,不过这个时候要求是二值图、椭圆是封闭的、椭圆里面都是白色的。即如果是检测校徽那种圆,它里面有东西,而且二值化后不一定外框不一定封闭,那就不适合用斑点检测了。
OpenCV 有专门的检测椭圆方法,都是 ximgproc 里面的方法:findEllipse 和 EdgeDrawing。其中后者单独有一个页面,不仅仅可以检测椭圆,还能检测边缘和直线。代码如下,具体的个人实验代码在 test_detect_ellipses.ipynb 中:
import math
def draw_ellipses(src, ells, ells_type):
result = np.copy(src)
if ells is not None:
for one_ell in ells:
now_ell = one_ell[0]
center = now_ell[0:2].astype(int)
angle = now_ell[5] * 180 / math.pi
# 注意这里,每个方法返回值其实不太一样
if ells_type == 0:
# 这个是 findEllipses 返回值,(x,y,a,b,raidus,score)
axes = now_ell[2:4].astype(int)
elif ells_type == 1:
# 这个 EdgeDrawing 的返回值
axes = now_ell[3:5].astype(int) + int(now_ell[2])
cv2.ellipse(result, center, axes, angle, 0, 360, (0, 255, 0), 2)
return result
# ----------------------- findEllipses -------------------------------------
ells = cv2.ximgproc.findEllipses(
src,
scoreThreshold=0.7,
reliabilityThreshold=0.7,
centerDistanceThreshold=0.02
)
result1 = draw_ellipses(src, ells, ells_type=0)
# ----------------------- EdgeDrawing -------------------------------------
gray_src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
ed = cv2.ximgproc.createEdgeDrawing()
edParms = ed.Params()
edParms.GradientThresholdValue = 38
edParms.EdgeDetectionOperator = cv2.ximgproc.EdgeDrawing_SOBEL
edParms.AnchorThresholdValue = 8
ed.setParams(edParms)
# 最开始要执行这个函数,相当于和原图绑定一下
ed.detectEdges(gray_src)
# EdgeDrawing 可以检测边缘、直线、椭圆
ells = ed.detectEllipses()
result2 = draw_ellipses(src, ells, ells_type=1)
show_images([
('result1', result1),
('result2', result2)
])