目录
0、项目介绍
1、效果展示
2、项目搭建
3、项目代码展示与部分讲解
pyzjr库
游戏实现思路
4、项目资源
5、项目总结
简单的自娱自乐的计算机视觉互动游戏,石头剪刀布,使用random生成随机数,用于模拟AI窗口随机出拳,玩家窗口手势识别检测石头、剪刀、布三种手势,根据游戏规则,两方玩家进行比较,按下空格键即为游戏开始,玩家在游戏开始后,有三秒的时间思考出拳策略。计时器会显示在屏幕上。在时间结束后,玩家出拳并与AI进行比较,根据游戏规则判断胜负并累计分数。
安装pyzjr:
pip install pyzjr==1.0.4
必须要安装大于等于1.0.4版本以上,详细可看此处。
这个工程只需要一个main文件就足够了。
import pyzjr as pz
import cv2
from cvzone.HandTrackingModule import HandDetector
import time
import random
import cvzone
Vap=pz.VideoCap()
Vap.CapInit()
imgList,all = pz.getPhotopath(r"Resources",debug=False)
detector = HandDetector(maxHands=1,detectionCon=0.8)
timer = 0
stateResult = False
startGame = False
scores = [0, 0] # [AI, Player]
imgAI = None
initialTime = 0
while True:
img = Vap.read(flip=1)
imgbackground = cv2.imread(imgList[0])
imgScaled = cv2.resize(img, (0, 0), None, 0.875, 0.875)[:, 80:480]
hands = detector.findHands(imgScaled,draw=False)
if startGame:
if stateResult is False:
timer = time.time() - initialTime
cv2.putText(imgbackground, str(int(timer)), (605, 435), cv2.FONT_HERSHEY_PLAIN, 6, pz.purple, 4)
if timer > 3:
stateResult = True
timer = 0
if hands:
playerMove = None
hand = hands[0]
fingers = detector.fingersUp(hand)
if fingers == [0, 0, 0, 0, 0]:
playerMove = 1
if fingers == [1, 1, 1, 1, 1]:
playerMove = 2
if fingers == [0, 1, 1, 0, 0]:
playerMove = 3
randomNumber = random.randint(1, 3)
imgAI = cv2.imread(imgList[randomNumber], cv2.IMREAD_UNCHANGED)
imgbackground = cvzone.overlayPNG(imgbackground, imgAI, (149, 310))
winning_rules = {
# 1-石头,2-布,3-剪刀
(1, 3): "player", # 石头 vs 剪刀
(2, 1): "player", # 布 vs 石头
(3, 2): "player", # 剪刀 vs 布
(3, 1): "AI", # 剪刀 vs 石头
(1, 2): "AI", # 石头 vs 布
(2, 3): "AI", # 布 vs 剪刀
}
result = winning_rules.get((playerMove, randomNumber))
if result == "player":
scores[1] += 1
elif result == "AI":
scores[0] += 1
imgbackground[234:654, 795:1195] = imgScaled
if stateResult:
imgbackground = cvzone.overlayPNG(imgbackground, imgAI, (149, 310))
cv2.putText(imgbackground, str(scores[0]), (410, 215), cv2.FONT_HERSHEY_PLAIN, 4, pz.white, 6)
cv2.putText(imgbackground, str(scores[1]), (1112, 215), cv2.FONT_HERSHEY_PLAIN, 4, pz.white, 6)
cv2.imshow("background", imgbackground)
k = cv2.waitKey(1)
if k == 32:
startGame = True
initialTime = time.time()
stateResult = False
elif k == 27:
break
只要环境没有任何问题,这个代码是可以直接运行的,我先来讲解一下pyzjr的一些函数。
VideoCap:opencv视频捕捉类的再封装,CapInit为VideoCap的镜头初始化函数,默认的参数为调取本地摄像头、宽度、高度、亮度,未给参数,使用默认值即可。read函数只返回img,不返回标志位,flip参数可选,对镜头进行翻转,1表示进行了水平翻转。
getPhotopath:获取目标文件夹下的路径,解决了转义字符的问题。debug默认为True,会返回路径有问题的信息,可以设置为False。
white,purple:常量,默认的BGR格式。
游戏开始后,使用计时器来限制玩家思考时间。在倒计时结束后,玩家会做出出拳动作。利用条件判断来比较玩家和AI的出拳,根据游戏规则判断胜负并计算分数。
检测玩家的手势的方式是使用的mediapipe的方法,这在cvzone中已被集成。通过打印fingers的值,确定剪刀、石头、布三种手势的手指上下的情况。overlayPNG函数将AI的出拳图像也加入到了背景图像中,让玩家能够清楚地看到双方的出拳。
游戏规则的方式由字典的方式进行判断,scores=[AI,player]进行累计积分,并打印在背景图片当中。通过按下空格键来触发游戏的重新开始。玩家有三秒的时间来思考出拳策略,倒计时会显示在屏幕上,让玩家清楚地知道还剩多少时间。
请注意手势识别错误或相同手势均不计分。
Opencv项目实战:24 石头剪刀布
通过手势识别检测石头、剪刀、布完成了这个视觉小游戏,比起网上现在的形态学方法和搭建模型要简单许多。个人也可以体验一下视觉游戏的乐趣,检测手势的画面被我关了,你可以通过将findHands的参数draw设置为True即可。