openCV自带的模板匹配函数只能匹配出一个地方,但是有多个,这就需要用到多目标模板匹配。
原图:
初步处理之后:
可见效果还算不错,但是还是有部分气泡没有识别出来而且,将一个噪声点误识别为气泡了。
示例代码如下:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
if __name__=='__main__':
path='./test_img/line/line7.jpg'
img=cv.imread(path)
cv.imshow('original', img)
#模板匹配
tpl=cv.imread('./test_img/template.png').astype(np.uint8)
cv.imshow('template',tpl)
result = cv.matchTemplate(img, tpl, cv.TM_CCOEFF_NORMED)
threshold = 0.8
th, tw = tpl.shape[:2]
# 返回res中值大于0.8的所有坐标
# 返回坐标格式(col,row) 注意:是先col后row 一般是(row,col)!!!
loc = np.where(result >= threshold) # 找到匹配程度大于%80的坐标y,x
# loc[::-1]:取从后向前(相反)的元素
for pt in zip(*loc[::-1]): # *号表示可选参数
#右下角
right_bottom = (pt[0] + tw, pt[1] + th)
cv.rectangle(img=img, pt1=pt,pt2=right_bottom,color=(0, 0, 255), thickness=1)
cv.imshow('matched', img)
cv.waitKey(0)
然后想对外接矩形标号来着,发现不可行,因为每个被识别出的气泡的外接矩形可能不唯一,如下图所示:
可以看到矩形的边缘粗细各不相同,且标号也重叠着,可见外接矩形不一定只有一个,故而无法进行气泡数量和位置统计,需另作它法。
接下来考虑不直接用原图来进行匹配,而是用边缘检测之后的图像来进行匹配。
对原图用了Canny的边缘检测,之后从Canny检测的结果图中扣了一小块气泡边缘图片来作为模板ROI进行模板匹配,发现随着阈值(匹配相似度)的增加,可以识别出来的气泡数量呈下降趋势,直到将相似度阈值调整为80%时,一个气泡也检测不出来了,可见效果并不理想。
有的气泡检测出的边缘是一个圈;有的气泡是一个圈,里面还带个点,所以我想如果膨胀之后将圈里全部膨胀成白色的话,那么再取作模板,效果是不是会更好。
注:试图将圆圈中间的点全部腐蚀掉的办法是不可行的,因为之前试了,整张图已经全都黑了。
利用膨胀之后的图来检测效果如下:
不难看出效果很乱,矩形层叠在一起,而且气泡数量问题用此方法得不到解决,但是可以看到识别效果还不错,大部分气泡都可以检测到。
到这暂时没想到别的好方法,写一下待解决问题:
1.气泡数量问题(可能需要自己来从0开始设计一个适应此场景的模板匹配)