当前位置:   article > 正文

利用yolov5和模板匹配制作游戏自动化脚本_yolo 游戏脚本

yolo 游戏脚本

大家好,今天为大家带来原神自动刷副本的脚本,先看看效果。

1、脚本思路:

1、找到进入副本的特征,根据这个特征让角色移动到挑战地点。

2、当角色到达挑战地点,找到副本挑战开始的信号。

3、挑战开始后,根据队伍预设的指令进行攻击,一直循环直到挑战成功。

4、找到挑战成功的标识,以此来结束攻击循环。

5、识别周围环境,寻找领奖位置

6、移动到领奖处,识别可以领取奖励的标志,并按照指令领奖。

2、代码前的准备:

        由脚本思路中,我们需要准备通关副本的各种数据(脚本思路下划线部分)。

        首先,对于其中一些简单的标识,在电脑屏幕上持续时间长且容易识别,采用模板匹配算法

        模板匹配就是将特征图在一张图片里不停的移动并进行匹配,根据匹配相似度得到最高值,具体就不在这里说了。说回到简单的标识,比如,开启副本的标识,挑战位置的标识,等等。这些都是固定的标识。这些标识如下:

        得到了这些标识,也就是所谓特征。那么我们需要将标识在一张图片里移动,找到相似度最高的值(模板匹配算法)。那么这个图片在哪里来呢?当然是我们的屏幕,但是把全屏放进去是不好的,这样运算速度比较慢,我们选择将屏幕部分区域截取下来,让这些特征在区域内进行匹配,这样大大节省了时间。

        但是这些区域怎么获得呢?这个根据自己的显示屏大小来确定了。以我的为例:

        tree_pos为石化古树的位置(874,278),(1042,321)分别代表了这个区域左上角和右下角点在屏幕上的位置坐标。这样,将所有需要匹配的特征加载进来,已经这些匹配区域的位置信息得到,就能进行识别。

        上面说完了简单的标识,对于不那么简单的标识,模板匹配就不那么好用了。例如在战斗过后,找寻领奖位置。在战斗中难免有碰撞,导致位置不一样,包括视角转动这些,在进行匹配就不那么好找了,当然可以选择降低阈值,但很多时候仍然不容易找到。选择用YOLO进行识别。效果图如下:

        至此,简单和困难的标识都得到了解决,下面着手代码的编写。

3、代码

1、对于简单标识,我们需要用模板匹配识别,先定义一个识别函数:

  1. #匹配函数值
  2. def get_match_value(path,pos):
  3. area = src_area(pos)
  4. tar = cv2.imread(path)
  5. res = cv2.matchTemplate(area,tar,cv2.TM_CCOEFF_NORMED)
  6. _,max_value,_,_= cv2.minMaxLoc(res)
  7. return max_value

        函数输入值path,pos就是上面图里面的每一个特征的path和pos。

这里的src_area函数如下定义:

  1. def src_area(xyxy):
  2. im = ImageGrab.grab()
  3. r,g,b = cv2.split(np.array(im))
  4. img = cv2.merge([b,g,r])
  5. if xyxy==None:
  6. return img
  7. return img[xyxy[1]:xyxy[3],xyxy[0]:xyxy[2]]

        有了这个函数,我们就基本可以完成副本挑战一半的任务了。

2、利用识别函数识别,定义在识别后需要进行的操作

        已经说了,用这个识别函数就能做到很多事了,如下:

        1、关闭副本提示

  1. #关闭副本提示(标志)
  2. def close_tip(thr):
  3. value = get_match_value(place_tip_path,place_tip_pos)
  4. if value>=thr:
  5. time.sleep(1)
  6. mouse.click()
  7. return True
  8. return False

        2、去往挑战处

  1. #前往挑战处
  2. def go_to_start(thr):
  3. key.kevent_down('w')
  4. while True:
  5. value=get_match_value(start_path,start_pos)
  6. if value>=thr:
  7. key.kevent_up('w')
  8. key.kevent_down('f')
  9. key.kevent_up('f')
  10. break

        3、判断挑战是否成功

  1. #判断是否挑战成功
  2. def win_the_challenge(thr):
  3. value = get_match_value(end_path,end_pos)
  4. if value>=thr:
  5. return True
  6. return False

        4、去往领奖处

  1. #前往领奖处
  2. def go_to_reward(thr):
  3. while True:
  4. key.kevent_down('w')
  5. value=get_match_value(reward_path,reward_pos)
  6. if value>=thr:
  7. key.kevent_up('w')
  8. key.kevent_down('f')
  9. key.kevent_up('f')
  10. break
  11. time.sleep(0.5)
  12. key.kevent_up('w')

        5、是否有足够体力进行下一次副本

  1. #是否有足够体力
  2. def have_sz(thr):
  3. value = get_match_value(tree_path,tree_pos)
  4. if value>=thr:
  5. return False
  6. return True

        好了,到此一些简单标识能做的任务我们已经完成了。

3、定义战斗函数

        在《识别后操作》部分1、2、3中,我们通过1、2部分已经可以成功走到挑战位置并开启挑战,这时在挑战开启后执行战斗函数并通过3部分判断是否战斗胜利。战斗函数比较随意,可以根据自己的设置来配置,我的战斗函数为:

  1. #预设战斗指令
  2. def fight():
  3. time.sleep(0.4)
  4. key.kevent_down('e')
  5. time.sleep(1)
  6. key.kevent_up('e')
  7. time.sleep(0.5)
  8. key.kevent_down('2')
  9. key.kevent_up('2')
  10. time.sleep(0.5)
  11. key.kevent_down('e')
  12. key.kevent_up('e')
  13. time.sleep(1)
  14. key.kevent_down('3')
  15. key.kevent_up('3')
  16. time.sleep(0.5)
  17. key.kevent_down('e')
  18. time.sleep(0.4)
  19. for i in range(10):
  20. mouse.move_mouse((800,0))
  21. time.sleep(0.05)
  22. key.kevent_up('e')
  23. time.sleep(0.5)
  24. key.kevent_down('4')
  25. key.kevent_up('4')
  26. time.sleep(0.4)
  27. key.kevent_down('e')
  28. key.kevent_up('e')
  29. time.sleep(0.9)
  30. key.kevent_down('1')
  31. key.kevent_up('1')

4、战斗胜利后找寻领奖位置

        在《识别后操作》4部分,我们已经有了去往领奖处的函数了,但是找到领奖处却要在这里定义,这是因为领奖识别比较简单,用模板匹配容易,而找到这个位置需要用YOLO。接定义战斗函数部分后,在战斗后,我们已经识别了战斗胜利了,这时还没有操作,我们让计算机转动视角,同时将每转动一次的图像传递给YOLO模型,进行识别,识别到领奖位置后,停止转动视角。代码如下:

  1. #寻找领奖位置
  2. def find_goal(model):
  3. area = src_area(yolo_pos)
  4. xywh,conf = model.inference(area)
  5. return xywh,conf

        这里的model如下定义:

  1. class yolo_model():
  2. def __init__(self):
  3. device = ''
  4. weights = 'yolov5/runs/train/exp12/weights/best.pt' # pt
  5. data = 'yolov5/ys_data/ys.yaml' # yaml
  6. half = False
  7. dnn = False
  8. imgsz = (640, 640)
  9. self.augment = False
  10. self.max_det = 1000
  11. self.agnostic_nms = False
  12. self.classes = None
  13. self.conf_thres = 0.25 # confidence threshold
  14. self.iou_thres = 0.45
  15. # Load model
  16. device = select_device(device)
  17. self.model = DetectMultiBackend(weights, device=device, dnn=dnn, data=data, fp16=half)
  18. self.stride, names, self.pt = self.model.stride, self.model.names, self.model.pt
  19. self.imgsz = check_img_size(imgsz, s=self.stride) # check image size
  20. # Run inference
  21. self.model.warmup(imgsz=(1, 3, *imgsz)) # warmup
  22. self.dt = (Profile(), Profile(), Profile())
  23. def inference(self,im0):
  24. im = letterbox(im0, self.imgsz, stride=self.stride, auto=self.pt)[0] # padded resize
  25. im = im.transpose((2, 0, 1))[::-1] # HWC to CHW, BGR to RGB
  26. im = np.ascontiguousarray(im)
  27. with self.dt[0]:
  28. im = torch.from_numpy(im).to(self.model.device)
  29. im = im.half() if self.model.fp16 else im.float() # uint8 to fp16/32
  30. im /= 255 # 0 - 255 to 0.0 - 1.0
  31. if len(im.shape) == 3:
  32. im = im[None] # expand for batch dim
  33. # Inference
  34. with self.dt[1]:
  35. visualize = False
  36. pred = self.model(im, augment=self.augment, visualize=visualize)
  37. # NMS
  38. with self.dt[2]:
  39. pred = non_max_suppression(pred, self.conf_thres, self.iou_thres, self.classes, self.agnostic_nms, max_det=self.max_det)
  40. det = pred[0]
  41. gn = torch.tensor(im0.shape)[[1, 0, 1, 0]] # normalization gain whwh
  42. cof = None
  43. xywh = None
  44. if len(det):
  45. for *xyxy, conf, cls in reversed(det):
  46. xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()
  47. cof = conf
  48. return xywh,cof

        寻找到位置后,结合《识别后操作》4部分,我们成功来到领奖位置处并获得奖励。

5、函数汇总 

        以下是源文件,执行就可以自动化了

  1. import cv2
  2. import sys
  3. sys.path.append(r'./yolov5')
  4. from my_utils.screen_capture import src_area
  5. from model import yolo_model
  6. from my_utils.mouse_control import *
  7. import my_utils.keyboard as key
  8. import time
  9. mouse=Mouse()
  10. #匹配图形位置及路径
  11. tree_pos = [874,278,1042,321]
  12. tree_path = './img/no_sz.png'
  13. use_nssz_pos = (747,744)
  14. place_tip_pos=[853,673,1055,709]
  15. place_tip_path='./img/place_tip.png'
  16. start_pos=[1163,516,1292,561]
  17. start_path='./img/start_button.png'
  18. reward_pos = [1208,515,1349,556]
  19. reward_path = './img/reward.png'
  20. end_pos = [956,941,1082,973]
  21. end_path='./img/end.png'
  22. yolo_pos = [690,9,1214,856]
  23. #获得鼠标在屏幕的位置坐标
  24. def get_src_pos():
  25. while True:
  26. if win32api.GetAsyncKeyState(0x04)<0:
  27. pos = mouse.get_position()
  28. print(pos)
  29. while win32api.GetAsyncKeyState(0x04)<0:
  30. pass
  31. #匹配函数值
  32. def get_match_value(path,pos):
  33. area = src_area(pos)
  34. tar = cv2.imread(path)
  35. res = cv2.matchTemplate(area,tar,cv2.TM_CCOEFF_NORMED)
  36. _,max_value,_,_= cv2.minMaxLoc(res)
  37. return max_value
  38. '''
  39. if max_value>thr:
  40. print('got the target')
  41. else:
  42. print('can not find the target')
  43. '''
  44. #是否有足够体力
  45. def have_sz(thr):
  46. value = get_match_value(tree_path,tree_pos)
  47. if value>=thr:
  48. return False
  49. return True
  50. #关闭副本提示(标志)
  51. def close_tip(thr):
  52. value = get_match_value(place_tip_path,place_tip_pos)
  53. if value>=thr:
  54. time.sleep(1)
  55. mouse.click()
  56. return True
  57. return False
  58. #前往挑战处
  59. def go_to_start(thr):
  60. key.kevent_down('w')
  61. while True:
  62. value=get_match_value(start_path,start_pos)
  63. if value>=thr:
  64. key.kevent_up('w')
  65. key.kevent_down('f')
  66. key.kevent_up('f')
  67. break
  68. #前往领奖处
  69. def go_to_reward(thr):
  70. while True:
  71. key.kevent_down('w')
  72. value=get_match_value(reward_path,reward_pos)
  73. if value>=thr:
  74. key.kevent_up('w')
  75. key.kevent_down('f')
  76. key.kevent_up('f')
  77. break
  78. time.sleep(0.5)
  79. key.kevent_up('w')
  80. #预设战斗指令
  81. def fight():
  82. time.sleep(0.4)
  83. key.kevent_down('e')
  84. time.sleep(1)
  85. key.kevent_up('e')
  86. time.sleep(0.5)
  87. key.kevent_down('2')
  88. key.kevent_up('2')
  89. time.sleep(0.5)
  90. key.kevent_down('e')
  91. key.kevent_up('e')
  92. time.sleep(1)
  93. key.kevent_down('3')
  94. key.kevent_up('3')
  95. time.sleep(0.5)
  96. key.kevent_down('e')
  97. time.sleep(0.4)
  98. for i in range(10):
  99. mouse.move_mouse((800,0))
  100. time.sleep(0.05)
  101. key.kevent_up('e')
  102. time.sleep(0.5)
  103. key.kevent_down('4')
  104. key.kevent_up('4')
  105. time.sleep(0.4)
  106. key.kevent_down('e')
  107. key.kevent_up('e')
  108. time.sleep(0.9)
  109. key.kevent_down('1')
  110. key.kevent_up('1')
  111. #判断是否挑战成功
  112. def win_the_challenge(thr):
  113. value = get_match_value(end_path,end_pos)
  114. if value>=thr:
  115. return True
  116. return False
  117. #寻找领奖位置
  118. def find_goal(model):
  119. area = src_area(yolo_pos)
  120. xywh,conf = model.inference(area)
  121. return xywh,conf
  122. #退出游戏
  123. def log_out():
  124. key.kevent_down('menu')
  125. time.sleep(0.01)
  126. key.kevent_down('f4')
  127. time.sleep(0.01)
  128. key.kevent_up('f4')
  129. time.sleep(0.01)
  130. key.kevent_up('menu')
  131. def main():
  132. model = yolo_model()
  133. print('press P to start')
  134. while win32api.GetAsyncKeyState(ord('P'))>=0:
  135. pass
  136. while have_sz(0.9):
  137. time.sleep(0.2)
  138. while True:
  139. if close_tip(0.95):
  140. break
  141. time.sleep(0.5)
  142. go_to_start(0.9)
  143. time.sleep(0.5)
  144. key.kevent_down('1')
  145. key.kevent_up('1')
  146. time.sleep(0.5)
  147. while not win_the_challenge(0.9):
  148. fight()
  149. time.sleep(7)
  150. flag = True
  151. while flag:
  152. xywh,conf = find_goal(model)
  153. if conf!=None and conf>0.4:
  154. flag = False
  155. mouse.move_mouse((40,0))
  156. time.sleep(0.02)
  157. time.sleep(0.5)
  158. go_to_reward(0.9)
  159. time.sleep(0.5)
  160. mouse.set_position((747,744))#鼠标移动到浓缩树脂处
  161. time.sleep(0.02)
  162. mouse.click()
  163. time.sleep(10)
  164. mouse.set_position((1191,993))#鼠标移动到继续挑战处
  165. time.sleep(0.05)
  166. mouse.click()
  167. time.sleep(1)
  168. time.sleep(1)
  169. log_out()
  170. if __name__=='__main__':
  171. main()
  172. #get_src_pos()

如果您看到了这里,真的非常感谢!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/131567
推荐阅读
相关标签
  

闽ICP备14008679号