使用yolov5玩dnf

使用yolov5目标检测算法对游戏界面进行监控,通过设计算法来控制角色玩dnf

超级详细的视频讲解链接:https://www.bilibili.com/video/BV18r4y1A7BF
github源码链接:https://github.com/c925777075/yolov5-dnf

1. 屏幕画面抓取

使用win32对屏幕进行实时抓取

import cv2
import numpy as np
import win32gui, win32ui, win32con, win32api

def grab_screen(region=None):

    hwin = win32gui.GetDesktopWindow()

    if region:
            left,top,x2,y2 = region
            width = x2 - left + 1
            height = y2 - top + 1
    else:
        width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)
        height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)
        left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
        top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)

    hwindc = win32gui.GetWindowDC(hwin)
    srcdc = win32ui.CreateDCFromHandle(hwindc)
    memdc = srcdc.CreateCompatibleDC()
    bmp = win32ui.CreateBitmap()
    bmp.CreateCompatibleBitmap(srcdc, width, height)
    memdc.SelectObject(bmp)
    memdc.BitBlt((0, 0), (width, height), srcdc, (left, top), win32con.SRCCOPY)
    
    signedIntsArray = bmp.GetBitmapBits(True)
    img = np.fromstring(signedIntsArray, dtype='uint8')
    img.shape = (height,width,4)

    srcdc.DeleteDC()
    memdc.DeleteDC()
    win32gui.ReleaseDC(hwin, hwindc)
    win32gui.DeleteObject(bmp.GetHandle())

    return img

将抓取好的游戏画面存入到指定的文件夹下。
然后是按键,按键可以通过win32和ctype同时协作(一开始我完全使用的是win32,后来发现dnf反外挂屏蔽虚拟按键,所以我又引入了ctype做虚拟按键)。

# coding=utf-8
import win32con
import win32api
import time

key_map = {
    "0": 49, "1": 50, "2": 51, "3": 52, "4": 53, "5": 54, "6": 55, "7": 56, "8": 57, "9": 58,
    "A": 65, "B": 66, "C": 67, "D": 68, "E": 69, "F": 70, "G": 71, "H": 72, "I": 73, "J": 74,
    "K": 75, "L": 76, "M": 77, "N": 78, "O": 79, "P": 80, "Q": 81, "R": 82, "S": 83, "T": 84,
    "U": 85, "V": 86, "W": 87, "X": 88, "Y": 89, "Z": 90, "LEFT": 37, "UP": 38, "RIGHT": 39,
    "DOWN": 40, "CTRL": 17, "ALT": 18, "F2": 113, "ESC": 27, "SPACE": 32, "NUM0": 96
}


def key_down(key):
    """
    函数功能:按下按键
    参    数:key:按键值
    """
    key = key.upper()
    vk_code = key_map[key]
    win32api.keybd_event(vk_code, win32api.MapVirtualKey(vk_code, 0), 0, 0)


def key_up(key):
    """
    函数功能:抬起按键
    参    数:key:按键值
    """
    key = key.upper()
    vk_code = key_map[key]
    win32api.keybd_event(vk_code, win32api.MapVirtualKey(vk_code, 0), win32con.KEYEVENTF_KEYUP, 0)


def key_press(key):
    """
    函数功能:点击按键(按下并抬起)
    参    数:key:按键值
    """
    key_down(key)
    time.sleep(0.02)
    key_up(key)
    time.sleep(0.01)

####################################
import ctypes
import time

SendInput = ctypes.windll.user32.SendInput

W = 0x11
A = 0x1E
S = 0x1F
D = 0x20

M = 0x32
J = 0x24
K = 0x25
LSHIFT = 0x2A
R = 0x13  # 用R代替识破
V = 0x2F

Q = 0x10
I = 0x17
O = 0x18
P = 0x19
C = 0x2E
F = 0x21

up = 0xC8
down = 0xD0
left = 0xCB
right = 0xCD

direct_dic = {"UP": 0xC8, "DOWN": 0xD0, "LEFT": 0xCB, "RIGHT": 0xCD}

esc = 0x01

# C struct redefinitions
PUL = ctypes.POINTER(ctypes.c_ulong)


class KeyBdInput(ctypes.Structure):
    _fields_ = [("wVk", ctypes.c_ushort),
                ("wScan", ctypes.c_ushort),
                ("dwFlags", ctypes.c_ulong),
                ("time", ctypes.c_ulong),
                ("dwExtraInfo", PUL)]


class HardwareInput(ctypes.Structure):
    _fields_ = [("uMsg", ctypes.c_ulong),
                ("wParamL", ctypes.c_short),
                ("wParamH", ctypes.c_ushort)]


class MouseInput(ctypes.Structure):
    _fields_ = [("dx", ctypes.c_long),
                ("dy", ctypes.c_long),
                ("mouseData", ctypes.c_ulong),
                ("dwFlags", ctypes.c_ulong),
                ("time", ctypes.c_ulong),
                ("dwExtraInfo", PUL)]


class Input_I(ctypes.Union):
    _fields_ = [("ki", KeyBdInput),
                ("mi", MouseInput),
                ("hi", HardwareInput)]


class Input(ctypes.Structure):
    _fields_ = [("type", ctypes.c_ulong),
                ("ii", Input_I)]


# Actuals Functions

def PressKey(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput(0, hexKeyCode, 0x0008, 0, ctypes.pointer(extra))
    x = Input(ctypes.c_ulong(1), ii_)
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))


def ReleaseKey(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput(0, hexKeyCode, 0x0008 | 0x0002, 0, ctypes.pointer(extra))
    x = Input(ctypes.c_ulong(1), ii_)
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))


def defense():
    PressKey(M)
    time.sleep(0.05)
    ReleaseKey(M)
    # time.sleep(0.1)


def attack():
    PressKey(J)
    time.sleep(0.05)
    ReleaseKey(J)
    # time.sleep(0.1)


def go_forward():
    PressKey(W)
    time.sleep(0.4)
    ReleaseKey(W)


def go_back():
    PressKey(S)
    time.sleep(0.4)
    ReleaseKey(S)


def go_left():
    PressKey(A)
    time.sleep(0.4)
    ReleaseKey(A)


def go_right():
    PressKey(D)
    time.sleep(0.4)
    ReleaseKey(D)


def jump():
    PressKey(K)
    time.sleep(0.1)
    ReleaseKey(K)
    # time.sleep(0.1)


def dodge():  # 闪避
    PressKey(R)
    time.sleep(0.1)
    ReleaseKey(R)
    # time.sleep(0.1)


def lock_vision():
    PressKey(V)
    time.sleep(0.3)
    ReleaseKey(V)
    time.sleep(0.1)


def go_forward_QL(t):
    PressKey(W)
    time.sleep(t)
    ReleaseKey(W)


def turn_left(t):
    PressKey(left)
    time.sleep(t)
    ReleaseKey(left)


def turn_up(t):
    PressKey(up)
    time.sleep(t)
    ReleaseKey(up)


def turn_right(t):
    PressKey(right)
    time.sleep(t)
    ReleaseKey(right)


def F_go():
    PressKey(F)
    time.sleep(0.5)
    ReleaseKey(F)


def forward_jump(t):
    PressKey(W)
    time.sleep(t)
    PressKey(K)
    ReleaseKey(W)
    ReleaseKey(K)


def press_esc():
    PressKey(esc)
    time.sleep(0.3)
    ReleaseKey(esc)


def dead():
    PressKey(M)
    time.sleep(0.5)
    ReleaseKey(M)

if __name__ == "__main__":
    time1 = time.time()
    k = "LEFT"
    s = "D"
    while True:
        if abs(time.time() - time1) > 10:
            break
        else:
            # if k not in ["LEFT", "RIGHT", "UP", "DOWN"]:
            #     key_press(k)
            # else:
            #     PressKey(direct_dic[k])
            #     time.sleep(0.1)
            #     ReleaseKey(direct_dic[k])
            #     time.sleep(0.2)
            PressKey(direct_dic[k])
            key_down(s)
            time.sleep(0.02)
            key_up(s)
            ReleaseKey(direct_dic[k])
            time.sleep(0.02)


2. yolov5数据及制作。

安装插件labelme:pip install labelme
安装好之后直接在prompt中输入labelme即可打开标注工具,labelme的使用十分简单,我们需要对游戏内所控制的角色,怪物,掉地上的材料,传送门,以及boss做矩形框标注,给给与他们一些标签。标注后的文件被保存为json格式,但是yolo系列算法所需要的标注信息是txt格式,因此我们需要一个脚本给数据做转换,代码如下:


import json
import os

name2id = {'hero': 0, 'small_map': 1, "monster": 2, 'money': 3, 'material': 4, 'door': 5, 'BOSS': 6, 'box': 7, 'options': 8}
               
def convert(img_size, box):
    dw = 1./(img_size[0])
    dh = 1./(img_size[1])
    x = (box[0] + box[2])/2.0 - 1
    y = (box[1] + box[3])/2.0 - 1
    w = box[2] - box[0]
    h = box[3] - box[1]
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    return (x,y,w,h)
 
 
def decode_json(json_floder_path,json_name):
 
    txt_name = 'E:\\Computer_vision\\object_DNF\\datasets\\guiqi\\yolo5_datasets\\labels\\' + json_name[0:-5] + '.txt'
    txt_file = open(txt_name, 'w')
 
    json_path = os.path.join(json_floder_path, json_name)
    data = json.load(open(json_path, 'r', encoding='gb2312'))
 
    img_w = data['imageWidth']
    img_h = data['imageHeight']
 
    for i in data['shapes']:
        
        label_name = i['label']
        if (i['shape_type'] == 'rectangle'):
            print(txt_name)
            x1 = int(i['points'][0][0])
            y1 = int(i['points'][0][1])
            x2 = int(i['points'][1][0])
            y2 = int(i['points'][1][1])
 
            bb = (x1,y1,x2,y2)
            bbox = convert((img_w,img_h),bb)
            txt_file.write(str(name2id[label_name]) + " " + " ".join([str(a) for a in bbox]) + '\n')
    
if __name__ == "__main__":
    
    json_floder_path = r'E:\Computer_vision\object_DNF\datasets\guiqi\yolo5_datasets\labels_json'
    json_names = os.listdir(json_floder_path)
    for json_name in json_names:
        decode_json(json_floder_path,json_name)

3. 训练yolov5s模型

在这里我们使用的是yolov5s,因为5s作为最小的yolo系列模型可以实现高效的实时监测,yolov5可通过在github源码中找到,因此这里我给出一些我训练的参数:

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', type=str, default=r'E:\Computer_vision\yolov5\YOLO5\yolov5-master\weights\yolov5s.pt', help='initial weights path')
    parser.add_argument('--cfg', type=str, default=r'E:\Computer_vision\yolov5\YOLO5\yolov5-master\models\yolov5s_rga.yaml', help='model.yaml path')#网络配置
    parser.add_argument('--data', type=str, default=r'E:\Computer_vision\yolov5\YOLO5\DNF\data.yaml', help='data.yaml path')#数据
    parser.add_argument('--hyp', type=str, default='data/hyp.scratch.yaml', help='hyperparameters path')
    parser.add_argument('--epochs', type=int, default=200)
    parser.add_argument('--batch-size', type=int, default=8, help='total batch size for all GPUs')
    parser.add_argument('--img-size', nargs='+', type=int, default=[608, 608], help='[train, test] image sizes')
    parser.add_argument('--rect', action='store_true', default=False, help='rectangular training')#矩形训练
    parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')#接着之前的训练
    parser.add_argument('--nosave', action='store_true', help=' only save final checkpoint')#不保存
    parser.add_argument('--notest', action='store_true', help='only test final epoch')#不测试
    parser.add_argument('--noautoanchor', action='store_true', default=False, help='disable autoanchor check')#是否调整候选框
    parser.add_argument('--evolve', action='store_true', default=False, help='evolve hyperparameters')#超参数更新
    parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
    parser.add_argument('--cache-images', action='store_true', default=True, help='cache images for faster training')#缓存图片
    parser.add_argument('--image-weights', action='store_true', default=True, help='use weighted image selection for training')
    parser.add_argument('--name', default='', help='renames experiment folder exp{N} to exp{N}_{name} if supplied')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--multi-scale', action='store_true', default=False, help='vary img-size +/- 50%%')#是否多尺度训练
    parser.add_argument('--single-cls', action='store_true', help='train as single-class dataset')#是否一个类别
    parser.add_argument('--adam', action='store_true', default=False, help='use torch.optim.Adam() optimizer')#优化器选择
    parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')#跨GPU的BN
    parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')#GPU ID
    parser.add_argument('--logdir', type=str, default='DNF_runs/', help='logging directory')
    parser.add_argument('--workers', type=int, default=0, help='maximum number of dataloader workers')#windows的同学别改
    opt = parser.parse_args()
    print(opt)
```python
在这里插入代码片

4. 开始玩游戏了

我们将训练好的yolov5模型加载,然后通过实时的屏幕抓取对每一帧图像做目标检测,如果检测到图片中有怪物和自身角色,那么记录自己的坐标和怪物的坐标,通过虚拟按键向怪物所在位置移动;如果怪物没清空了并且地上有掉落的材料,那么控制角色靠近材料所在的坐标;如果怪物和材料都不存在,那么控制角色走向传送门的位置,即走向下一个房间,具体细节和原理在b站视频中有详细的介绍,这里给出部分代码:

main:

import numpy as np
from grabscreen import grab_screen
import cv2
import time
import directkeys
import torch
from torch.autograd import Variable
from directkeys import PressKey, ReleaseKey, key_down, key_up
from getkeys import key_check
from utils.torch_utils import select_device, load_classifier, time_synchronized
from utils.general import (
    check_img_size, non_max_suppression, apply_classifier, scale_coords,
    xyxy2xywh, xywh2xyxy, plot_one_box, strip_optimizer, set_logging)
from models.experimental import attempt_load
from direction_move import move
from small_recgonize import current_door, next_door
from skill_recgnize import skill_rec
import random

def letterbox(img, new_shape=(640, 640), color=(114, 114, 114), auto=False, scaleFill=False, scaleup=True):
    # Resize image to a 32-pixel-multiple rectangle https://github.com/ultralytics/yolov3/issues/232
    shape = img.shape[:2]  # current shape [height, width]
    if isinstance(new_shape, int):
        new_shape = (new_shape, new_shape)

    # Scale ratio (new / old)
    r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
    if not scaleup:  # only scale down, do not scale up (for better test mAP)
        r = min(r, 1.0)

    # Compute padding
    ratio = r, r  # width, height ratios
    new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
    dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh padding
    if auto:  # minimum rectangle
        dw, dh = np.mod(dw, 64), np.mod(dh, 64)  # wh padding
    elif scaleFill:  # stretch
        dw, dh = 0.0, 0.0
        new_unpad = (new_shape[1], new_shape[0])
        ratio = new_shape[1] / shape[1], new_shape[0] / shape[0]  # width, height ratios

    dw /= 2  # divide padding into 2 sides
    dh /= 2

    if shape[::-1] != new_unpad:  # resize
        img = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR)
    top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
    left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
    img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add border
    return img, ratio, (dw, dh)

# 设置所有用到的参数
weights = r'E:\Computer_vision\yolov5\YOLO5\yolov5-master\DNF_runs\4s\weights\best.pt'    #yolo5 模型存放的位置
# weights = r'F:\Computer_vision\yolov5\YOLO5\yolov5-master\runs\exp0\weights\best.pt'
device = torch.device("cuda:0") if torch.cuda.is_available() else torch.device("cpu")
# device = torch.device("cpu")
model = attempt_load(weights, map_location=device)  # load FP32 model
window_size = (0,0,1280,800)          # 截屏的位置
img_size = 608                      # 输入到yolo5中的模型尺寸
paused = False
half = device.type != 'cpu'
view_img = True                     # 是否观看目标检测结果
save_txt = False
conf_thres = 0.3                    # NMS的置信度过滤
iou_thres = 0.2                     # NMS的IOU阈值
classes = None
agnostic_nms = False                # 不同类别的NMS时也参数过滤
skill_char = "XYHGXFAXDSWXETX"          # 技能按键,使用均匀分布随机抽取
direct_dic = {"UP": 0xC8, "DOWN": 0xD0, "LEFT": 0xCB, "RIGHT": 0xCD}    # 上下左右的键码
names = ['hero', 'small_map', "monster", 'money', 'material', 'door', 'BOSS', 'box', 'options']   # 所有类别名
colors = [[random.randint(0, 255) for _ in range(3)] for _ in range(len(names))]
if half:
    model.half()  # to FP16
action_cache = None  # 动作标记
press_delay = 0.1  # 按压时间
release_delay = 0.1  # 释放时间
# last_time = time.time()
frame = 0  # 帧
door1_time_start = -20
next_door_time = -20
fs = 1 # 每四帧处理一次

# 倒计时
for i in list(range(5))[::-1]:
    print(i + 1)
    time.sleep(1)

# 捕捉画面+目标检测+玩游戏
while True:
    if not paused:
        t_start = time.time()
        img0 = grab_screen(window_size)
        frame += 1
        if frame % fs == 0:
            # img0 = cv2.imread("datasets/guiqi/yolo5_datasets/imgs/1004_14.jpg")
            img0 = cv2.cvtColor(img0, cv2.COLOR_BGRA2BGR)
            # Padded resize
            img = letterbox(img0, new_shape=img_size)[0]

            # Convert
            img = img[:, :, ::-1].transpose(2, 0, 1)  # BGR to RGB
            img = np.ascontiguousarray(img)

            img = torch.from_numpy(img).to(device).unsqueeze(0)
            img = img.half() if half else img.float()  # uint8 to fp16/32
            img /= 255.0  # 0 - 255 to 0.0 - 1.0

            pred = model(img, augment=False)[0]

            # Apply NMS
            det = non_max_suppression(pred, conf_thres, iou_thres, classes=classes, agnostic=agnostic_nms)
            gn = torch.tensor(img0.shape)[[1, 0, 1, 0]]
            det = det[0]
            if det is not None and len(det):
                # Rescale boxes from img_size to im0 size
                det[:, :4] = scale_coords(img.shape[2:], det[:, :4], img0.shape).round()

                # Print results
                for c in det[:, -1].unique():
                    n = (det[:, -1] == c).sum()  # detections per class

                img_object = []
                cls_object = []
                # Write results
                hero_conf = 0
                hero_index = 0
                for idx, (*xyxy, conf, cls) in enumerate(reversed(det)):
                    # if save_txt:  # Write to file
                    #     xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()  # normalized xywh
                    #     with open(txt_path + '.txt', 'a') as f:
                    #         f.write(('%g ' * 5 + '\n') % (cls, *xywh))  # label format

                    xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4))).view(-1).tolist()
                    cls = int(cls)
                    img_object.append(xywh)
                    cls_object.append(names[cls])

                    if names[cls] == "hero" and conf > hero_conf:
                        hero_conf = conf
                        hero_index = idx


                    if view_img:  # Add bbox to image
                        label = '%s %.2f' % (names[int(cls)], conf)
                        plot_one_box(xyxy, img0, label=label, color=colors[int(cls)], line_thickness=2)

                # 游戏
                thx = 30    # 捡东西时,x方向的阈值
                thy = 30    # 捡东西时,y方向的阈值
                attx = 150   # 攻击时,x方向的阈值
                atty = 50   # 攻击时,y方向的阈值

                if current_door(img0) == 1 and time.time() - door1_time_start > 10:
                    door1_time_start = time.time()
                    # move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
                    #      release_delay=release_delay)
                    # ReleaseKey(direct_dic["RIGHT"])
                    # directkeys.key_press("SPACE")
                    directkeys.key_press("CTRL")
                    time.sleep(1)
                    directkeys.key_press("ALT")
                    time.sleep(0.5)
                    action_cache = None
                # 扫描英雄
                if "hero" in cls_object:
                    # hero_xywh = img_object[cls_object.index("hero")]
                    hero_xywh = img_object[hero_index]
                    cv2.circle(img0, (int(hero_xywh[0]), int(hero_xywh[1])), 1, (0,0,255), 10)
                    # print(hero_index)
                    # print(cls_object.index("hero"))
                else:
                    continue
                # 打怪
                if "monster" in cls_object or "BOSS" in cls_object:
                    min_distance = float("inf")
                    for idx, (c, box) in enumerate(zip(cls_object, img_object)):
                        if c == 'monster' or c == "BOSS":
                            dis = ((hero_xywh[0] - box[0])**2 + (hero_xywh[1] - box[1])**2)**0.5
                            if dis < min_distance:
                                monster_box = box
                                monster_index = idx
                                min_distance = dis
                    if abs(hero_xywh[0] - monster_box[0]) < attx and abs(hero_xywh[1] - monster_box[1]) < atty:
                        if "BOSS" in cls_object:
                            directkeys.key_press("R")
                            directkeys.key_press("Q")
                            # time.sleep(0.5)
                            skill_name = skill_char[int(np.random.randint(len(skill_char), size=1)[0])]
                            while True:
                                if skill_rec(skill_name, img0):
                                    directkeys.key_press(skill_name)
                                    directkeys.key_press(skill_name)
                                    directkeys.key_press(skill_name)
                                    break
                                else:
                                    skill_name = skill_char[int(np.random.randint(len(skill_char), size=1)[0])]

                        else:
                            skill_name = skill_char[int(np.random.randint(len(skill_char), size=1)[0])]
                            while True:
                                if skill_rec(skill_name, img0):
                                    directkeys.key_press(skill_name)
                                    directkeys.key_press(skill_name)
                                    directkeys.key_press(skill_name)
                                    break
                                else:
                                    skill_name = skill_char[int(np.random.randint(len(skill_char), size=1)[0])]
                        print("释放技能攻击")
                        if not action_cache:
                            pass
                        elif action_cache not in ["LEFT", "RIGHT", "UP", "DOWN"]:
                            ReleaseKey(direct_dic[action_cache.strip().split("_")[0]])
                            ReleaseKey(direct_dic[action_cache.strip().split("_")[1]])
                            action_cache = None
                        elif action_cache:
                            ReleaseKey(direct_dic[action_cache])
                            action_cache = None
                        # break
                    elif monster_box[1] - hero_xywh[1] < 0 and monster_box[0] - hero_xywh[0] > 0:
                        if abs(monster_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="RIGHT", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - monster_box[1] < monster_box[0] - hero_xywh[0]:
                            action_cache = move(direct="RIGHT_UP", material=True, action_cache=action_cache,
                                                press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - monster_box[1] >= monster_box[0] - hero_xywh[0]:
                            action_cache = move(direct="UP", material=True, action_cache=action_cache,
                                                    press_delay=press_delay,
                                                    release_delay=release_delay)
                        # break
                    elif monster_box[1] - hero_xywh[1] < 0 and monster_box[0] - hero_xywh[0] < 0:
                        if abs(monster_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="LEFT", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - monster_box[1] < hero_xywh[0] - monster_box[0]:
                            action_cache = move(direct="LEFT_UP", material=True, action_cache=action_cache,
                                                    press_delay=press_delay,
                                                    release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - monster_box[1] >= hero_xywh[0] - monster_box[0]:
                            action_cache = move(direct="UP", material=True, action_cache=action_cache,
                                                    press_delay=press_delay,
                                                    release_delay=release_delay)
                            # break
                    elif monster_box[1] - hero_xywh[1] > 0 and monster_box[0] - hero_xywh[0] < 0:
                        if abs(monster_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="LEFT", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif monster_box[1] - hero_xywh[1] < hero_xywh[0] - monster_box[0]:
                            action_cache = move(direct="LEFT_DOWN", material=True, action_cache=action_cache,
                                                    press_delay=press_delay,
                                                    release_delay=release_delay)
                            # break
                        elif monster_box[1] - hero_xywh[1] >= hero_xywh[0] - monster_box[0]:
                            action_cache = move(direct="DOWN", material=True, action_cache=action_cache,
                                                    press_delay=press_delay,
                                                    release_delay=release_delay)
                            # break
                    elif monster_box[1] - hero_xywh[1] > 0 and monster_box[0] - hero_xywh[0] > 0:
                        if abs(monster_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="RIGHT", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif monster_box[1] - hero_xywh[1] < monster_box[0] - hero_xywh[0]:
                            action_cache = move(direct="RIGHT_DOWN", material=True, action_cache=action_cache,
                                                    press_delay=press_delay,
                                                    release_delay=release_delay)
                            # break
                        elif monster_box[1] - hero_xywh[1] >= monster_box[0] - hero_xywh[0]:
                            action_cache = move(direct="DOWN", material=True, action_cache=action_cache,
                                                    press_delay=press_delay,
                                                    release_delay=release_delay)
                            # break

                # 移动到下一个地图
                if "door" in cls_object and "monster" not in cls_object and "BOSS" not in cls_object and "material" not in cls_object and "money" not in cls_object:
                    for idx, (c, box) in enumerate(zip(cls_object, img_object)):
                        if c == 'door':
                            door_box = box
                            door_index = idx
                    if door_box[0] < img0.shape[0] // 2:
                        action_cache = move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
                                            release_delay=release_delay)
                        # break
                    elif door_box[1] - hero_xywh[1] < 0 and door_box[0] - hero_xywh[0] > 0:
                        if abs(door_box[1] - hero_xywh[1]) < thy and abs(door_box[0] - hero_xywh[0]) < thx:
                            action_cache = None
                            print("进入下一地图")
                            # break
                        elif abs(door_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - door_box[1] < door_box[0] - hero_xywh[0]:
                            action_cache = move(direct="RIGHT_UP", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - door_box[1] >= door_box[0] - hero_xywh[0]:
                            action_cache = move(direct="UP", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                    elif door_box[1] - hero_xywh[1] < 0 and door_box[0] - hero_xywh[0] < 0:
                        if abs(door_box[1] - hero_xywh[1]) < thy and abs(door_box[0] - hero_xywh[0]) < thx:
                            action_cache = None
                            print("进入下一地图")
                            # break
                        elif abs(door_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="LEFT", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - door_box[1] < hero_xywh[0] - door_box[0]:
                            action_cache = move(direct="LEFT_UP", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - door_box[1] >= hero_xywh[0] - door_box[0]:
                            action_cache = move(direct="UP", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                    elif door_box[1] - hero_xywh[1] > 0 and door_box[0] - hero_xywh[0] < 0:
                        if abs(door_box[1] - hero_xywh[1]) < thy and abs(door_box[0] - hero_xywh[0]) < thx:
                            action_cache = None
                            print("进入下一地图")
                            # break
                        elif abs(door_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="LEFT", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif door_box[1] - hero_xywh[1] < hero_xywh[0] - door_box[0]:
                            action_cache = move(direct="LEFT_DOWN", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif door_box[1] - hero_xywh[1] >= hero_xywh[0] - door_box[0]:
                            action_cache = move(direct="DOWN", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                    elif door_box[1] - hero_xywh[1] > 0 and door_box[0] - hero_xywh[0] > 0:
                        if abs(door_box[1] - hero_xywh[1]) < thy and abs(door_box[0] - hero_xywh[0]) < thx:
                            action_cache = None
                            print("进入下一地图")
                            # break
                        elif abs(door_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif door_box[1] - hero_xywh[1] < door_box[0] - hero_xywh[0]:
                            action_cache = move(direct="RIGHT_DOWN", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif door_box[1] - hero_xywh[1] >= door_box[0] - hero_xywh[0]:
                            action_cache = move(direct="DOWN", action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                if "money" not in cls_object and "material" not in cls_object and "monster" not in cls_object \
                        and "BOSS" not in cls_object and "door" not in cls_object and 'box' not in cls_object \
                        and 'options' not in cls_object:
                    # if next_door(img0) == 0 and abs(time.time()) - next_door_time > 10:
                    #     next_door_time = time.time()
                    #     action_cache = move(direct="LEFT", action_cache=action_cache, press_delay=press_delay,
                    #                         release_delay=release_delay)
                    #     # time.sleep(3)
                    # else:
                    #     action_cache = move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
                    #                     release_delay=release_delay)

                    action_cache = move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
                                        release_delay=release_delay)
                    # break

                # 捡材料
                if "monster" not in cls_object and "hero" in cls_object and ("material" in cls_object or "money" in cls_object):
                    min_distance = float("inf")
                    hero_xywh[1] = hero_xywh[1] + (hero_xywh[3] // 2) * 0.7
                    thx = thx / 2
                    thy = thy / 2
                    for idx, (c, box) in enumerate(zip(cls_object, img_object)):
                        if c == 'material' or c == "money":
                            dis = ((hero_xywh[0] - box[0]) ** 2 + (hero_xywh[1] - box[1]) ** 2) ** 0.5
                            if dis < min_distance:
                                material_box = box
                                material_index = idx
                                min_distance = dis
                    if abs(material_box[1] - hero_xywh[1]) < thy and abs(material_box[0] - hero_xywh[0]) < thx:
                        if not action_cache:
                            pass
                        elif action_cache not in ["LEFT", "RIGHT", "UP", "DOWN"]:
                            ReleaseKey(direct_dic[action_cache.strip().split("_")[0]])
                            ReleaseKey(direct_dic[action_cache.strip().split("_")[1]])
                            action_cache = None
                        else:
                            ReleaseKey(direct_dic[action_cache])
                            action_cache = None
                        time.sleep(1)
                        directkeys.key_press("X")
                        print("捡东西")
                        # break

                    elif material_box[1] - hero_xywh[1] < 0 and material_box[0] - hero_xywh[0] > 0:

                        if abs(material_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="RIGHT", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - material_box[1] < material_box[0] - hero_xywh[0]:
                            action_cache = move(direct="RIGHT_UP", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - material_box[1] >= material_box[0] - hero_xywh[0]:
                            action_cache = move(direct="UP", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                    elif material_box[1] - hero_xywh[1] < 0 and material_box[0] - hero_xywh[0] < 0:
                        if abs(material_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="LEFT", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - material_box[1] < hero_xywh[0] - material_box[0]:
                            action_cache = move(direct="LEFT_UP", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif hero_xywh[1] - material_box[1] >= hero_xywh[0] - material_box[0]:
                            action_cache = move(direct="UP", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                    elif material_box[1] - hero_xywh[1] > 0 and material_box[0] - hero_xywh[0] < 0:
                        if abs(material_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="LEFT", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif material_box[1] - hero_xywh[1] < hero_xywh[0] - material_box[0]:
                            action_cache = move(direct="LEFT_DOWN", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif material_box[1] - hero_xywh[1] >= hero_xywh[0] - material_box[0]:
                            action_cache = move(direct="DOWN", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                    elif material_box[1] - hero_xywh[1] > 0 and material_box[0] - hero_xywh[0] > 0:
                        if abs(material_box[1] - hero_xywh[1]) < thy:
                            action_cache = move(direct="RIGHT", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif material_box[1] - hero_xywh[1] < material_box[0] - hero_xywh[0]:
                            action_cache = move(direct="RIGHT_DOWN", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                        elif material_box[1] - hero_xywh[1] >= material_box[0] - hero_xywh[0]:
                            action_cache = move(direct="DOWN", material=True, action_cache=action_cache, press_delay=press_delay,
                                                release_delay=release_delay)
                            # break
                # 开箱子
                if "box" in cls_object:
                    box_num = 0
                    for b in cls_object:
                        if b == "box":
                            box_num += 1
                    if box_num >= 4:
                        directkeys.key_press("ESC")
                        print("打开箱子ESC")
                        # break62

                # 重新开始
                time_option = -20
                if "options" in cls_object:
                    if not action_cache:
                        pass
                    elif action_cache not in ["LEFT", "RIGHT", "UP", "DOWN"]:
                        ReleaseKey(direct_dic[action_cache.strip().split("_")[0]])
                        ReleaseKey(direct_dic[action_cache.strip().split("_")[1]])
                        action_cache = None
                    else:
                        ReleaseKey(direct_dic[action_cache])
                        action_cache = None
                    if time.time() - time_option > 10:
                        directkeys.key_press("NUM0")
                        print("移动物品到脚下")
                        directkeys.key_press("X")
                        time_option = time.time()
                    directkeys.key_press("F2")
                    print("重新开始F2")
                    # break
            t_end = time.time()
            print("一帧游戏操作所用时间:", (t_end - t_start)/fs)

            img0 = cv2.resize(img0, (600, 375))
            # Stream results
            if view_img:
                cv2.imshow('window', img0)
                # cv2.waitKey(0)
                # cv2.destroyAllWindows()
                if cv2.waitKey(5) & 0xFF == ord('q'):
                    raise StopIteration


    # Setting pause and unpause
    keys = key_check()
    if 'P' in keys:
        if not action_cache:
            pass
        elif action_cache not in ["LEFT", "RIGHT", "UP", "DOWN"]:
            ReleaseKey(direct_dic[action_cache.strip().split("_")[0]])
            ReleaseKey(direct_dic[action_cache.strip().split("_")[1]])
            action_cache = None
        else:
            ReleaseKey(direct_dic[action_cache])
            action_cache = None
        if paused:
            paused = False
            time.sleep(1)
        else:
            paused = True
            time.sleep(1)


OK,以上就是使用yolov5玩dnf的大致流程了,详细请关注B站视频和github源码。

上一篇:[LeetCode] 689. Maximum Sum of 3 Non-Overlapping Subarrays 三个非重叠子数组的最大和


下一篇:Java知识弥补-Android开发