みなさんこんにちは、ピカソです(ロック!)
今日はYolov5 FPSとガンのソースコード解析と原理説明をシェアします。コードは比較的ラフですが、最適化の方法があれば、メッセージを残して指摘することもできますし、コミュニケーションを取りながら一緒に学ぶこともできます。
知っておくべきことと発生する可能性のある問題
1. xy 座標点と現在のマウスの xy 座標点の間の距離を計算します。
2. ウィンドウ ハンドルを取得する この記事では、ウィンドウ名を使用してハンドルを取得します。
3. 推論方法: この記事では GPU を使用しています (なぜですか? 3060 グラフィック カードを使用しているため速度が速いのです~)。
4. 画面の幅と高さと敵の座標を取得し、最も近い敵を計算し、マウスを操作して敵の体と頭に移動します。(なんで胴体と頭なの? 敵の体の座標だけで敵の頭の座標が計算できるという別の方法があるから。) 乾物~
5. マウスボタンの状態取得もあります。
テキストから始めましょう。最初からコード分析を始めましょう。
まず、2 つの xy 座標間の距離計算
class Point():
def __init__(self, x1, y1, x2, y2):
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
class Line(Point):
def __init__(self, x1, y1, x2, y2):
super().__init__(x1, y1, x2, y2)
def getlen(self):
changdu = math.sqrt(math.pow((self.x1 - self.x2), 2) + math.pow((self.y1 - self.y2), 2))
return changdu
上記のコードは次のように使用できます
L1 = Line(x1, y1, x2, y2) #传入两个xy坐标
L1.getlen() #return出两个坐标点的直线距离
次に、完全なコード分析に直接進みます。クラスとメソッドを分離できます
# 这里是导入依赖,需要这些库
import math
import sys
import time
import torch
import win32api
import win32con
import win32gui
from PyQt5.QtWidgets import QApplication
from pynput.mouse import Controller
import mouse
#这里这俩class就是文章上面说的那个传入两个坐标点,计算直线距离的
class Point():
def __init__(self, x1, y1, x2, y2):
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
class Line(Point):
def __init__(self, x1, y1, x2, y2):
super().__init__(x1, y1, x2, y2)
def getlen(self):
changdu = math.sqrt(math.pow((self.x1 - self.x2), 2) + math.pow((self.y1 - self.y2), 2))
return changdu
#第一步:我们获取到某FPS游戏的窗口句柄
hwnd = win32gui.FindWindow(None, "穿越火线")
#这个方法是获取上面句柄窗口的窗口截图,用的是PyQt截图,有速度更快更好的方式的话可以换上
#截图完毕后保存在根目录的cfbg.bmp文件
def screen_record():
app = QApplication(sys.argv)
screen = QApplication.primaryScreen()
img = screen.grabWindow(hwnd).toImage()
img.save("cfbg.bmp")
#这里就是调用我们那yolo模型来进行推理啦,我设置的是cuda,也就是英伟达的GPU,因为cpu太慢了。
#如果自己的不能使用GPU推理的话把下面这两行改改,改成cpu的就可以了。
device = torch.device("cuda")
model = torch.hub.load('F:/yolov5-master', 'custom', 'F:/yolov5-master/yolov5n6.pt',
source='local', force_reload=False) # 加载本地模型
# 这里是定义屏幕宽高[其实这俩就是游戏所对应的分辨率,比如:游戏里1920*1080这里就是1920*1080]
game_width = 1024
game_height = 768
# 这边就是开始实时进行游戏窗口推理了
#无限循环 -> 截取屏幕 -> 推理模型获取到每个敌人坐标 -> 计算每个敌人中心坐标 -> 挑选距离准星最近的敌人 -> 如果左键是按下状态则控制鼠标移动到敌人的身体或者头部(本文计算方式是移动到头部)
while True:
# 截取屏幕
screen_record()
# 使用模型
model = model.to(device)
img = 'cfbg.bmp'
# 开始推理
results = model(img)
# 过滤模型
xmins = results.pandas().xyxy[0]['xmin']
ymins = results.pandas().xyxy[0]['ymin']
xmaxs = results.pandas().xyxy[0]['xmax']
ymaxs = results.pandas().xyxy[0]['ymax']
class_list = results.pandas().xyxy[0]['class']
confidences = results.pandas().xyxy[0]['confidence']
newlist = []
for xmin, ymin, xmax, ymax, classitem, conf in zip(xmins, ymins, xmaxs, ymaxs, class_list, confidences):
if classitem == 0 and conf > 0.5:
newlist.append([int(xmin), int(ymin), int(xmax), int(ymax), conf])
# 循环遍历每个敌人的坐标信息传入距离计算方法获取每个敌人距离鼠标的距离
if len(newlist) > 0:
# 存放距离数据
cdList = []
xyList = []
for listItem in newlist:
# 当前遍历的人物中心坐标
xindex = int(listItem[2] - (listItem[2] - listItem[0]) / 2)
yindex = int(listItem[3] - (listItem[3] - listItem[1]) / 2)
mouseModal = Controller()
x, y = mouseModal.position
L1 = Line(x, y, xindex, yindex)
# 获取到距离并且存放在cdList集合中
cdList.append(int(L1.getlen()))
xyList.append([xindex, yindex, listItem[0], listItem[1], listItem[2], listItem[3]])
# 这里就得到了距离最近的敌人位置了
minCD = min(cdList)
# 如果敌人距离鼠标坐标小于150则自动进行瞄准,这里可以改大改小,小的话跟枪会显得自然些
if minCD < 150:
for cdItem, xyItem in zip(cdList, xyList):
if cdItem == minCD:
# 锁头算法:使用win32api获取左键按下状态,如果按下则开始自动跟枪
if win32api.GetAsyncKeyState(0x01):
# 控制鼠标移动到某个点:看不懂计算方式的话看文章下面讲解吧O(∩_∩)O
win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, int(xyItem[0] - game_width // 2),int(xyItem[1] - (game_height - (xyItem[3] - xyItem[5])) // 2), 0, 0)
break
わかりました、このコード行を説明しましょう
win32api.mouse_event (マウスの動作: MOVE 相対移動がここで使用されます。x 座標、y 座標、0, 0)
最初のパラメータは、最初にマウスの動作を設定します: 相対移動を使用します。絶対移動はゲーム内では無効なので絶対移動を使用
第二引数 x 軸の相対移動距離: 敵の x 座標 - (画面幅 / 2) 第
三引数 y 軸の相対移動距離-axis: 敵の y 座標 -
(画面の高さ - (敵の最大の y 座標 - 敵の最小の y 座標) / 2) 3番目のyの動き くそー、絵を描いたので、わかるといいのですが。
例図
他の fps ゲームでは、ウィンドウ名パラメーターと解像度パラメーターのみを変更する必要があります。
以上、Yolov5 FPSとガンのソースコード解析と原理説明でした。
私はBi Jiasuoです。あなたの注目を楽しみにしています