在 Python 中使用 OpenCV 構(gòu)建 Color Catcher 游戲
介紹
你是否曾經(jīng)想在 Python 中使用 OpenCV 創(chuàng)建自己的游戲?
今天我們將構(gòu)建一個名為 Color Catcher 的游戲,該游戲挑戰(zhàn)玩家使用手部跟蹤機制接住從屏幕頂部掉落的彩球。
設(shè)置游戲窗口
構(gòu)建游戲的第一步是使用 OpenCV 設(shè)置游戲窗口。我們將定義窗口大小、創(chuàng)建窗口并設(shè)置其在屏幕上的位置:
# Set up the game window
window_size = (640, 480)
window_name = 'Color Catcher'
cv2.namedWindow(window_name)
cv2.moveWindow(window_name, 0, 0)
定義游戲?qū)ο?/p>
接下來,我們將定義游戲?qū)ο。?Color Catcher 中,我們有兩個主要的游戲?qū)ο螅翰妒趾颓颉?/p>
捕手是玩家用手移動的矩形,而球是從屏幕頂部落下的隨機生成的圓圈。我們將定義這些游戲?qū)ο蟮膶傩裕?/p>
# Set up the game objects
catcher_color = (0, 0, 255)
catcher_width = 100
catcher_height = 20
catcher_position = np.array([window_size[0]//2, window_size[1]-catcher_height], dtype=int)
catcher_velocity = np.array([10, 0], dtype=int)
ball_radius = 20
ball_speed = 5
ball_colors = [(0, 255, 0), (255, 0, 0), (0, 0, 255)]
balls = []
score = 0
從網(wǎng)絡(luò)攝像頭捕獲視頻
為了跟蹤玩家的手部動作,我們需要使用 OpenCV 從網(wǎng)絡(luò)攝像頭捕獲視頻。
我們將創(chuàng)建一個視頻捕獲設(shè)備并循環(huán)播放視頻的每一幀:
# Set up the video capture device
cap = cv2.VideoCapture(0)
while True:
# Read a frame from the video capture device
ret, frame = cap.read()
if not ret:
break
檢測玩家的手
為了跟蹤玩家的手部動作,我們將使用 OpenCV 的輪廓檢測功能。首先,我們將每個幀轉(zhuǎn)換為灰度并應(yīng)用閾值以便更容易檢測輪廓:
# Convert the frame to grayscale and apply a threshold
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
接下來,我們將在閾值圖像中找到輪廓,并確定面積最大的輪廓,這應(yīng)該是玩家的手:
# Find the contours in the thresholded image
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Find the contour with the largest area, which should be the hand
if contours:
hand_contour = max(contours, key=cv2.contourArea)
hand_hull = cv2.convexHull(hand_contour)
hand_center = np.mean(hand_contour, axis=0, dtype=int)[0]
移動捕手
一旦我們檢測到玩家手的位置,我們就可以相應(yīng)地移動捕手。
在代碼中,我們檢查手中心的 x 坐標并將其與接球手位置的 x 坐標進行比較。如果手在接球手的左側(cè),我們通過從接球手的當(dāng)前位置減去接球手的速度,將接球手向左移動。如果手在捕手的右側(cè),我們通過將捕手的速度添加到其當(dāng)前位置來將捕手移動到右側(cè)。
if hand_center[0] < catcher_position[0] and catcher_position[0] > 0:
catcher_position -= catcher_velocity
elif hand_center[0] > catcher_position[0]+catcher_width and catcher_position[0]+catcher_width < window_size[0]:
catcher_position += catcher_velocity
生成和移動球:
如果當(dāng)前比賽中的球數(shù)少于五個,我們將生成具有隨機顏色和位置的新球。我們將包含球的顏色、位置和速度的元組附加到balls列表中。
if len(balls) < 5:
ball_color = random.choice(ball_colors)
ball_position = np.array([random.randint(ball_radius, window_size[0]-ball_radius), 0], dtype=int)
ball_velocity = np.array([0, ball_speed], dtype=int)
balls.append((ball_color, ball_position, ball_velocity))
然后我們遍歷balls列表中的每個球,通過將其速度添加到其當(dāng)前位置來更新其位置,并檢查它是否與接球手發(fā)生碰撞或擊中游戲窗口的底部。
如果球與接球手發(fā)生碰撞,我們將其從balls列表中移除,增加玩家的得分,然后跳出循環(huán)。
如果球擊中了游戲窗口的底部,我們將其從balls列表中移除并跳出循環(huán)。
for i in range(len(balls)):
balls[i] = (balls[i][0], balls[i][1]+balls[i][2], balls[i][2])
ball_position = balls[i][1]
if ball_position[1]+ball_radius >= catcher_position[1] and
ball_position[0] >= catcher_position[0] and
ball_position[0] <= catcher_position[0]+catcher_width:
balls.pop(i)
score += 1
break
elif ball_position[1]+ball_radius >= window_size[1]:
balls.pop(i)
break
繪制游戲?qū)ο螅?/strong>
最后,我們使用cv2.rectangle()和cv2.circle()函數(shù)在框架上繪制游戲?qū)ο。我們使用np.zeros()創(chuàng)建一個黑色框架,將捕手繪制為紅色矩形,并將每個球繪制為彩色圓圈。
我們還使用cv2.putText()函數(shù)在框架的左上角顯示玩家的分數(shù)。
frame = np.zeros(window_size+(3,), dtype=np.uint8)
cv2.rectangle(frame, tuple(catcher_position), tuple(catcher_position+np.array([catcher_width, catcher_height])), catcher_color, -1)
for ball in balls:
cv2.circle(frame, tuple(ball[1]), ball_radius, ball[0], -1)
cv2.putText(frame, "Score: {}".format(score), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
cv2.imshow(window_name, frame)
退出游戲:
最后,游戲循環(huán)包含在while循環(huán)中。在這個循環(huán)中,執(zhí)行以下任務(wù):
使用cap.read()方法從視頻捕獲設(shè)備讀取新幀。處理框架以檢測手區(qū)域并相應(yīng)地移動捕手。如有必要,將生成一個具有隨機顏色和位置的新球。球被移動并檢查是否與接球手發(fā)生碰撞。游戲?qū)ο罄L制在框架上。框架顯示在屏幕上。循環(huán)繼續(xù),直到用戶按下“q”鍵。
按“q”鍵可以退出游戲。這是使用cv2.waitKey()方法完成的,該方法等待鍵盤事件的給定毫秒數(shù)。如果按鍵被按下,該方法返回按鍵的 ASCII 代碼,如果沒有按鍵被按下,則返回 -1。
我們使用按位與運算符 ( &) 提取結(jié)果的最低有效 8 位,這為我們提供了按 256 模的按下鍵的 ASCII 代碼。我們將此值與 'q' 鍵 ( ord('q')) 的 ASCII 代碼進行比較,如果匹配則退出循環(huán)。
# Exit the game if the user presses the 'q' key
if cv2.waitKey(1) & 0xFF == ord('q'):
break
退出循環(huán)后,我們分別使用cap.release()和cv2.destroyAllWindows()方法釋放視頻捕獲設(shè)備并關(guān)閉游戲窗口。
# Release the video capture device and close the game window
cap.release()
cv2.destroyAllWindows()
就是這樣!你現(xiàn)在應(yīng)該能夠運行代碼并玩游戲了。這個游戲是一個簡單的例子,說明了如何使用計算機視覺來實時控制游戲?qū)ο蟮囊苿。?dāng)然,還有很大的改進和優(yōu)化空間,但這應(yīng)該足以讓你入門。
編碼愉快!
完整代碼:
https://github.com/Yaga987/Computer-Vision/blob/main/CompVisGame.py
原文標題 : 在 Python 中使用 OpenCV 構(gòu)建 Color Catcher 游戲
請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個字
最新活動更多
-
即日-10.29立即報名>> 2024德州儀器嵌入式技術(shù)創(chuàng)新發(fā)展研討會
-
10月31日立即下載>> 【限時免費下載】TE暖通空調(diào)系統(tǒng)高效可靠的組件解決方案
-
即日-11.13立即報名>>> 【在線會議】多物理場仿真助跑新能源汽車
-
11月14日立即報名>> 2024工程師系列—工業(yè)電子技術(shù)在線會議
-
12月19日立即報名>> 【線下會議】OFweek 2024(第九屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會
-
即日-12.26火熱報名中>> OFweek2024中國智造CIO在線峰會
推薦專題
- 1 Intel宣布40年來最重大轉(zhuǎn)型:年底前裁員15000人、拋掉2/3房產(chǎn)
- 2 因美封殺TikTok,字節(jié)股價骨折!估值僅Meta1/5
- 3 宏山激光重磅發(fā)布行業(yè)解決方案,助力智能制造產(chǎn)業(yè)新飛躍
- 4 國產(chǎn)AI芯片公司破產(chǎn)!白菜價拍賣
- 5 具身智能火了,但規(guī)模落地還需時間
- 6 國產(chǎn)英偉達們,抓緊沖刺A股
- 7 三次錯失風(fēng)口!OpenAI前員工殺回AI編程賽道,老東家捧金相助
- 8 英特爾賦能智慧醫(yī)療,共創(chuàng)數(shù)字化未來
- 9 英偉達的麻煩在后頭?
- 10 將“網(wǎng)紅”變成“商品”,AI“爆改”實力拉滿
- 高級軟件工程師 廣東省/深圳市
- 自動化高級工程師 廣東省/深圳市
- 光器件研發(fā)工程師 福建省/福州市
- 銷售總監(jiān)(光器件) 北京市/海淀區(qū)
- 激光器高級銷售經(jīng)理 上海市/虹口區(qū)
- 光器件物理工程師 北京市/海淀區(qū)
- 激光研發(fā)工程師 北京市/昌平區(qū)
- 技術(shù)專家 廣東省/江門市
- 封裝工程師 北京市/海淀區(qū)
- 結(jié)構(gòu)工程師 廣東省/深圳市