【每日随记】Opencv QQ炫舞2自动跳舞
2023-04-10 / 0 评论 / 122 阅读 / 13 点赞

【每日随记】Opencv QQ炫舞2自动跳舞

发光的神
2023-04-10 / 0 评论 / 122 阅读 / 正在检测是否收录...

简介

最近写的一个基于Opencv视觉检测的游戏脚本(某炫舞2),可以辅助玩家在游戏中传统模式自动跳舞,通过对游戏画面的识别检测出目标需要按下的方向键或空格键,利用pynput模块模拟键盘操作来实现自动跳舞的效果。

实现过程

1.寻找游戏窗口并实时获取窗口大小,对游戏画面中的特定区域实时截图并其转换为灰度图像。
2.预先准备好的方向键和空格键的图片进行图案匹配,在游戏画面中检测出它们的位置。
3.根据匹配结果,按照从左到右的顺序依次模拟按下需要的按键,来实现自动跳舞的效果。

注意:游戏窗口大小要设置为:1280x720

import numpy as np
import win32gui
import mss, os
import cv2 as cv
from pynput.keyboard import Controller, Key

# @Author  > 忆梦
# @Date    > 2023/4/10
# @Project > QQ炫舞2 目标识别 - 自动跳舞(传统模式)

window_name = 'Auto'
path = "./img/"
threshold = 0.8 # 设置阈值为0.8

sct = mss.mss()
keyboard = Controller()

def press(keys):
    keyboard.press(keys)
    keyboard.release(keys)


template_data = [
    {'name': 'right', 'file': 'right.png'},
    {'name': 'left', 'file': 'left.png'},
    {'name': 'up', 'file': 'up.png'},
    {'name': 'down', 'file': 'down.png'},
    {'name': 'space', 'file': 'en.png'},
]

keys = {
    'right': Key.right,
    'left': Key.left,
    'up': Key.up,
    'down': Key.down,
}

for tpl in template_data:
    tpl['path'] = os.path.join(path, tpl['file'])
    tpl['image'] = cv.imread(tpl['path'], cv.IMREAD_GRAYSCALE)


def main():
  
    while True:
        boxes = []
        hwnd = win32gui.FindWindow(None, "QQ炫舞2")
        cleft, ctop, cright, cbottom = win32gui.GetWindowRect(hwnd)
        c_width, cheight = cright - cleft, cbottom - ctop

        monitor = {
            'left': cleft + 475,
            'top': ctop + 481,
            'width': c_width // 2 - 290,
            'height': cheight // 2 - 294,
        }

        img = np.array(sct.grab(monitor))
        game_area = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

        for tpl in template_data:
            template = tpl['image']

            h, w = template.shape
            res = cv.matchTemplate(game_area, template, cv.TM_CCOEFF_NORMED)
            loc = np.where(res >= threshold)

            found_pts = []
            for pt in zip(*loc[::-1]):
                center_pt = (pt[0] + w // 2, pt[1] + h // 2)
                is_close_to_existing_point = False
                for found_pt in found_pts:
                    if np.linalg.norm(np.array(center_pt) - np.array(found_pt)) < w // 2:
                        is_close_to_existing_point = True
                        break

                if is_close_to_existing_point:
                    continue

                found_pts.append(center_pt)

                if tpl['name'] == "space":
                    if pt[0] >= 293 and pt[0] <= 320:
                        press(Key.space)

                boxes.append({'name': tpl['name'], 'pt': pt})
                cv.rectangle(
                    img, pt, (pt[0] + w, pt[1] + h), (0, 255, 255), 2)

        boxes = sorted(boxes, key=lambda k: k['pt'][0])
        found_names = [box['name'] for box in boxes]

        for key in found_names:
            if key != "space":
                press(keys[key])

        cv.imshow(window_name, img)
        if cv.waitKey(1) & 0xFF == ord('q'):
            break
    cv.destroyAllWindows()


if __name__ == '__main__':
    try:
        main()
    except Exception as e:
        print(e)

效果

lgn84f9v.png

13

评论 (0)

取消
0:00