【好玩的计算机视觉】自动玩“别踩白块儿”

在4399上找到了“别踩白块儿”网页版小游戏,然后用python3写了一个自动玩的小脚本。使用Python3,OpenCV 3.

【好玩的计算机视觉】自动玩“别踩白块儿”_第1张图片

【好玩的计算机视觉】自动玩“别踩白块儿”_第2张图片

import cv2
import numpy as np
import os
import pyscreenshot as ss
import time

def onMouse(event, x, y, flags, param):
    global flag, pLeftTop, pRightBottom
    if event == cv2.EVENT_LBUTTONDOWN:
        if flag:
            pLeftTop = (x,y)
        else:
            pRightBottom = (x,y)
        flag = False

flag = True
pLeftTop = None
pRightBottom = None

cv2.namedWindow('frame')
cv2.setMouseCallback('frame', onMouse)

img = ss.grab(bbox=(0,0,1300,768))
img = np.array(img)
cv2.imshow('frame', img)
if cv2.waitKey(0) & 0xff == ord(' '):
    cv2.destroyAllWindows()
打开网页游戏后,运行程序首先显示截图界面,用户用鼠标点击来确定游戏场景的范围(点击左上和右下),目的是为了减少之后处理的代码量。

while True:
    t0 = time.time()
    img = ss.grab(bbox=(pLeftTop[0],pLeftTop[1],pRightBottom[0],pRightBottom[1]), childprocess=False, backend='imagemagick') #'imagemagick' runs fastest acording my test.
    t1 = time.time()
    print(round(t1-t0, 2))
    target = np.array(img)
    print(target.shape)
    if target.shape[-1] != 3:
        gray = target.reshape((target.shape[0],target.shape[1],1))
    else:
        gray = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
    if gray[1,1] < 150 and gray[1,1] > 130: #The Grayscale value of green background in the finishing page is 140
        break
    ret, thresh = cv2.threshold(gray, 5, 255, cv2.THRESH_BINARY_INV)
    thresh = cv2.erode(thresh, None, iterations=5)
    im, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    num = 0
    for c in contours:
        topMost = tuple(c[c[:,:,1].argmin()][0])
        bottomMost = tuple(c[c[:,:,1].argmax()][0])
        if bottomMost[1]-topMost[1] < 50:
            continue
        pointX = int(bottomMost[0])
        pointY = int(bottomMost[1])
        cv2.circle(thresh, (pointX, pointY), 2, 125, 2)
        realX = pointX + pLeftTop[0]
        realY = pointY + pLeftTop[1]
        os.system('xdotool mousemove '+ str(realX)+' '+str(realY))
        os.system('xdotool click 1')
        print(realX, realY)
        count += 1
    if count >= 12345:
        break
    #cv2.imwrite(str(count)+'.png', thresh)
    #cv2.imwrite(str(count)+'.1.png',target)
    time.sleep(0.1)

然后进入while循环进行处理,这里有几点要说一下。经过测试,在我的渣本上用pyscreenshot截一张1300x768的图片要耗时0.6秒左右,这段时间游戏早就跑没了,所以要减少时间的瓶颈,首先缩小截图范围,其次利用一次截图尽可能做更多的操作。缩小截图范围就是根据用户点击的位置来做,而对于利用一次截图尽可能做更多操作,需要判断好黑块的位置。这里我尝试过好几种方式,最后最简单也最有效的是找最低点,如下:

【好玩的计算机视觉】自动玩“别踩白块儿”_第3张图片

【好玩的计算机视觉】自动玩“别踩白块儿”_第4张图片

上面二值图片中的灰色小点就是找到的每个黑块儿的最低点,也就是点击的点。

</pre><pre code_snippet_id="1742613" snippet_file_name="blog_20160703_3_102017" name="code" class="python">topMost = tuple(c[c[:,:,1].argmin()][0])
bottomMost = tuple(c[c[:,:,1].argmax()][0])
上面代码可以获取目标的最高点和最低点。所以我在程序中经过二值化后的目标,再进行一次腐蚀erode操作,然后找到每个分离目标的最低点,尽可能一次多点击几个目标,因为用linux下的xdotool操作鼠标是非常快的。最后要说的一点是程序最后的sleep的时间,因为点击黑块之后整体场景会向下移动,而且越来越快,截一张图的时间游戏场景的位置就会发生变化,所以我延时0.1秒之后才进行新一轮的处理,这样正确率更高。当然,如果笔记本性能足够,完全没必要sleep哈:-)





演示视频:http://www.bilibili.com/video/av5177461/

完整代码:https://github.com/littlethunder/pianoTiles


转载请注明: 转自http://blog.csdn.net/littlethunder/article/details/51816511


你可能感兴趣的:(游戏,opencv,python3,计算机视觉,别踩白块儿)