aircv是网易放出的小开源我的项目,应该也是当初做简略图像匹配被援用最多的我的项目了。上一篇做了如何应用aircv之find_template的形容,然而,它并不算是一个成熟的我的项目,外面的小坑不少,有待改良。明天先做个代码逻辑的解析。

外围函数find_template 与 find_all_template

find_template函数是返回第一个最匹配的后果(地位未必在最下面),而find_all_template是返回所有大于指定置信度的后果。

比方要在思否页面截图中找

后果如如下图所示:

咱们深刻进去看一下代码,就会发现find_template是这样写的:

def find_template(im_source, im_search, threshold=0.5, rgb=False, bgremove=False):    '''    @return find location    if not found; return None    '''    result = find_all_template(im_source, im_search, threshold, 1, rgb, bgremove)    return result[0] if result else None

好家伙! 间接调用find_all_template,而后取返回值的第一个。。。

所以find_all_template才是真正的外围,咱们排除掉无关代码,来看一下最要害的局部:

def find_all_template(im_source, im_search, threshold=0.5, maxcnt=0, rgb=False, bgremove=False):    # 匹配算法,aircv实际上在代码里写死了用CCOEFF_NORMED,大部分测试的成果,也的确是这个算法更好    method = cv2.TM_CCOEFF_NORMED    # 获取匹配矩阵    res = cv2.matchTemplate(im_source, im_search, method)    w, h = im_search.shape[1], im_search.shape[0]    result = []    while True:        # 找到匹配最大最小值        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)        top_left = max_loc        if max_val < threshold:            break        # 计算中心点        middle_point = (top_left[0]+w/2, top_left[1]+h/2)        # 计算四个角的点,存入后果集        result.append(dict(            result=middle_point,            rectangle=(top_left, (top_left[0], top_left[1] + h), (top_left[0] + w, top_left[1]), (top_left[0] + w, top_left[1] + h)),            confidence=max_val        ))        # 把最匹配区域填充掉,再持续查找下一个        cv2.floodFill(res, None, max_loc, (-1000,), max_val-threshold+0.1, 1, flags=cv2.FLOODFILL_FIXED_RANGE)    return result

其中cv2.matchTemplate是opencv的办法,它的返回值是个矩阵,相当于用小图在大图上滑动,从左上角开始,每次挪动一个像素,而后计算一个匹配后果,最终造成后果矩阵。

后果矩阵大小应该是: (W - w + 1) x (H - h + 1),其中W,H是大图的宽高, w和h是小图的宽高。

这个矩阵中最大值的那个点,就示意小图的左上角对在这个地位时,匹配度最高,由此失去第一个匹配后果。

最初cv2.floodFill的作用,是把后果矩阵最大值这块区域用别的数字填充掉,这样就能够查找下一个最大值了,而且也防止了区域重叠的景象(要不然下一个最大值,有可能在刚刚找到的区域外面)。

几个小问题

  • 不反对灰度图和带通明通道的图
    其实opencv的matchTemplate原本只反对灰度图,但大多数状况下,咱们都是查找黑白图,所以aircv封装的时候,把bgr三个黑白通道做了拆散,别离调用matchTemplate,而后再合并后果。

但这个封装没有兼容原本就是灰度图的状况,居然会出错,而且如果源图带通明通道也会出错,为此,我专门提交了一个PR,但始终没有解决,看来我的项目曾经没人保护了。

  • floodFill貌似有点调兵遣将了,numpy的切片应该能够实现
    这个回头写段小代码验证一下
  • 不能解决图片的缩放
    模板图片和原图中的内容,并不一定大小严格统一的,那么就须要做一些缩放解决,反复尝试。
  • 图像匹配成果不现实
    如果是完全一致的图,find_template的成果十分好,但当须要含糊匹配时,某些人眼一看就雷同的图像,是无奈被辨认进去的,有点时候又会误辨认,这可能须要从两方面改良:
    -- 调整算法:采纳SIFT之类的特色点检测算法,能够解决大小和角度都不统一的图像匹配问题;Halcon等商业软件,采纳了shape based matching,匹配成果更佳。
    -- 退出信息:有时候除了模板图像自身,咱们兴许晓得更多的信息,比方图像可能呈现的地位范畴,图像周边区域的款式等等,来帮忙晋升辨认准确度,缩小误识和漏识。