赞
踩
大家好,今天为大家带来原神自动刷副本的脚本,先看看效果。
1、找到进入副本的特征,根据这个特征让角色移动到挑战地点。
2、当角色到达挑战地点,找到副本挑战开始的信号。
3、挑战开始后,根据队伍预设的指令进行攻击,一直循环直到挑战成功。
4、找到挑战成功的标识,以此来结束攻击循环。
5、识别周围环境,寻找领奖位置。
6、移动到领奖处,识别可以领取奖励的标志,并按照指令领奖。
由脚本思路中,我们需要准备通关副本的各种数据(脚本思路下划线部分)。
首先,对于其中一些简单的标识,在电脑屏幕上持续时间长且容易识别,采用模板匹配算法。
模板匹配就是将特征图在一张图片里不停的移动并进行匹配,根据匹配相似度得到最高值,具体就不在这里说了。说回到简单的标识,比如,开启副本的标识,挑战位置的标识,等等。这些都是固定的标识。这些标识如下:
得到了这些标识,也就是所谓特征。那么我们需要将标识在一张图片里移动,找到相似度最高的值(模板匹配算法)。那么这个图片在哪里来呢?当然是我们的屏幕,但是把全屏放进去是不好的,这样运算速度比较慢,我们选择将屏幕部分区域截取下来,让这些特征在区域内进行匹配,这样大大节省了时间。
但是这些区域怎么获得呢?这个根据自己的显示屏大小来确定了。以我的为例:
tree_pos为石化古树的位置(874,278),(1042,321)分别代表了这个区域左上角和右下角点在屏幕上的位置坐标。这样,将所有需要匹配的特征加载进来,已经这些匹配区域的位置信息得到,就能进行识别。
上面说完了简单的标识,对于不那么简单的标识,模板匹配就不那么好用了。例如在战斗过后,找寻领奖位置。在战斗中难免有碰撞,导致位置不一样,包括视角转动这些,在进行匹配就不那么好找了,当然可以选择降低阈值,但很多时候仍然不容易找到。选择用YOLO进行识别。效果图如下:
至此,简单和困难的标识都得到了解决,下面着手代码的编写。
1、对于简单标识,我们需要用模板匹配识别,先定义一个识别函数:
- #匹配函数值
- def get_match_value(path,pos):
- area = src_area(pos)
- tar = cv2.imread(path)
- res = cv2.matchTemplate(area,tar,cv2.TM_CCOEFF_NORMED)
- _,max_value,_,_= cv2.minMaxLoc(res)
- return max_value
函数输入值path,pos就是上面图里面的每一个特征的path和pos。
这里的src_area函数如下定义:
- def src_area(xyxy):
- im = ImageGrab.grab()
- r,g,b = cv2.split(np.array(im))
- img = cv2.merge([b,g,r])
- if xyxy==None:
- return img
- return img[xyxy[1]:xyxy[3],xyxy[0]:xyxy[2]]
有了这个函数,我们就基本可以完成副本挑战一半的任务了。
2、利用识别函数识别,定义在识别后需要进行的操作
已经说了,用这个识别函数就能做到很多事了,如下:
1、关闭副本提示
- #关闭副本提示(标志)
- def close_tip(thr):
- value = get_match_value(place_tip_path,place_tip_pos)
- if value>=thr:
- time.sleep(1)
- mouse.click()
- return True
- return False
2、去往挑战处
- #前往挑战处
- def go_to_start(thr):
- key.kevent_down('w')
- while True:
- value=get_match_value(start_path,start_pos)
- if value>=thr:
- key.kevent_up('w')
- key.kevent_down('f')
- key.kevent_up('f')
- break
3、判断挑战是否成功
- #判断是否挑战成功
- def win_the_challenge(thr):
- value = get_match_value(end_path,end_pos)
- if value>=thr:
- return True
- return False
4、去往领奖处
- #前往领奖处
- def go_to_reward(thr):
- while True:
- key.kevent_down('w')
- value=get_match_value(reward_path,reward_pos)
- if value>=thr:
- key.kevent_up('w')
- key.kevent_down('f')
- key.kevent_up('f')
- break
- time.sleep(0.5)
- key.kevent_up('w')
5、是否有足够体力进行下一次副本
- #是否有足够体力
- def have_sz(thr):
- value = get_match_value(tree_path,tree_pos)
- if value>=thr:
- return False
- return True
好了,到此一些简单标识能做的任务我们已经完成了。
3、定义战斗函数
在《识别后操作》部分1、2、3中,我们通过1、2部分已经可以成功走到挑战位置并开启挑战,这时在挑战开启后执行战斗函数并通过3部分判断是否战斗胜利。战斗函数比较随意,可以根据自己的设置来配置,我的战斗函数为:
- #预设战斗指令
- def fight():
- time.sleep(0.4)
- key.kevent_down('e')
- time.sleep(1)
- key.kevent_up('e')
- time.sleep(0.5)
- key.kevent_down('2')
- key.kevent_up('2')
- time.sleep(0.5)
- key.kevent_down('e')
- key.kevent_up('e')
- time.sleep(1)
- key.kevent_down('3')
- key.kevent_up('3')
- time.sleep(0.5)
- key.kevent_down('e')
- time.sleep(0.4)
- for i in range(10):
- mouse.move_mouse((800,0))
- time.sleep(0.05)
- key.kevent_up('e')
- time.sleep(0.5)
- key.kevent_down('4')
- key.kevent_up('4')
- time.sleep(0.4)
- key.kevent_down('e')
- key.kevent_up('e')
- time.sleep(0.9)
- key.kevent_down('1')
- key.kevent_up('1')
4、战斗胜利后找寻领奖位置
在《识别后操作》4部分,我们已经有了去往领奖处的函数了,但是找到领奖处却要在这里定义,这是因为领奖识别比较简单,用模板匹配容易,而找到这个位置需要用YOLO。接定义战斗函数部分后,在战斗后,我们已经识别了战斗胜利了,这时还没有操作,我们让计算机转动视角,同时将每转动一次的图像传递给YOLO模型,进行识别,识别到领奖位置后,停止转动视角。代码如下:
- #寻找领奖位置
- def find_goal(model):
- area = src_area(yolo_pos)
- xywh,conf = model.inference(area)
- return xywh,conf
这里的model如下定义:
- class yolo_model():
- def __init__(self):
- device = ''
- weights = 'yolov5/runs/train/exp12/weights/best.pt' # pt
- data = 'yolov5/ys_data/ys.yaml' # yaml
- half = False
- dnn = False
- imgsz = (640, 640)
- self.augment = False
- self.max_det = 1000
- self.agnostic_nms = False
- self.classes = None
- self.conf_thres = 0.25 # confidence threshold
- self.iou_thres = 0.45
-
- # Load model
- device = select_device(device)
- self.model = DetectMultiBackend(weights, device=device, dnn=dnn, data=data, fp16=half)
- self.stride, names, self.pt = self.model.stride, self.model.names, self.model.pt
- self.imgsz = check_img_size(imgsz, s=self.stride) # check image size
-
- # Run inference
- self.model.warmup(imgsz=(1, 3, *imgsz)) # warmup
- self.dt = (Profile(), Profile(), Profile())
-
- def inference(self,im0):
- im = letterbox(im0, self.imgsz, stride=self.stride, auto=self.pt)[0] # padded resize
- im = im.transpose((2, 0, 1))[::-1] # HWC to CHW, BGR to RGB
- im = np.ascontiguousarray(im)
-
- with self.dt[0]:
- im = torch.from_numpy(im).to(self.model.device)
- im = im.half() if self.model.fp16 else im.float() # uint8 to fp16/32
- im /= 255 # 0 - 255 to 0.0 - 1.0
- if len(im.shape) == 3:
- im = im[None] # expand for batch dim
-
- # Inference
- with self.dt[1]:
- visualize = False
- pred = self.model(im, augment=self.augment, visualize=visualize)
-
- # NMS
- with self.dt[2]:
- pred = non_max_suppression(pred, self.conf_thres, self.iou_thres, self.classes, self.agnostic_nms, max_det=self.max_det)
-
- det = pred[0]
- gn = torch.tensor(im0.shape)[[1, 0, 1, 0]] # normalization gain whwh
- cof = None
- xywh = None
- if len(det):
- for *xyxy, conf, cls in reversed(det):
- xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()
- cof = conf
- return xywh,cof
寻找到位置后,结合《识别后操作》4部分,我们成功来到领奖位置处并获得奖励。
5、函数汇总
以下是源文件,执行就可以自动化了
- import cv2
- import sys
- sys.path.append(r'./yolov5')
- from my_utils.screen_capture import src_area
- from model import yolo_model
- from my_utils.mouse_control import *
- import my_utils.keyboard as key
- import time
- mouse=Mouse()
-
- #匹配图形位置及路径
- tree_pos = [874,278,1042,321]
- tree_path = './img/no_sz.png'
- use_nssz_pos = (747,744)
- place_tip_pos=[853,673,1055,709]
- place_tip_path='./img/place_tip.png'
- start_pos=[1163,516,1292,561]
- start_path='./img/start_button.png'
- reward_pos = [1208,515,1349,556]
- reward_path = './img/reward.png'
- end_pos = [956,941,1082,973]
- end_path='./img/end.png'
- yolo_pos = [690,9,1214,856]
-
-
- #获得鼠标在屏幕的位置坐标
- def get_src_pos():
- while True:
- if win32api.GetAsyncKeyState(0x04)<0:
- pos = mouse.get_position()
- print(pos)
- while win32api.GetAsyncKeyState(0x04)<0:
- pass
-
-
- #匹配函数值
- def get_match_value(path,pos):
- area = src_area(pos)
- tar = cv2.imread(path)
- res = cv2.matchTemplate(area,tar,cv2.TM_CCOEFF_NORMED)
- _,max_value,_,_= cv2.minMaxLoc(res)
- return max_value
- '''
- if max_value>thr:
- print('got the target')
- else:
- print('can not find the target')
- '''
- #是否有足够体力
- def have_sz(thr):
- value = get_match_value(tree_path,tree_pos)
- if value>=thr:
- return False
- return True
-
- #关闭副本提示(标志)
- def close_tip(thr):
- value = get_match_value(place_tip_path,place_tip_pos)
- if value>=thr:
- time.sleep(1)
- mouse.click()
- return True
- return False
-
-
- #前往挑战处
- def go_to_start(thr):
- key.kevent_down('w')
- while True:
- value=get_match_value(start_path,start_pos)
- if value>=thr:
- key.kevent_up('w')
- key.kevent_down('f')
- key.kevent_up('f')
- break
- #前往领奖处
- def go_to_reward(thr):
- while True:
- key.kevent_down('w')
- value=get_match_value(reward_path,reward_pos)
- if value>=thr:
- key.kevent_up('w')
- key.kevent_down('f')
- key.kevent_up('f')
- break
- time.sleep(0.5)
- key.kevent_up('w')
- #预设战斗指令
- def fight():
- time.sleep(0.4)
- key.kevent_down('e')
- time.sleep(1)
- key.kevent_up('e')
- time.sleep(0.5)
- key.kevent_down('2')
- key.kevent_up('2')
- time.sleep(0.5)
- key.kevent_down('e')
- key.kevent_up('e')
- time.sleep(1)
- key.kevent_down('3')
- key.kevent_up('3')
- time.sleep(0.5)
- key.kevent_down('e')
- time.sleep(0.4)
- for i in range(10):
- mouse.move_mouse((800,0))
- time.sleep(0.05)
- key.kevent_up('e')
- time.sleep(0.5)
- key.kevent_down('4')
- key.kevent_up('4')
- time.sleep(0.4)
- key.kevent_down('e')
- key.kevent_up('e')
- time.sleep(0.9)
- key.kevent_down('1')
- key.kevent_up('1')
-
- #判断是否挑战成功
- def win_the_challenge(thr):
- value = get_match_value(end_path,end_pos)
- if value>=thr:
- return True
- return False
-
- #寻找领奖位置
- def find_goal(model):
- area = src_area(yolo_pos)
- xywh,conf = model.inference(area)
- return xywh,conf
-
- #退出游戏
- def log_out():
- key.kevent_down('menu')
- time.sleep(0.01)
- key.kevent_down('f4')
- time.sleep(0.01)
- key.kevent_up('f4')
- time.sleep(0.01)
- key.kevent_up('menu')
-
- def main():
- model = yolo_model()
- print('press P to start')
- while win32api.GetAsyncKeyState(ord('P'))>=0:
- pass
- while have_sz(0.9):
-
- time.sleep(0.2)
- while True:
- if close_tip(0.95):
- break
- time.sleep(0.5)
- go_to_start(0.9)
- time.sleep(0.5)
- key.kevent_down('1')
- key.kevent_up('1')
- time.sleep(0.5)
- while not win_the_challenge(0.9):
- fight()
- time.sleep(7)
-
- flag = True
- while flag:
- xywh,conf = find_goal(model)
- if conf!=None and conf>0.4:
- flag = False
- mouse.move_mouse((40,0))
- time.sleep(0.02)
- time.sleep(0.5)
- go_to_reward(0.9)
- time.sleep(0.5)
- mouse.set_position((747,744))#鼠标移动到浓缩树脂处
- time.sleep(0.02)
- mouse.click()
- time.sleep(10)
- mouse.set_position((1191,993))#鼠标移动到继续挑战处
- time.sleep(0.05)
- mouse.click()
- time.sleep(1)
- time.sleep(1)
- log_out()
-
-
- if __name__=='__main__':
-
- main()
- #get_src_pos()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。