毕业设计项目做了一个在游戏GTA5中实现自动驾驶的项目,其中一个功能是汽车的碰撞检测。为了实现这个功能我首先需要能实现识别汽车,对比了使用了SSD和Faster-RCNN,我选择了YOLOv3来实现这个功能,因为它既有速度又有精度,还非常灵活,简直是工业界良心。
当时在网上查阅相关教程的时候,很多教程只是讲到调用一下文件实现视频文件的检测。然而我需要对屏幕上显示的游戏画面进行检测,所以很多教程都不适用。
现在毕设做好了比较空闲,所以记录一下顺便帮助后来人,这个教程会讲如何用YOLOv3检测屏幕上的画面。
本文旨在帮助新手快速上手YOLOv3,不会涉及详细的代码和相应的算法原理,具体YOLO的原理等以后有时间再写篇详细的~
1、下载YOLOv3的Keras版(https://github.com/qqwweee/keras-yolo3) 里面有成熟的代码。
2、生成Keras的.h5文件,
需要:
权重文件:https://pjreddie.com/media/files/yolov3.weights,此权重文件包含一些预训练的参数。
网络结构配置文件:项目默认自带了YOLOv3-416的网络的.cfg。如果需要其他网络,则以txt文件打开.cfg文件,将第8行和第9行的参数修改为320或608。
下图为各种YOLOv3版本的准确度和速度对比,根据自己项目的准确度和速度需求,选择自己的网络(改那个.cfg)
下面为官网对比(https://pjreddie.com/darknet/yolo/)
下载好上述两个文件后,将权重文件放到项目根目录下
3、运行convert.py,将 yolov3.weights转换成Keras能使用的.h5文件
使用方法:
python convert.py yolov3.cfg yolov3.weights yolov3.h5
执行完成示意图
执行完成之后在当前目录下生成yolov3.h5文件,将其重命名为yolo.h5并放入model_data文件夹中。
4、新建grabscreen.py文件,复制以下内容,此文件里实现用Win32API截取屏幕。相比于使用PIL,这种方式截屏速度更快
import cv2
import numpy as np
import win32gui
import win32ui
import win32con
import 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 cv2.cvtColor(img, cv2.COLOR_BGRA2RGB)
5、新建example.py文件,复制以下内容 ,并运行。
import numpy as np
import cv2
import time
from grabscreen import grab_screen
from PIL import Image
from yolo import YOLO
import tensorflow as tf
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.8 #爆显存的话可以在此调整程序的显存占用情况
session = tf.Session(config=config)
yolo = YOLO()
while True:
image_array = grab_screen(region=(0, 0, 1280, 720))
# 获取屏幕,(0, 0, 1280, 720)表示从屏幕坐标(0,0)即左上角,截取往右1280和往下720的画面
array_to_image = Image.fromarray(image_array, mode='RGB') #将array转成图像,才能送入yolo进行预测
img = yolo.detect_image(array_to_image) #调用yolo文件里的函数进行检测
img = np.asarray(img) #将图像转成array
cv2.imshow('window',cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) #将截取的画面从另一窗口显示出来,对速度会有一点点影响,不过也就截取每帧多了大约0.01s的时间
if cv2.waitKey(25) & 0xFF == ord('q'): #按q退出,记得输入切成英语再按q
cv2.destroyAllWindows()
break
6、检测结果:
左边为GTA5的游戏画面,右边为检测结果,使用一个窗口显示出来