栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

乒乓游戏|手势识别|计算机视觉

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

乒乓游戏|手势识别|计算机视觉

准备工作

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]

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/982707.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号