Jeder kennt das Spiel „Snake“, aber das wenig bekannte Computer Vision + Snake-Spiel bringt den Menschen mehr Beteiligung und Frische. Dieses Projekt nutzt hauptsächlich Gestenerkennung Schließe das einfache Spiel „Snake“ ab. In diesem Spiel erfasst der Computer unsere Gesten durch die Kamera und bestimmt, ob er sich bewegen soll. Der Spieler bewegt seine Hand, um die Nahrung zu steuern, die zufällig auf dem Bildschirm erscheint Punkt, und der Punktestand wird auf dem Bildschirm angezeigt. Wenn der Spieler während des Betriebs versehentlich mit dem Kopf und Körper kollidiert, wird GameOver angezeigt.
(1) Das linke und rechte Problem des Bildes
Weil wir Gesten verwenden, um die Bewegung der Schlange zu steuern, aber das Kamerabild zeigt die Perspektive anderer Dies ist also genau das Gegenteil des linken und rechten Bewusstseins des Spielers, daher müssen wir das von der Kamera gelesene Bild nach links und rechts umdrehen. Im Prinzip wird die Position des linken und rechten Pixels vertauscht, aber in Python können Sie eine cv2.flip()-Funktion verwenden, um eine Spiegelung zu erreichen.
(2) Das Problem der Kamerabildschirmgröße
Wir müssen Spiele auf den über die Kamera aufgenommenen Bildern spielen. Wenn der Bildschirm zu klein ist, kann dies zu Beginn zu einer Vorverarbeitung führen Wählen Sie die Bildschirmgröße aus und stellen Sie eine angemessenere Größe ein, damit das endgültige Bild beim Spielen nicht beengt aussieht. Die Breite und Höhe des Bildschirms kann über die Funktionen cap.set(3, m) cap.set(4, n) eingestellt werden.
In diesem Projekt wird es auch einige andere Vorsichtsmaßnahmen geben, z. B. die Bestimmung von Kollisionen, die Bestimmung der Nahrungsaufnahme usw. Ich werde sie später im Projektprozess vorstellen.
3. Wichtige Punkte der Spielimplementierung
import math import random import cvzone import cv2 import numpy as np from cvzone.HandTrackingModule import HandDetector
2. Finden Sie die Schlüsselpunkte und markieren Sie sie.
In diesem Spiel haben wir eine Hand als Zielknoten ausgewählt. Wenn wir also eine Hand auf dem Bildschirm erkennen, müssen wir die Schlüsselpunkte markieren, und dieser Schlüsselpunkt passiert Da wir eine Bibliothek eines Drittanbieters aufrufen, können wir die Hand in 3D markieren, wir benötigen jedoch nur die beiden Koordinatenwerte x und y. Wir verwenden hauptsächlich Folgendes Funktion zum Markieren der Schlüsselknoten der Hand:
#检测到第一个手,并标记手部位置 if hands: lmList = hands[0]['lmList'] pointIndex = lmList[8][0:2] #第八个坐标点的 x, y值,其中 z 值不被包括在里面 cv2.circle(img, pointIndex, 20, (200, 0, 200), cv2.FILLED) #在关键点处绘制一个圆点并进行填充(此处只是示范,后面会更改)
Das Spiel, das wir implementieren müssen, ist eine Kombination aus vielen Funktionen. Wenn Sie Funktionen verwenden möchten, um diese zu implementieren Funktionen, dann Es wird sehr mühsam sein, es zu vervollständigen, da viele Dinge in derselben Klasse gespeichert werden. In diesem Kurs werden wir viele wichtige Listen erstellen, um einige der von uns verwendeten Schlüsselpunkte zu speichern, wie z. B. alle Punkte auf dem Körper der Schlange, die Länge der Schlange, die Gesamtentfernung der Schlange, die Platzierung der Nahrung, Punkte usw. :
class SnakeGameClass: def __init__(self, pathFood): self.points = [] #贪吃蛇身上所有点 self.lengths = [] #点与点之间的距离 self.currentLength = 0 #当下蛇的长度 self.allowedLength = 50 #最大允许长度(阈值) self.previousHead = 0, 0 #手部关键点之后的第一个点 self.imgFood = cv2.imread(pathFood, cv2.IMREAD_UNCHANGED) #定义食物 self.hFood, self.wFood, _ = self.imgFood.shape self.foodPoint = 0, 0 self.randomFoodLocation() self.score = 0 self.gameOver = False
Wenn sich unsere Hände bewegen, ändern sich Länge und Position der Schlange, daher müssen wir eine Funktion erstellen, die kontinuierlich aktualisiert wird, um sich ändernden Anforderungen gerecht zu werden (der Teil davon wird auch in ausgeführt). die zuvor erstellte große Klasse):
def update(self, imgMain, currentHead): #游戏结束,打印文本 if self.gameOver: cvzone.putTextRect(imgMain, "Game Over", [300, 400], scale=7, thickness=5, offset=20) cvzone.putTextRect(imgMain, f'Your Score: {self.score}', [300, 550], scale=7, thickness=5, offset=20) else: px, py = self.previousHead cx, cy = currentHead self.points.append([cx, cy]) distance = math.hypot(cx - px, cy - py) self.lengths.append(distance) self.currentLength += distance self.previousHead = cx, cy #长度缩小 if self.currentLength > self.allowedLength: for i, length in enumerate(self.lengths): self.currentLength -= length self.lengths.pop(i) self.points.pop(i) if self.currentLength < self.allowedLength: break #检查贪吃蛇是否已经触碰到食物 rx, ry = self.foodPoint if rx - self.wFood // 2 < cx < rx + self.wFood // 2 and \ ry - self.hFood // 2 < cy < ry + self.hFood // 2: self.randomFoodLocation() self.allowedLength += 50 self.score += 1 print(self.score) #使用线条绘制贪吃蛇 if self.points: for i, point in enumerate(self.points): if i != 0: cv2.line(imgMain, self.points[i - 1], self.points[i], (0, 0, 255), 20) cv2.circle(imgMain, self.points[-1], 20, (0, 255, 0), cv2.FILLED) #显示食物 imgMain = cvzone.overlayPNG(imgMain, self.imgFood, (rx - self.wFood // 2, ry - self.hFood // 2)) cvzone.putTextRect(imgMain, f'Score: {self.score}', [50, 80], scale=3, thickness=3, offset=10) #检测是否碰撞 pts = np.array(self.points[:-2], np.int32) pts = pts.reshape((-1, 1, 2)) cv2.polylines(imgMain, [pts], False, (0, 255, 0), 3) minDist = cv2.pointPolygonTest(pts, (cx, cy), True) if -1 <= minDist <= 1: print("Hit") self.gameOver = True self.points = [] #蛇身上所有的点 self.lengths = [] #不同点之间的距离 self.currentLength = 0 #当前蛇的长度 self.allowedLength = 50 #最大允许长度 self.previousHead = 0, 0 #先前的蛇的头部 self.randomFoodLocation() return imgMain
Hauptsächlich durch die oben definierte Klasse können wir das aktuelle Snake-Spiel implementieren.
4. Gesamtcode
Ich habe das Tutorial auf Station B gesehen und es Schritt für Schritt für dieses Minispiel reproduziert. Wenn Sie interessiert sind, können Sie es natürlich wie immer unten veröffentlichen.
""" Author:XiaoMa CSDN Address:一马归一码 """ import math import random import cvzone import cv2 import numpy as np from cvzone.HandTrackingModule import HandDetector cap = cv2.VideoCapture(0) #设置画面的尺寸大小,过小的话导致贪吃蛇活动不开 cap.set(3, 1280) cap.set(4, 720) detector = HandDetector(detectionCon=0.8, maxHands=1) class SnakeGameClass: def __init__(self, pathFood): self.points = [] #贪吃蛇身上所有点 self.lengths = [] #每一个点之间的距离 self.currentLength = 0 #当下蛇的长度 self.allowedLength = 50 #最大允许长度(阈值) self.previousHead = 0, 0 #手部关键点之后的第一个点 self.imgFood = cv2.imread(pathFood, cv2.IMREAD_UNCHANGED) #定义食物 self.hFood, self.wFood, _ = self.imgFood.shape self.foodPoint = 0, 0 self.randomFoodLocation() self.score = 0 self.gameOver = False def randomFoodLocation(self): self.foodPoint = random.randint(100, 1000), random.randint(100, 600) def update(self, imgMain, currentHead): #游戏结束,打印文本 if self.gameOver: cvzone.putTextRect(imgMain, "Game Over", [300, 400], scale=7, thickness=5, offset=20) cvzone.putTextRect(imgMain, f'Your Score: {self.score}', [300, 550], scale=7, thickness=5, offset=20) else: px, py = self.previousHead cx, cy = currentHead self.points.append([cx, cy]) distance = math.hypot(cx - px, cy - py) self.lengths.append(distance) self.currentLength += distance self.previousHead = cx, cy #长度缩小 if self.currentLength > self.allowedLength: for i, length in enumerate(self.lengths): self.currentLength -= length self.lengths.pop(i) self.points.pop(i) if self.currentLength < self.allowedLength: break #检查贪吃蛇是否已经触碰到食物 rx, ry = self.foodPoint if rx - self.wFood // 2 < cx < rx + self.wFood // 2 and \ ry - self.hFood // 2 < cy < ry + self.hFood // 2: self.randomFoodLocation() self.allowedLength += 50 self.score += 1 print(self.score) #使用线条绘制贪吃蛇 if self.points: for i, point in enumerate(self.points): if i != 0: cv2.line(imgMain, self.points[i - 1], self.points[i], (0, 0, 255), 20) cv2.circle(imgMain, self.points[-1], 20, (0, 255, 0), cv2.FILLED) #显示食物 imgMain = cvzone.overlayPNG(imgMain, self.imgFood, (rx - self.wFood // 2, ry - self.hFood // 2)) cvzone.putTextRect(imgMain, f'Score: {self.score}', [50, 80], scale=3, thickness=3, offset=10) #检测是否碰撞 pts = np.array(self.points[:-2], np.int32) pts = pts.reshape((-1, 1, 2)) cv2.polylines(imgMain, [pts], False, (0, 255, 0), 3) minDist = cv2.pointPolygonTest(pts, (cx, cy), True) if -1 <= minDist <= 1: print("Hit") self.gameOver = True self.points = [] #蛇身上所有的点 self.lengths = [] #不同点之间的距离 self.currentLength = 0 #当前蛇的长度 self.allowedLength = 50 #最大允许长度 self.previousHead = 0, 0 #先前的蛇的头部 self.randomFoodLocation() return imgMain game = SnakeGameClass("Donut.png") while True: success, img = cap.read() img = cv2.flip(img, 1) #镜像翻转 hands, img = detector.findHands(img, flipType=False) #检测到第一个手,并标记手部位置 if hands: lmList = hands[0]['lmList'] pointIndex = lmList[8][0:2] #第八个坐标点的 x, y值,其中 z 值不被包括在里面 #cv2.circle(img, pointIndex, 20, (200, 0, 200), cv2.FILLED) #在关键点处绘制一个圆点并进行填充(此处只是示范,后面会更改) img = game.update(img, pointIndex) cv2.imshow("Image", img) key = cv2.waitKey(1) #按下‘r'重新开始游戏 if key == ord('r'): game.gameOver = False
Das obige ist der detaillierte Inhalt vonWie Python Gestenerkennung nutzt, um das Snake-Spiel zu implementieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!