对不起,但标题似乎不太合理
我正在尝试制作一个AI,通过点击球使其弹跳。以下是应用程序的图片
在游戏中,点击球后,球会向上然后再落下来,游戏的目标是保持球不落地。
我已经编写了一些代码,使用OpenCV将图像转换为掩码,以下是结果的图片
我现在需要做的是找到球的位置(以像素/坐标表示),这样我可以让鼠标移动到该位置并点击它。顺便说一下,球的左右两侧有边距,所以它不会只是直上直下,而是左右移动。另外,球不是动画,只是移动的图像。
如何获取球的位置(以像素/坐标表示),这样我可以移动鼠标到该位置。
这是我的代码副本:
import numpy as npfrom PIL import ImageGrabimport cv2import timeimport pyautoguidef draw_lines(img,lines): for line in lines: coords = line[0] cv2.line(img, (coords[0], coords[1]), (coords[2], coords[3]), [255,255,255], 3)def process_img(original_image): processed_img = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY) processed_img = cv2.Canny(processed_img, threshold1=200, threshold2=300) vertices = np.array([[0,0],[0,800],[850,800],[850,0] ], np.int32) processed_img = roi(processed_img, [vertices]) # more info: http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_houghlines/py_houghlines.html # edges rho theta thresh # min length, max gap: lines = cv2.HoughLinesP(processed_img, 1, np.pi/180, 180, 20, 15) draw_lines(processed_img,lines) return processed_imgdef roi(img, vertices): #blank mask: mask = np.zeros_like(img) # fill the mask cv2.fillPoly(mask, vertices, 255) # now only show the area that is the mask masked = cv2.bitwise_and(img, mask) return maskeddef main(): last_time = time.time() while(True): screen = np.array(ImageGrab.grab(bbox=(0,40, 800, 850))) new_screen = process_img(screen) print('Loop took {} seconds'.format(time.time()-last_time)) last_time = time.time() cv2.imshow('window', new_screen) #cv2.imshow('window2', cv2.cvtColor(screen, cv2.COLOR_BGR2RGB)) if cv2.waitKey(25) & 0xFF == ord('q'): cv2.destroyAllWindows() breakdef mouse_movement(): ##Set to move relative to where ball is pyautogui.moveTo(300,400) pyautogui.click();main()
对不起如果这让您感到困惑,但我的大脑已经停止工作了 🙁 谢谢
回答:
当您删除了另一个相关的问题时,我正在处理它,并且看到您在定位球时遇到了性能问题。由于您的球似乎在一个简单而干净的白色背景上(除了得分和右上角的close
按钮),有更简单/更快的方法来找到球。
首先,使用灰度模式工作,这样您只需处理一个通道,而不是RGB的三个通道——这通常会更快。
然后,用白色像素覆盖右上角的得分和菜单,这样图像中只剩下球。现在反转图像,使所有白色变为黑色,然后您可以使用findNonZero()
来找到任何不是背景的东西,即球。
现在找到y方向上的最低和最高坐标,并平均它们以确定球的中心,同样在x方向上找到另一方向的中心。
#!/usr/bin/env python3# Load image - work in greyscale as 1/3 as many pixelsim = cv2.imread('ball.png',cv2.IMREAD_GRAYSCALE)# Overwrite "Current Best" with white - these numbers will vary depending on what you captureim[134:400,447:714] = 255# Overwrite menu and "Close" button at top-right with white - these numbers will vary depending on what you captureim[3:107,1494:1726] = 255# Negate image so whites become blackim=255-im# Find anything not black, i.e. the ballnz = cv2.findNonZero(im)# Find top, bottom, left and right edge of balla = nz[:,0,0].min()b = nz[:,0,0].max()c = nz[:,0,1].min()d = nz[:,0,1].max()print('a:{}, b:{}, c:{}, d:{}'.format(a,b,c,d))# Average top and bottom edges, left and right edges, to give centrec0 = (a+b)/2c1 = (c+d)/2print('Ball centre: {},{}'.format(c0,c1))
这会得到:
a:442, b:688, c:1063, d:1304Ball centre: 565.0,1183.5
如果我在图像上画一个红色的框,会显示如下:
在我的Mac上处理时间为845微秒,或者不到一毫秒,这相当于每秒1,183帧。显然,您需要时间来捕获屏幕,但我无法控制这一点。
请注意,您还可以将图像按每个方向的4倍(或可能是8倍或16倍)缩小尺寸,并且仍然可以确定找到球,这可能会使处理速度更快。
关键词:球,追踪,定位,寻找,位置,图像,图像处理,Python,OpenCV,NumPy,边界框,bbox。