作者 | 原始碼•宸
使用Mediapipe
水平映象處理
import
cvzone
import
cv2
import
numpy
as
np
from
cvzone。HandTrackingModule
import
HandDetector
cap = cv2。VideoCapture(
0
)
# 0代表自己電腦的攝像頭
cap。set(
3
,
1280
)
# 寬
cap。set(
4
,
720
)
# 高
detector = HandDetector(detectionCon=
0。8
, maxHands=
2
)
# 處理每一幀影象
while
True
:
success, img = cap。read()
# 翻轉影象,使自身和攝像頭中的自己呈映象關係
img = cv2。flip(img,
1
)
# 將手水平翻轉
hands, img = detector。findHands(img)
cv2。imshow(
“Image”
, img)
cv2。waitKey(
1
)
修改程式碼
import
cvzone
import
cv2
import
numpy
as
np
from
cvzone。HandTrackingModule
import
HandDetector
cap = cv2。VideoCapture(
0
)
# 0代表自己電腦的攝像頭
cap。set(
3
,
1280
)
# 寬
cap。set(
4
,
720
)
# 高
detector = HandDetector(detectionCon=
0。8
, maxHands=
1
)
# 處理每一幀影象
while
True
:
success, img = cap。read()
# 翻轉影象,使自身和攝像頭中的自己呈映象關係
img = cv2。flip(img,
1
)
# 將手水平翻轉
hands, img = detector。findHands(img, flipType=
False
)
# 左手是左手,右手是右手,對映正確
cv2。imshow(
“Image”
, img)
cv2。waitKey(
1
)
問題修復完畢
觀察手的資訊
import
cvzone
import
cv2
import
numpy
as
np
from
cvzone。HandTrackingModule
import
HandDetector
cap = cv2。VideoCapture(
0
)
# 0代表自己電腦的攝像頭
cap。set(
3
,
1280
)
# 寬
cap。set(
4
,
720
)
# 高
detector = HandDetector(detectionCon=
0。8
, maxHands=
1
)
# 處理每一幀影象
while
True
:
success, img = cap。read()
# 翻轉影象,使自身和攝像頭中的自己呈映象關係
img = cv2。flip(img,
1
)
# 將手水平翻轉
hands, img = detector。findHands(img, flipType=
False
)
# 左手是左手,右手是右手,對映正確
print(hands)
cv2。imshow(
“Image”
, img)
cv2。waitKey(
1
)
輸出結果
[{‘lmList’: [[1088, 633, 0], [1012, 655, -24], [940, 629, -32], [894, 596, -35], [875, 562, -36], [949, 504, -17], [891, 441, -16], [862, 419, -16], [838, 403, -16], [995, 480, -3], [943, 418, 8], [924, 426, 17], [920, 440, 22], [1044, 480, 8], [998, 455, 17], [987, 489, 21], [993, 513, 23], [1085, 492, 19], [1048, 477, 27], [1036, 505, 35], [1041, 528, 40]], ‘bbox’: (838, 403, 250, 252), ‘center’: (963, 529), ‘type’: ‘Left’}]
做個小蛇
import math
import cvzone
import cv2
import numpy as np
from cvzone。HandTrackingModule import HandDetector
cap = cv2。VideoCapture(
0
)
# 0代表自己電腦的攝像頭
cap。set(
3
,
1280
)
# 寬
cap。set(
4
,
720
)
# 高
detector = HandDetector(detectionCon=
0
。
8
, maxHands=
1
)
class
SnakeGameClass
:
def
__init__
(
self
)
:
# 構造方法
self
。points = []
# 蛇身上所有的點
self
。lengths = []
# 每個點之間的長度
self
。currentLength =
0
# 蛇的總長
self
。allowedLength =
150
# 蛇允許的總長度
self
。previousHead =
0
,
0
# 第二個頭結點
def
update
(
self
, imgMain, currentHead)
:
# 例項方法
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
# Draw Snake
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
, (
200
,
0
,
200
), cv2。FILLED)
return
imgMain
game = SnakeGameClass()
# 處理每一幀影象
while
True:
# 不斷迭代更新
success, img = cap。read()
# 翻轉影象,使自身和攝像頭中的自己呈映象關係
img = cv2。flip(img,
1
)
# 將手水平翻轉
hands, img = detector。findHands(img, flipType=False)
# 左手是左手,右手是右手,對映正確
if
hands:
lmList = hands[
0
][
‘lmList’
]
# hands是由N個字典組成的列表
pointIndex = lmList[
8
][
0
:
2
]
# 只要食指指尖的x和y座標
img = game。update(img, pointIndex)
cv2。imshow(
“Image”
, img)
cv2。waitKey(
1
)
新增甜甜圈
import
math
import
random
import
cvzone
import
cv2
import
numpy
as
np
from
cvzone。HandTrackingModule
import
HandDetector
cap = cv2。VideoCapture(
0
)
# 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 =
150
# 蛇允許的總長度
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()
def
randomFoodLocation
(self)
:
self。foodPoint = random。randint(
100
,
1000
), random。randint(
100
,
600
)
def
update
(self, imgMain, currentHead)
:
# 例項方法
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
# Length Reduction
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
break
# Draw Snake
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
, (
200
,
0
,
200
), cv2。FILLED)
# Draw Food
rx, ry = self。foodPoint
imgMain = cvzone。overlayPNG(imgMain, self。imgFood,
(rx - self。wFood //
2
, ry - self。hFood //
2
))
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’
]
# hands是由N個字典組成的列表
pointIndex = lmList[
8
][
0
:
2
]
# 只要食指指尖的x和y座標
img = game。update(img, pointIndex)
cv2。imshow(
“Image”
, img)
cv2。waitKey(
1
)
donut。png
部分程式碼解釋說明
imgMain = cvzone。overlayPNG(imgMain,
self
。imgFood, (rx -
self
。wFood
// 2, ry - self。hFood // 2))
為什麼不是
imgMain
= cvzone。overlayPNG(imgMain, self。imgFood, (rx , ry))
那是因為,隨機生成一個點後,有座標(x,y)
增加分數機制
import
math
import
random
import
cvzone
import
cv2
import
numpy
as
np
from
cvzone。HandTrackingModule
import
HandDetector
cap = cv2。VideoCapture(
0
)
# 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 =
150
# 蛇允許的總長度
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
def
randomFoodLocation
(self)
:
self。foodPoint = random。randint(
100
,
1000
), random。randint(
100
,
600
)
def
update
(self, imgMain, currentHead)
:
# 例項方法
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
# Length Reduction
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
break
# Check if snake ate the food
rx, ry = self。foodPoint
if
rx - self。wFood //
2
2
and
\
ry - self。hFood //
2
2:
self。randomFoodLocation()
self。allowedLength +=
50
self。score +=
1
print(self。score)
# Draw Snake
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
, (
200
,
0
,
200
), cv2。FILLED)
# Draw Food
imgMain = cvzone。overlayPNG(imgMain, self。imgFood,
(rx - self。wFood //
2
, ry - self。hFood //
2
))
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’
]
# hands是由N個字典組成的列表
pointIndex = lmList[
8
][
0
:
2
]
# 只要食指指尖的x和y座標
img = game。update(img, pointIndex)
cv2。imshow(
“Image”
, img)
cv2。waitKey(
1
)
完整程式碼
import
math
import
random
import
cvzone
import
cv2
import
numpy
as
np
from
cvzone。HandTrackingModule
import
HandDetector
cap = cv2。VideoCapture(
0
)
# 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 =
150
# 蛇允許的總長度
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
# Length Reduction
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
break
# Check if snake ate the food
rx, ry = self。foodPoint
if
rx - self。wFood //
2
2
and
\
ry - self。hFood //
2
2:
self。randomFoodLocation()
self。allowedLength +=
50
self。score +=
1
print(self。score)
# Draw Snake
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
, (
200
,
0
,
200
), cv2。FILLED)
# Draw Food
imgMain = cvzone。overlayPNG(imgMain, self。imgFood,
(rx - self。wFood //
2
, ry - self。hFood //
2
))
cvzone。putTextRect(imgMain,
f‘Your Score:
{self。score}
’
, [
50
,
80
],
scale=
3
, thickness=
5
, offset=
10
)
# Check for Collision
pts = np。array(self。points[:
-2
], np。int32)
pts = pts。reshape((
-1
,
1
,
2
))
# 重塑為一個行數未知但只有一列且每個元素有2個子元素的矩陣
cv2。polylines(imgMain, [pts],
False
, (
0
,
200
,
0
),
3
)
# 第三個引數是False,我們得到的是不閉合的線
minDist = cv2。pointPolygonTest(pts, (cx, cy),
True
)
# 引數True表示輸出該畫素點到輪廓最近距離
if
-1
1:
print(
“Hit”
)
self。gameOver =
True
self。points = []
# 蛇身上所有的點
self。lengths = []
# 每個點之間的長度
self。currentLength =
0
# 蛇的總長
self。allowedLength =
150
# 蛇允許的總長度
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’
]
# hands是由N個字典組成的列表
pointIndex = lmList[
8
][
0
:
2
]
# 只要食指指尖的x和y座標
img = game。update(img, pointIndex)
cv2。imshow(
“Image”
, img)
key = cv2。waitKey(
1
)
if
key == ord(
‘r’
):
game。gameOver =
False
開啟App看更多精彩內容