准备工作
pycharm新建项目,在虚拟环境中下载好mediapipe,opencv-python,cvzone。大家可以执行一段代码就看一下效果,总代码在文末。
打开摄像头捕捉图像
cap = cv2.VideoCapture(0)//0是本机摄像头的设备号
cap.set(3, 1280)//3代表图像的宽度,宽度设置为1280
cap.set(4, 720)//4代表图像的高度,高度设置为720
while True:
_, img = cap.read()//read函数返回两个值,第一个值可以忽略,第二个值img是捕捉到的图像
cv2.imshow("Image", img)//第一个参数是图像的名字,可以随意决定;第二个参数是摄像头捕捉的图像
cv2.waitKey(1)//1代表延时1ms,0代表延时无限时间
加游戏背景图片
# 导入所有图片
imgBackground = cv2.imread("Resources/Background.png")
imgGameOver = cv2.imread("Resources/gameOver.png")
imgBall = cv2.imread("Resources/Ball.png", cv2.IMREAD_UNCHANGED)//第二个参数让cv2导入图片时,不做任何处理
imgBat1 = cv2.imread("Resources/bat1.png", cv2.IMREAD_UNCHANGED)
imgBat2 = cv2.imread("Resources/bat2.png", cv2.IMREAD_UNCHANGED)
img = cv2.addWeighted(img, 0.2, imgBackground, 0.8, 0)//在while循环内将游戏背景图片覆盖在摄像头捕捉的图片之上,0.2代表img图像的透明度,0.8代表游戏背景图片的透明度
识别手势
detector = HandDetector(detectionCon=0.8, maxHands=2)//maxhands为2意味着只需要检测到两只手,不会检测到第三只手
hands, img = detector.findHands(img)
左右手镜面翻转
img = cv2.flip(img, 1)
hands, img = detector.findHands(img, flipType=False)
画乒乓球
img = cvzone.overlayPNG(img, imgBall, (100,100))//参数:原图像;粘贴图像;粘贴位置
竖杆随着手的出现而出现
if hands:
for hand in hands:
if hand['type'] == "Left":
img=cvzone.overlayPNG(img,imgBat1,(59,100))//(59,100)是坐标
竖杆的位置由手的位置而决定
x, y, w, h = hand['bbox']//bbox意味着boundingbox,返回横坐标,纵坐标,宽度,高度
h1, w1, _ = imgBat1.shape//竖杆的大小,返回高度,宽度,通道(在这里不需要)
y1 = y - h1 // 2
img = cvzone.overlayPNG(img, imgBat1, (59, y1))//根据手的位置确定数杆的纵坐标(59,y1)
规定竖杆纵坐标的范围
y1 = np.clip(y1, 20, 415)//y1的纵坐标范围在20-415之间
补全左右手位置确定竖杆位置的代码
if hands:
for hand in hands:
x, y, w, h = hand['bbox']
h1, w1, _ = imgBat1.shape
y1 = y - h1 // 2
y1 = np.clip(y1, 20, 415)
if hand['type'] == "Left":
img = cvzone.overlayPNG(img, imgBat1, (59, y1))
if hand['type'] == "Right":
img = cvzone.overlayPNG(img, imgBat2, (1195, y1))
移动小球
ballPos = [100, 100]//小球的初始位置
speedX = 15//小球x方向运动的速度
speedY = 15
ballPos[0] += speedX
ballPos[1] += speedY
img = cvzone.overlayPNG(img, imgBall, ballPos)
小球到达上下边界时,换方向运动
if ballPos[1] >= 500 or ballPos[1] <= 10:
speedY = -speedY
小球撞到竖杆时,换方向运动
if 59 < ballPos[0] < 59 + w1 and y1 < ballPos[1] < y1 + h1:
speedX = -speedX
if 1195 - 50 < ballPos[0] < 1195 and y1 < ballPos[1] < y1 + h1:
speedX = -speedX
为了撞击更有视觉效果
if 59 < ballPos[0] < 59 + w1 and y1 < ballPos[1] < y1 + h1:
speedX = -speedX
ballPos[0] += 30//加上这行代码
if 1195 - 50 < ballPos[0] < 1195 and y1 < ballPos[1] < y1 + h1:
speedX = -speedX
ballPos[0] -= 30
游戏结束
gameOver = False
if ballPos[0] < 40 or ballPos[0] > 1200://如果没有击中竖杆,游戏结束
gameOver = True
if gameOver:
img = imgGameOver//如果游戏结束,用游戏结束的图片覆盖画面
else:
# move the ball
计算分数
score = [0, 0]
if 59 < ballPos[0] < 59 + w1 and y1 < ballPos[1] < y1 + h1:
speedX = -speedX
ballPos[0] += 30
score[0] += 1//若击中竖杆便加一分
cv2.putText(img, str(score[0]), (300, 650), cv2.FONT_HERSHEY_COMPLEX, 3, (255, 255, 255), 5)//实时显示左右手的分数
cv2.putText(img, str(score[1]), (900, 650), cv2.FONT_HERSHEY_COMPLEX, 3, (255, 255, 255), 5)
cv2.putText(img, str(score[1] + score[0]).zfill(2), (585, 360), cv2.FONT_HERSHEY_SIMPLEX, 2.5, (200, 0, 200), 5)//游戏结束界面计算总分
重新开始游戏
key = cv2.waitKey(1)
if key == ord('r'):
ballPos = [100, 100]
speedX = 15
speedX = 15
gameOver = False
score = [0, 0]
总代码
import cv2
import cvzone
from cvzone.HandTrackingModule import HandDetector
import numpy as np
# import all images
imgBackground = cv2.imread("Resources/Background.png")
imgGameOver = cv2.imread("Resources/gameOver.png")
imgBall = cv2.imread("Resources/Ball.png", cv2.IMREAD_UNCHANGED)
imgBat1 = cv2.imread("Resources/bat1.png", cv2.IMREAD_UNCHANGED)
imgBat2 = cv2.imread("Resources/bat2.png", cv2.IMREAD_UNCHANGED)
cap = cv2.VideoCapture(0)
cap.set(3, 1280)
cap.set(4, 720)
# hand detector
detector = HandDetector(detectionCon=0.8, maxHands=2)
# variables
ballPos = [100, 100]
speedX = 15
speedY = 15
gameOver = False
score = [0, 0]
while True:
_, img = cap.read()
img = cv2.flip(img, 1)
# find the hands and landmarks
hands, img = detector.findHands(img, flipType=False)
# overlay the background image
img = cv2.addWeighted(img, 0.2, imgBackground, 0.8, 0)
# check the hands
if hands:
for hand in hands:
x, y, w, h = hand['bbox']
h1, w1, _ = imgBat1.shape
y1 = y - h1 // 2
y1 = np.clip(y1, 20, 415)
if hand['type'] == "Left":
img = cvzone.overlayPNG(img, imgBat1, (59, y1))
if 59 < ballPos[0] < 59 + w1 and y1 < ballPos[1] < y1 + h1:
speedX = -speedX
ballPos[0] += 30
score[0] += 1
if hand['type'] == "Right":
img = cvzone.overlayPNG(img, imgBat2, (1195, y1))
if 1195 - 50 < ballPos[0] < 1195 and y1 < ballPos[1] < y1 + h1:
speedX = -speedX
ballPos[0] -= 30
score[1] += 1
if ballPos[0] < 40 or ballPos[0] > 1200:
gameOver = True
if gameOver:
img = imgGameOver
cv2.putText(img, str(score[1] + score[0]).zfill(2), (585, 360), cv2.FONT_HERSHEY_SIMPLEX, 2.5, (200, 0, 200), 5)
else:
# move the ball
if ballPos[1] >= 500 or ballPos[1] <= 10:
speedY = -speedY
ballPos[0] += speedX
ballPos[1] += speedY
# draw the ball
img = cvzone.overlayPNG(img, imgBall, ballPos)
cv2.putText(img, str(score[0]), (300, 650), cv2.FONT_HERSHEY_COMPLEX, 3, (255, 255, 255), 5)
cv2.putText(img, str(score[1]), (900, 650), cv2.FONT_HERSHEY_COMPLEX, 3, (255, 255, 255), 5)
cv2.imshow("Image", img)
key = cv2.waitKey(1)
if key == ord('r'):
ballPos = [100, 100]
speedX = 15
speedX = 15
gameOver = False
score = [0, 0]
今天的文章乒乓游戏|手势识别|计算机视觉分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/66277.html