用手势导航可以完成GTAV,那么这一思想也能带入到别的游戏中。因此,我们的第一选择是打格斗游戏,并且该类别中最好的游戏之一是《铁拳》(SFTK)。主要概念很简单,无论人类玩家会采取什么行动(例如拳打),游戏中的玩家都会复制相同的动作。因此,为了实现这个想法,我们想出了两种方法。
首先,一种是较为复杂的方法:把我们的200+图像做不同的动作(如冲压,跳跃)等,然后用它来训练模型,以不同的姿势或者动作之间进行分类,并模拟它在游戏。但是这种方法存在一些问题。
显而易见,我们必须给自己拍很多张照片,每个类别中要有200张以上。这将非常忙碌,并且为了概括起见,我们还需要不同大小,背景和光照条件不同的人的图像。这可能会花费很多时间。
第二种方法是简单地使用我们以前在Virtual Switch and Gesture Gaming中的项目中的想法,为了概念验证,我们决定采用第二种方法。
概念
其工作背后的主要概念非常容易,只是有一个虚拟开关,只要按下该开关,就可以模拟游戏中相应的动作(踢)。
步骤
Bbox(边界框)是用于指代感兴趣区域(矩形/框内)的术语。
我们跟踪人脸,并且虚拟开关框相对于人脸移动。因此,为了在游戏中移动而使用的逻辑是:
Setup.ipynb->
在此笔记本中,我们将定义人类玩家开始的初始位置。因此,将通过跟踪算法从该位置跟踪他。首先,设置相机并将其放置在固定位置。然后,我们将只跟踪面部来跟踪人类玩家在游戏中的位置,因此执行“面部”框单元格,然后:
现在,如果您还想为新操作添加新的开关,则可以运行“按钮”单元,然后:
请注意,开关0将映射到操作键0。因此,将操作映射到类Action中的键。
class Buttons:
def __init__(self, n=0, bbox_body=(), training=False):
self.training = training
if not training: # automatically set the buttons values if not training mode
self.set_buttons()
else:
self.n = n
self.bbox_switch = []
self.bbox_body = bbox_body
self.center_point = get_centroid(self.bbox_body) # center point of face
self.buttons_bbox_init()
self.action = Actions(self.center_point) # calling the Actions object
def set_buttons(self):
self.bbox_body, self.center_point, self.n, self.bbox_switch = buttons_data
def buttons_bbox_init(self): # to setup the regions of action (bbox of switch)
self.switches = [] # the switch object
self.bbox_center = [] # the coordinates of bbox of switch wrt to the face
for i in range(self.n):
if not self.training: # copy the switch data, if already done the setup
bbox = self.bbox_switch[i]
s = Switch(self.bbox_body, bbox)
else: # else, select the region for switch
s = Switch(self.bbox_body)
self.bbox_switch.append(s.bbox)
self.switches.append(s)
self.bbox_center.append(self.bbox_wrt_center(s.bbox)) #now bbox is wrt origin
if self.training: # prints the values of bbox of body and switch
print(f'bbox_body = {self.bbox_body} \nbbox_switch = {self.bbox_switch}')
# Calculates the distance of bbox from center point (face). Then this is used to get new position
# of switch when the positoin of face changes.
def bbox_wrt_center(self, bbox):
center_x, center_y = self.center_point #starting center point, find switch pos, wrt starting bbox
x, y, w, h = bbox
dx, dy = x - center_x, y - center_y
return dx, dy, w, h
# updates to the new position of bbox switch, wrt to face
def bbox_update(self, bbox):
curr_x, curr_y = self.curr_center #cetner curr point of body
dx, dy, w, h = bbox
x = dx + curr_x
y = dy + curr_y
return x, y, w, h
def run(self, frame, curr_center):
self.curr_center = curr_center
for i in range(self.n):
s, bbox = self.switches[i], self.bbox_center[i]
s.bbox = self.bbox_update(bbox)
pressed = s.update(frame)
if pressed:
self.action.press_val(i)
self.action.action_movement(curr_center)
Gameplay.ipynb->
我们将初始化按钮对象,其中将包含所有虚拟交换机,通过训练为False将使其使用默认值。
button = Buttons(training=False)
tracker = cv2.TrackerCSRT_create()
fvs = cv2.VideoCapture(path)
TIMER_SETUP = 3
t = time.time()
while True:
frame = get_framecv2(fvs)
curr = (time.time() - t)
if curr > TIMER_SETUP or frame is None:
break
cv2.putText(frame, str(int(TIMER_SETUP - curr)+1), (225,255), cv2.FONT_HERSHEY_SIMPLEX, 1.5, COLOR_RED, 4)
cv2.putText(frame, 'Keep your face inside the box', POS_SCREEN, cv2.FONT_HERSHEY_SIMPLEX, 1, COLOR_RED, 4)
drawbox(True, bbox, frame)
cv2.imshow("Tracking", frame)
cv2.waitKey(1)
tracker.init(frame, BB)
#After the timer finishes, now your actions will be recorded, and will be mapped to key in game.
while True:
frame = get_framecv2(fvs)
if frame is None:
break
copy = frame.copy()
_, bbox = tracker.update(frame)
drawbox(True, bbox, frame)
button.run(frame, get_centroid(bbox))
cv2.imshow("Tracking", frame) # orig video frames
k = cv2.waitKey(1)
if k == 13: #13 is the Enter Key
break
cv2.destroyAllWindows()
fvs.release()
唯一的变化是,我们将当前帧传递给button对象,该对象将跟踪位置的变化以及与所按下的虚拟开关相对应的游戏中要执行的动作。
Switch.py->
该脚本包含所有基本功能,交换机—此类用于实现虚拟交换机。
按钮-此类用于:
bbox_wrt_center:此函数用于计算开关wrt到脸部中心的坐标。这样做是为了在我们移动时,开关也相应地移动。运行—此功能获取当前帧,并将其传递到开关。如果按下任何开关(返回True),则在游戏中按下与该开关相对应的动作。
动作:此类用于将Switch与游戏中相应的动作键(打孔,向左移动)映射。注意—我们尚未在其他PC上进行过测试,因此,如果某项操作在您的PC上不起作用,请尝试为Pressley和ReleaseKey之间的时间间隔设置不同的值。
注意:
结论
因此,这是我们尝试使用图像处理技能来创建一种有趣的玩《铁拳》游戏的方法。这只是对该想法的实验,将来,我们可能会使用一些更好的技术来获得更好的结果。