!pip install paddlex -i https://mirror.baidu.com/pypi/simple
import matplotlib
matplotlib.use('Agg')
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
import paddlex as pdx
#把製作好的數據集解壓到相應子目錄
!rm data/game -r
# !cat game.zip.* > game.zip
!unzip game.zip
!mv game data/
# !rm game.zip
import os
import zipfile
import xml.etree.ElementTree as ET
import re
import numpy as np
lables = os.listdir("data/game/lable")
print("lables:",len(lables))
trains = os.listdir("data/game/train1")
print("trains:",len(trains))
_lable = []
ratio = 0.8
offset = int(len(lables)*ratio)
np.random.shuffle(lables)
path = "data/game/"
with open(path + "train_list.txt","w") as f:
for lable in lables[:offset]:
if lable.split(".")[0] + ".jpg" in trains:
f.writelines("train1/" + lable.split(".")[0] + ".jpg" + " " + "lable/" + lable +"\n")
tree = ET.parse(path + "lable/" + lable)
root = tree.getroot()
objs = root.findall("object")
for obj in objs:
if obj.find("name").text not in _lable:
_lable.append(obj.find("name").text)
tree.find("path").text = path + "lable/" + lable
tree.write(path + "lable/" + lable)
with open(path + "test_list.txt","w") as f:
for lable in lables[offset:]:
if lable.split(".")[0] + ".jpg" in trains:
f.writelines("train1/" + lable.split(".")[0] + ".jpg" + " " + "lable/" + lable +"\n")
tree = ET.parse(path + "lable/" + lable)
root = tree.getroot()
objs = root.findall("object")
for obj in objs:
tree.find("path").text = path + "lable/" + lable
tree.write(path + "lable/" + lable)
if obj.find("name").text not in _lable:
_lable.append(obj.find("name").text)
with open(path + "val_list.txt","w") as f:
for lable in lables[offset:]:
if lable.split(".")[0] + ".jpg" in trains:
f.writelines("train1/" + lable.split(".")[0] + ".jpg" + " " + "lable/" + lable +"\n")
print(_lable)
with open(path + "lable.txt","w") as f:
for lable in _lable:
f.writelines(lable+"\n")
from paddlex.det import transforms
train_transforms = transforms.Compose([
transforms.MixupImage(mixup_epoch=250),
transforms.RandomDistort(),
transforms.RandomExpand(),
transforms.RandomCrop(),
transforms.Resize(target_size=608, interp='RANDOM'),
transforms.RandomHorizontalFlip(),
transforms.Normalize(),
])
eval_transforms = transforms.Compose([
transforms.Resize(target_size=608, interp='CUBIC'),
transforms.Normalize(),
])
train_dataset = pdx.datasets.VOCDetection(
data_dir='data/game',
file_list='data/game/train_list.txt',
label_list='data/game/lable.txt',
transforms=train_transforms,
shuffle=True)
eval_dataset = pdx.datasets.VOCDetection(
data_dir='data/game',
file_list='data/game/val_list.txt',
label_list='data/game/lable.txt',
transforms=eval_transforms)
num_classes = len(train_dataset.labels)
model = pdx.det.YOLOv3(num_classes=num_classes, backbone='DarkNet53')
model.train(
num_epochs=300,
train_dataset=train_dataset,
train_batch_size=12,
eval_dataset=eval_dataset,
learning_rate=0.000125,
lr_decay_epochs=[210, 240],
save_interval_epochs=20,
save_dir='output/yolov3_darknet53',
use_vdl=True)
# 訓練完了,就可以用來檢測小人與下一個跳臺分別在什麼地方了。
# 設置使用0號GPU卡(如無GPU,執行此代碼後會使用CPU訓練模型)
import matplotlib
matplotlib.use('Agg')
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
import paddlex as pdx
# 加載模型文件夾路徑,這裡修改為訓練時模型保存的路徑:
base_path = "output/best_model"
model = pdx.load_model(base_path)
import win32gui
import win32api
from PIL import ImageGrab
import cv2
import time
import numpy as np
classname = None
titlename = "360手機演示"
#獲取句柄
hwnd = win32gui.FindWindow(classname, titlename)
print("獲取窗口:",hwnd)
#獲取窗口左上角和右下角坐標
left, top, right, bottom = win32gui.GetWindowRect(hwnd)
print(left, top, right, bottom)
def getScreen():
n = time.time()
left, top, right, bottom = win32gui.GetWindowRect(hwnd)
img = ImageGrab.grab(bbox=(left, top, right, bottom))
img = np.array(img.getdata(), np.uint8).reshape(img.size[1], img.size[0], 3)
#img = img[...,::-1]
cv2.imwrite("response.jpg", img)
getScreen()
filename = "response.jpg"
result = model.predict("temp/" +filename)
pdx.det.visualize("temp/" +filename, result, threshold=0.5, save_dir='./output/yolov3_mobilenetv1')
#result的格式是
# [{'category_id': 1,
# 'bbox': [164.57411193847656, 248.15550231933594, 34.76348876953125, 16.626205444335938],
# 'score': 0.972798228263855,
# 'category': 'next'}]
#獲取小人腳底坐標與下一個跳臺中心的坐標,計算距離d
#計算距離d和時間t的之間函數關係,
#假定小人的路徑是拋物線,與發射角和時間都相關
#當按下時間為0時,發射方向為垂直向上的,此時發射角為0度
#按下時間越長,發射角越接近0度,所以構造以下函數
#發射角aa = Pi/2 - Pi/2*(a/(c*t + 1.0) + (1-a))
#發射起始速度V與按下時間成正比,V = z*t
#Vx = V*cos(aa),Vy= V*sin(aa)
#空中飛行時間為T = 2*Vy/g
#跳躍距離為Vx*T = V*cos(aa)* 2*V*sin(aa)/g= z^2 * t^2 *sin(aa)*cos(aa) /g =b *t^2 * sin(2*aa)
#
#這部分其實應該用深度學習來找這個函數,這個以後再弄
import math
def d2t(a,b,c,d):
#返回按下的時間長度,感覺是單調函數,所以二分法試一下
t0,t1 = 0.0,500.0
for _ in range(100):
t = t1/2.0 + t0/2.0
aa = (3.1415926*(a/(c*t+1.0)+1-a) - 3.1415926/2)
d0 = b * t**2 *math.sin(aa)
if (d - d0)**2 < 0.000001:
return t
if d > d0:
t0 = t1/2.0 + t0/2.0
else:
t1 = t1/2.0 + t0/2.0
return t
#手工調試這組參數
a,b,c = 0.25, 420, 3.0
#最後就是在屏幕上對遊戲進行操作:
#需要用到autopy庫
!pip install autopy
import autopy
def toggle(x,y,t):
#在x,y位置按下t時長,模擬在手機上的按下操作
autopy.mouse.move(x ,y)
autopy.mouse.toggle(None,True)
time.sleep(t)
autopy.mouse.toggle(None,False)