内容目录
参考视频:https://www.youtube.com/watch?v=NZde8Xt78Iw
完整代码见:github仓库
前期准备
1、安装opencv-python和mediapipe库(参考[[安装类]])
手部关节21点标号说明
1、读取摄像头
import cv2
import mediapipe as mp
import time
cap = cv2.VideoCapture(0)
while True:
success, img = cap.read()
cv2.imshow("Image",img)
cv2.waitKey(1)
2、检测手部并将手部的21个点表现出来
import cv2
import mediapipe as mp
import time
# 打开默认摄像头
cap = cv2.VideoCapture(0)
# 创建一个手的实体类来存储手部信息
mpHands = mp.solutions.hands
hands = mpHands.Hands()
# 创建一个用于绘制手部关键点和连接线的实体类
mpDraw = mp.solutions.drawing_utils
while True:
# 从摄像头捕获一帧图像
success, img = cap.read()
# 将捕获的图像从BGR颜色空间转换为RGB颜色空间
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 处理图像以检测手部信息
results = hands.process(imgRGB)
# 检查是否检测到了手部关键点
if results.multi_hand_landmarks:
# 遍历每个检测到的手
for handLms in results.multi_hand_landmarks:
# 在图像上绘制手部关键点和连接线
mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
# 在窗口中显示图像
cv2.imshow("Image", img)
# 按键等待1毫秒,允许窗口保持打开状态
cv2.waitKey(1)
3、添加帧率显示
# 初始化参数
pTime = 0
cTime = 0
...
...
...
# 当前时间
cTime = time.time()
# 计算fps
fps = 1 / (cTime-pTime)
# 存储当前时间
pTime = cTime
# 将fps显示在img上
cv2.putText(img,str(int(fps)),(10,70),cv2.FONT_HERSHEY_PLAIN,3,
(255,0,255),3)
4、获取每个点的坐标
# 获得手部21点的id和其对应的坐标
for id, lm in enumerate(handLms.landmark):
# print(id,lm)
h, w, c = img.shape
cx, cy = int(lm.x*w), int(lm.y*h)
print(id, cx, cy)
if id ==0:
cv2.circle(img, (cx,cy), 25, (255,0,255), cv2.FILLED)
完整版代码
import cv2
import mediapipe as mp
import time
# 打开默认摄像头
cap = cv2.VideoCapture(0)
# 创建一个手的实体类来存储手部信息
mpHands = mp.solutions.hands
hands = mpHands.Hands()
# 创建一个用于绘制手部关键点和连接线的实体类
mpDraw = mp.solutions.drawing_utils
pTime = 0
cTime = 0
while True:
# 从摄像头捕获一帧图像
success, img = cap.read()
# 将捕获的图像从BGR颜色空间转换为RGB颜色空间
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 处理图像以检测手部信息
results = hands.process(imgRGB)
# 检查是否检测到了手部关键点
if results.multi_hand_landmarks:
# 遍历每个检测到的手
for handLms in results.multi_hand_landmarks:
# 获得手部21点的id和其对应的坐标
for id, lm in enumerate(handLms.landmark):
# print(id,lm)
h, w, c = img.shape
cx, cy = int(lm.x*w), int(lm.y*h)
print(id, cx, cy)
if id ==0:
cv2.circle(img, (cx,cy), 25, (255,0,255), cv2.FILLED)
# 在图像上绘制手部关键点和连接线
mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
cTime = time.time()
fps = 1 / (cTime-pTime)
pTime = cTime
cv2.putText(img,str(int(fps)),(10,70),cv2.FONT_HERSHEY_PLAIN,3,
(255,0,255),3)
# 在窗口中显示图像
cv2.imshow("Image", img)
# 按键等待1毫秒,允许窗口保持打开状态
cv2.waitKey(1)
完整版代码(模块化)
将v1版本封装成实体类和函数
import cv2
import mediapipe as mp
import time
class handDetector():
def __init__(self, mode=False, maxHands = 2, detectionCon=0.5, trackCon=0.5):
self.mode = mode
self.maxHands = maxHands
self.detectionCon = detectionCon
self.trackCon = trackCon
# 创建一个手的实体类来存储手部信息
self.mpHands = mp.solutions.hands
self.hands = self.mpHands.Hands(self.mode, self.maxHands, 1, self.detectionCon, self.trackCon)
# 创建一个用于绘制手部关键点和连接线的实体类
self.mpDraw = mp.solutions.drawing_utils
def findHands(self, img, draw = True):
# 将捕获的图像从BGR颜色空间转换为RGB颜色空间
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 处理图像以检测手部信息
self.results = self.hands.process(imgRGB)
# 检查是否检测到了手部关键点
if self.results.multi_hand_landmarks:
# 遍历每个检测到的手
for handLms in self.results.multi_hand_landmarks:
if draw:
# 在图像上绘制手部关键点和连接线
self.mpDraw.draw_landmarks(img, handLms,
self.mpHands.HAND_CONNECTIONS)
return img
def findPosition(self, img, handNo=0, draw=True):
lmList = []
# 检查是否检测到了手部关键点
if self.results.multi_hand_landmarks:
# 存储对应的手,此处默认handNo=0
myHand = self.results.multi_hand_landmarks[handNo]
# 获得手部21点的id和其对应的坐标
for id, lm in enumerate(myHand.landmark):
h, w, c = img.shape
cx, cy = int(lm.x * w), int(lm.y * h)
# 将参数添加入lmList
lmList.append([id, cx, cy])
if draw:
cv2.circle(img, (cx, cy), 10, (255, 0, 255), cv2.FILLED)
return lmList
def main():
pTime = 0
cTime = 0
# 打开默认摄像头
cap = cv2.VideoCapture(0)
# 生成实体类
detector = handDetector()
while True:
# 从摄像头捕获一帧图像
success, img = cap.read()
# 调用实体类的相关函数
img = detector.findHands(img)
lmList = detector.findPosition(img)
if len(lmList) != 0:
print(lmList[4])
cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime
cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3,
(255, 0, 255), 3)
# 在窗口中显示图像
cv2.imshow("Image", img)
# 按键等待1毫秒,允许窗口保持打开状态
cv2.waitKey(1)
if __name__ == "__main__":
main()