用OpenCV玩《鐵拳》!!!
點擊上方“小白學(xué)視覺”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達
用手勢導(dǎo)航可以完成GTAV,那么這一思想也能帶入到別的游戲中。因此,我們的第一選擇是打格斗游戲,并且該類別中最好的游戲之一是《鐵拳》(SFTK)。主要概念很簡單,無論人類玩家會采取什么行動(例如拳打),游戲中的玩家都會復(fù)制相同的動作。因此,為了實現(xiàn)這個想法,我們想出了兩種方法。
首先,一種是較為復(fù)雜的方法:把我們的200+圖像做不同的動作(如沖壓,跳躍)等,然后用它來訓(xùn)練模型,以不同的姿勢或者動作之間進行分類,并模擬它在游戲。但是這種方法存在一些問題。
顯而易見,我們必須給自己拍很多張照片,每個類別中要有200張以上。這將非常忙碌,并且為了概括起見,我們還需要不同大小,背景和光照條件不同的人的圖像。這可能會花費很多時間。
第二種方法是簡單地使用我們以前在Virtual Switch and Gesture Gaming中的項目中的想法,為了概念驗證,我們決定采用第二種方法。
其工作背后的主要概念非常容易,只是有一個虛擬開關(guān),只要按下該開關(guān),就可以模擬游戲中相應(yīng)的動作(踢)。
跟蹤臉部。
將邊界框wrt移到bbox面。
使用特定區(qū)域作為專用于特定操作的虛擬交換機。
Bbox(邊界框)是用于指代感興趣區(qū)域(矩形/框內(nèi))的術(shù)語。
我們跟蹤人臉,并且虛擬開關(guān)框相對于人臉移動。因此,為了在游戲中移動而使用的邏輯是:
當我們前進一定的門檻時,玩家也將開始前進,反之亦然。 我們存儲一條穿過臉部中心的水平線。如果我們跳躍并越過中心線一個閾值,則玩家也會跳躍。同樣,當我們走到線下時,玩家將蹲下。
在此筆記本中,我們將定義人類玩家開始的初始位置。因此,將通過跟蹤算法從該位置跟蹤他。首先,設(shè)置相機并將其放置在固定位置。然后,我們將只跟蹤面部來跟蹤人類玩家在游戲中的位置,因此執(zhí)行“面部”框單元格,然后:
從開始的位置做準備。 計時器結(jié)束后,在臉部周圍放置一個bbox。
現(xiàn)在,如果您還想為新操作添加新的開關(guān),則可以運行“按鈕”單元,然后:
設(shè)置n。這是總數(shù)。要添加的開關(guān)數(shù)量。 保持臉部收件箱為準,并進行操作(例如踢)。然后在您要分配用于踢腳動作的區(qū)域周圍打一個方框。 要保存以供以后使用,請復(fù)制打印的輸出并將其粘貼到Switch.py上。
請注意,開關(guān)0將映射到操作鍵0。因此,將操作映射到類Action中的鍵。
class Buttons:def __init__(self, n=0, bbox_body=(), training=False):self.training = trainingif not training: # automatically set the buttons values if not training modeself.set_buttons()else:self.n = nself.bbox_switch = []self.bbox_body = bbox_bodyself.center_point = get_centroid(self.bbox_body) # center point of faceself.buttons_bbox_init()self.action = Actions(self.center_point) # calling the Actions objectdef set_buttons(self):self.bbox_body, self.center_point, self.n, self.bbox_switch = buttons_datadef buttons_bbox_init(self): # to setup the regions of action (bbox of switch)self.switches = [] # the switch objectself.bbox_center = [] # the coordinates of bbox of switch wrt to the facefor i in range(self.n):if not self.training: # copy the switch data, if already done the setupbbox = self.bbox_switch[i]s = Switch(self.bbox_body, bbox)else: # else, select the region for switchs = 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 originif self.training: # prints the values of bbox of body and switchprint(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 bboxx, y, w, h = bboxdx, dy = x - center_x, y - center_yreturn dx, dy, w, h# updates to the new position of bbox switch, wrt to facedef bbox_update(self, bbox):curr_x, curr_y = self.curr_center #cetner curr point of bodydx, dy, w, h = bboxx = dx + curr_xy = dy + curr_yreturn x, y, w, hdef run(self, frame, curr_center):self.curr_center = curr_centerfor 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)
我們將初始化按鈕對象,其中將包含所有虛擬交換機,通過訓(xùn)練為False將使其使用默認值。
button = Buttons(training=False)tracker = cv2.TrackerCSRT_create()fvs = cv2.VideoCapture(path)TIMER_SETUP = 3t = time.time()while True:frame = get_framecv2(fvs)curr = (time.time() - t)if curr > TIMER_SETUP or frame is None:breakcv2.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:breakcopy = frame.copy()_, bbox = tracker.update(frame)drawbox(True, bbox, frame)button.run(frame, get_centroid(bbox))cv2.imshow("Tracking", frame) # orig video framesk = cv2.waitKey(1)if k == 13: #13 is the Enter Keybreakcv2.destroyAllWindows()fvs.release()
唯一的變化是,我們將當前幀傳遞給button對象,該對象將跟蹤位置的變化以及與所按下的虛擬開關(guān)相對應(yīng)的游戲中要執(zhí)行的動作。
該腳本包含所有基本功能,交換機—此類用于實現(xiàn)虛擬交換機。
按鈕-此類用于:
存儲所有Switch對象 通過當前幀來決定要按下哪個開關(guān)。
bbox_wrt_center:此函數(shù)用于計算開關(guān)wrt到臉部中心的坐標。這樣做是為了在我們移動時,開關(guān)也相應(yīng)地移動。運行—此功能獲取當前幀,并將其傳遞到開關(guān)。如果按下任何開關(guān)(返回True),則在游戲中按下與該開關(guān)相對應(yīng)的動作。
動作:此類用于將Switch與游戲中相應(yīng)的動作鍵(打孔,向左移動)映射。注意—我們尚未在其他PC上進行過測試,因此,如果某項操作在您的PC上不起作用,請嘗試為Pressley和ReleaseKey之間的時間間隔設(shè)置不同的值。
注意:
確保視頻質(zhì)量良好并且光線充足。由于它是通過計算噪聲來工作的,因此低圖像質(zhì)量或低光照可能會導(dǎo)致某些異常。 您可以使用背景減法器的history參數(shù),并根據(jù)需要更改開關(guān)的閾值。
因此,這是我們嘗試使用圖像處理技能來創(chuàng)建一種有趣的玩《鐵拳》游戲的方法。這只是對該想法的實驗,將來,我們可能會使用一些更好的技術(shù)來獲得更好的結(jié)果。
交流群
歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN、算法競賽等微信群(以后會逐漸細分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~

