零、软件功用和我使用背景
我需要操纵的app屏蔽了控件获取接口,因此直接用图像识别来分辨出app的各个元素进行操作。同时由于需要在各个设备上操纵此app,各设备图像有所不同,需要屏蔽掉这个影响。
一、参考文献及我的评判:
https://opencv.org/ opencv官网
二、意外问题一览
设备分辨率相关知识:
px:Pixel
dpi:device pixels
ppi:pixel per inch
density:密度
嗯 当然物理分辨率是没法调的。我当时是在一台设备上,通过调整密度,设置给手机不同的显示分辨率。
三、基本流程命令
1)对目标元素进行截图,保存作为样板。
对当前app进行截图,比对图片,(在估测区域region)找到样板。
kp1, des1 = sift.detectAndCompute(dst, None)
kp2, des2 = sift.detectAndCompute(src, None)
index_params = dict(algorithm=0, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=3)
matches是匹配的特征点集,是一个二维数组,由于提供的k为3故有3个。代表了三个可能匹配。我当时使用的方法是,如果说三个集合里匹配的特征点都不到总特征点数量的一半,认为两图并不匹配,即图片中并不存在我需要寻找的元素。
可能存在失误,但95%以上是正确的,对我当时需要的50%正确率是足够了。
2)无需考虑分辨率构成影响时,简单方便很多,matchtemplate搞定:
def find_dst_pos_val(src, dst, self_mask=False):
""" 找到目标在图像中的对应位置,并给出相似度 相似度比较方法为TM_SQDIFF,0为最优匹配
:param src: 源图
:param dst: 目标图(要求背景色为黑色(0,0,0)以排除干扰)
:return: 匹配点位置(加目标图大小即匹配区),相似度 """
res = cv2.matchTemplate(src, dst, cv2.TM_SQDIFF, mask=dst if self_mask else None)
xl = len(res)
yl = len(res[0])
m = 100
pos = None
for x in range(0, xl - 1):
for y in range(0, yl - 1):
if abs(res[x][y]) < m:
pos = x, y
m = abs(res[x][y])
posl = pos[1], pos[0] if pos else None
return posl, m
0为最优匹配 超出100,我判定为无匹配。
3)opencv 可以讲的实在太多了,嗯俺就给自己的用法做个小记录得。回头再用再回顾。