1 安装 opencv , 在设置好的虚拟目录执行
1 |
pip install opencv-python |
再安装 pyautogui
1 |
pip install pyautogui |
2 python + opencv 截屏
1 2 3 4 5 6 7 8 9 10 11 |
import numpy as np import pyautogui import cv2 # take a screenshot of the screen and store it in memory, then # convert the PIL/Pillow image to an OpenCV compatible NumPy array # and finally write the image to disk image = pyautogui.screenshot() image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) cv2.imwrite("in_memory_to_disk.png", image) |
3: How do I find an image contained within an image? From :
https://stackoverflow.com/questions/7853628/how-do-i-find-an-image-contained-within-an-image
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import cv2 method = cv2.TM_SQDIFF_NORMED # Read the images from the file small_image = cv2.imread('small_image.png') large_image = cv2.imread('large_image.png') result = cv2.matchTemplate(small_image, large_image, method) # We want the minimum squared difference mn,_,mnLoc,_ = cv2.minMaxLoc(result) # Draw the rectangle: # Extract the coordinates of our best match MPx,MPy = mnLoc # Step 2: Get the size of the template. This is the same size as the match. trows,tcols = small_image.shape[:2] #print(trows) #print(tcols) # Step 3: Draw the rectangle on large_image cv2.rectangle(large_image, (MPx,MPy),(MPx+tcols,MPy+trows),(0,0,255),2) # Display the original image with the rectangle around the match. cv2.imshow('output',large_image) # The image is only displayed if we call this cv2.waitKey(0) |
这段代码会在大图上, 以矩形标出match 的部分 , if exist match
4 在 windows , python 37 ,32位环境, 执行这段代码能找出 exactly match 的部分, 并自动把鼠标移动到那里, 点击右键
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
import cv2 import pyscreenshot as ImageGrab import numpy as np import autopy import pyautogui import os import time import math dev = True def check_screen_size(): print("Checking screen size") img = ImageGrab.grab() # img.save('temp.png') global screen_size global screen_start_point global screen_end_point screen_size = (img.size[0] / 2, img.size[1] / 2) #screen_size = (img.size[0], img.size[1]) screen_start_point = (screen_size[0] * 0.35, screen_size[1] * 0.35) screen_end_point = (screen_size[0] * 0.65, screen_size[1] * 0.65) print ("Screen size is " + str(screen_size)) def make_screenshot(): print('Capturing screen') print(screen_start_point) #screenshot = ImageGrab.grab(bbox=(screen_start_point[0], screen_start_point[1], #screen_end_point[0], screen_end_point[1])) # (0, 710, 410, 1010) image = pyautogui.screenshot(region=(0,0, 1920, 1080)) if dev: screenshot_name = 'var/fishing_session_' + str(int(time.time())) + '.png' else: screenshot_name = 'var/fishing_session.png' #screenshot.save(screenshot_name) image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) cv2.imwrite(screenshot_name, image) return screenshot_name def find_float(img_name): print('Looking for float') # todo: maybe make some universal float without background? for x in range(0, 1): #template = cv2.imread('small_image.png', 0) template = cv2.imread('yinye.png', 0) img_rgb = cv2.imread(img_name) img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY) # print('got images') w, h = template.shape[::-1] res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED) # We want the minimum squared difference mn,_,mnLoc,_ = cv2.minMaxLoc(res) # Draw the rectangle: # Extract the coordinates of our best match MPx,MPy = mnLoc print(MPx) print(MPy) threshold = 0.4 loc = np.where( res >= threshold) for pt in zip(*loc[::-1]): cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2) if loc[0].any(): print('Found ' + str(x) + ' float') if dev: cv2.imwrite('var/fishing_session_' + str(int(time.time())) + '_success.png', img_rgb) #return (loc[1][0] + w / 2) / 2, (loc[0][0] + h / 2) / 2 return pt[0] + w/2, pt[1] + h/2 def move_mouse(place): x,y = place[0], place[1] #print("Moving cursor to " + str(place)) #autopy.mouse.smooth_move(int(screen_start_point[0]) + x , int(screen_start_point[1]) + y) autopy.mouse.move(0,0) #autopy.mouse.move(x, y) autopy.mouse.smooth_move(x, y) #def main(): if __name__ == '__main__': check_screen_size() im = make_screenshot() place = find_float(im) move_mouse(place) autopy.mouse.click(autopy.mouse.Button.RIGHT) #print(place) #if not place: # print('Still cant find float, breaking this session') #print ('catched ') |
缺点是只能精确匹配, 图像稍有差别 , 或者放大缩小,变换镜头角度都不行
已经有人提出过这个问题, 在 : https://answers.opencv.org/question/169613/how-does-macthtemplate-deal-with-scaling/
关键字:
1 |
matchTemplate is not scale invariant |
意思是 opencv 的 matchTemplate 函数不是比例变换不相关的
那么, 如何使 matchTemplate 可以比较不同比例的图像, 参见这个文章:
https://www.pyimagesearch.com/2015/01/26/multi-scale-template-matching-using-python-opencv/
in this article , 解决方法是: 对于大图, 循环放大缩小多次, 以匹配小图 , 但是, 这样只是解决了比例问题, 还是没解决角度问题
更先进的方法应该是: 特征匹配或者关键点匹配, 参见文章:
或者这个文章 更好一些: https://blog.csdn.net/HuangZhang_123/article/details/80660688
找到特征匹配后, 如何找相应点的坐标: https://stackoverflow.com/questions/30716610/how-to-get-pixel-coordinates-from-feature-matching-in-opencv-python
关键字 : cv2.cornerHarris 函数
理论分析和实现 SIFT算法 : https://www.geek-share.com/detail/2777206412.html
5 如何模糊匹配, 即无论图像缩放, 观察角度的变化, 都能正确匹配到
参考文章 : https://www.lagou.com/lgeduarticle/74061.html
这个不一定对