```python
import logging
logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(levelname)s- %(message)s')
import os
import time
import multiprocessing
import Base
import cv2 as cv
import traceback
import warnings
PIC_PATH = os.path.join(os.getcwd(),'full_screen') #全拼截图的存放路径
MATCH_PIC_PATH = os.path.join(os.getcwd(),'match_pic')
if not os.path.exists(PIC_PATH):
os.mkdir(PIC_PATH)
if not os.path.exists(MATCH_PIC_PATH):
os.mkdir(MATCH_PIC_PATH)
FULL_SCREEN_PATH = os.path.join(PIC_PATH,'full_screen.png')
class Click_pic():
def __init__(self,match_pic,driver=None,cut=None,udid=None,sleeptime=1,Related=(0.96,1),screenshot_file=FULL_SCREEN_PATH):
self._pic = match_pic
self.screenshot_file = screenshot_file
self.Related = Related #匹配图片时的相关性阈值,小于该阈值不做匹配
self.sleeptime = sleeptime
self.udid = udid
self.driver = driver
self.cut = cut
self.cut_match = None #获取匹配到的图片
self.match_pic = cv.imread(os.path.join(MATCH_PIC_PATH,match_pic)) #匹配的控件部分,把匹配的图片放在MATCH_PIC_PATH
self.full_screen = self.full_pic()
self.target_screen = self.cut_screen()
self.target_click_point = self.pic_match()
self.point_x , self.point_y = self.main()
logging.debug('对象初始化完毕')
def full_pic(self):
screen_file = self.screenshot_file
time.sleep(self.sleeptime)
if not self.driver == None:
self.driver.get_screenshot_as_file(screen_file)
else: #使用adb进行截图
Base.adb_shotscreen(self.udid,screen_file)
screen = cv.imread(screen_file)
return screen
def cut_screen(self): #切割截图的图片 ,cut为切割三分取第一份
screen_gray = cv.cvtColor(self.full_screen,cv.COLOR_BGR2GRAY) #灰度
if self.cut == None:
return screen_gray
h,w = self.full_screen.shape[:2]
cuts = int(h/self.cut[0]) #把原图分为几分
if self.cut[1]<=1:
target = screen_gray[0:cuts,:]
else:
target = screen_gray[cuts*(self.cut[1]-1):cuts*self.cut[1],:]
return target
def pic_match(self): #opencv
h,w = self.match_pic.shape[:2]
little_pic_gray = cv.cvtColor(self.match_pic,cv.COLOR_BGR2GRAY)
result = cv.matchTemplate(self.target_screen,little_pic_gray,cv.TM_SQDIFF_NORMED)
# cv.imwrite('result.png',result)
min_val,max_val,min_loc,max_loc = cv.minMaxLoc(result)
min_loc_bottom = (min_loc[0]+w,min_loc[1]+h)
# cv.rectangle(self.target_screen,min_loc,min_loc_bottom,(0,0,255),thickness=2)
self.cut_match = self.target_screen[min_loc[1]:min_loc_bottom[1],min_loc[0]:min_loc_bottom[0]]
if self.cut == None:
target_click_point = (min_loc[0]+0.5*w,min_loc[1]+0.5*h)
else:
target_click_point = ((min_loc[0]+(min_loc_bottom[0]-min_loc[0])/2),(min_loc[1]+(min_loc_bottom[1]-min_loc[1])/2))
logging.debug(target_click_point)
return target_click_point
def get_clickpoint(self):
#点击位置的坐标(x,),y坐标需要加上切割成3份图片 取第一份+0份 ,取第二份加+1份,取第三份+2份
#获取每一份的高度尺寸
if self.cut == None:
return self.target_click_point
full_h,full_w = self.full_screen.shape[:2]
part_h = int(full_h/self.cut[0])
#确定需要咋原坐标上加上多少块被切割的part_h
y = int(self.target_click_point[1]+part_h*(self.cut[1]-1))
return int(self.target_click_point[0]),y
def main(self):
point_x, point_y = self.get_clickpoint()
return point_x,point_y
寻思着弄个东西,可以图像识别对接其他的ui自动化工具,解决一些,控件找不到的问题。于是于是就试着弄了这个东西出来。
构造参数:
match_pic: 需要点击的位置截图(注意一定要原尺寸图片上截图,这个有点麻烦,菜鸟暂时未晓得怎么优化)
driver: 接入driver,目前就用来截图,后期可能有别的用处。若为空则 adb截图
cut: (n,m)第一个数为把屏幕横向(切割y轴)平分为n份,需要匹配的图片在第m份,为None时会对全局进行匹配。
udid: adb devices出来的设备id。只有一台设备可以为空
Related: (最低阈值,最高阈值)。这个是匹配图片是的相似度阈值,设置得越高精度越高(但有时会匹配不到),反之…。测试过程中最低阈值范围一般为 0.3~0.96,可以根据实际匹配得对象调整。
流程大概如下:
1 使用自动化工具,或android 的adb 截图(当然可以修改后使用其他更加高速的截图方式。然后对图片进行灰度处理(感觉灰度处理后,处理会更高效,实际未进行对比)
2 然后根据cut 获得该部分的图片,下面称为图片A
3 根据opencv模板匹配的cv.TM_SQDIFF_NORMED算法将需要匹配的图片B与图片A进行匹配,获取B的中点位置在A上面坐标。找出这个坐标在原图(截屏的原始图片上的位置坐标)
4 这时对象构造完毕。
下次更新一些,这个对象执行的方法。