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

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

在这里插入图片描述

准备工作

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,100100)//参数:原图像;粘贴图像;粘贴位置

竖杆随着手的出现而出现

 if hands:
        for hand in hands:
            if hand['type'] == "Left":
                img=cvzone.overlayPNG(img,imgBat1,(59,100))//59100)是坐标

竖杆的位置由手的位置而决定

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

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注