OpenCV 是一个基于 Apache2.0 许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。
需要提前准备opencv 和 mediapipe库
pip --default-timeout=5000 install -i https://pypi.tuna.tsinghua.edu.cn/simple mediapipe
接着上一章的内容,这一次我们加入了fps显示和模块封装,以便我们接下来的学习。
import cv2
import numpy as np
import mediapipe as mp
import time
这部分是导入所需的Python库。cv2
是OpenCV库,用于图像处理和计算机视觉任务。numpy
用于数值计算。mediapipe
是一个Google开发的库,用于处理计算机视觉任务,例如姿势检测、手势识别等。time
是Python标准库,用于处理时间相关的操作。
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, self.detectionCon, self.trackCon)
self.mpDraw = mp.solutions.drawing_utils
这部分定义了一个名为 handDetector
的类。它有一个构造函数 __init__
,用于初始化手部检测器对象。传递给构造函数的参数包括:
mode
: 用于设置手部检测的模式,默认为False
。maxHands
: 最大检测手的数量,默认为 2。detectionCon
: 检测的置信度阈值,默认为 0.5。trackCon
: 跟踪的置信度阈值,默认为 0.5。
在构造函数中,还初始化了 mpHands
,hands
和 mpDraw
对象。mpHands
是 mediapipe
库中的手部检测模块,hands
是用于手部检测的实际处理器,mpDraw
是用于在图像上绘制标记的实用工具。
def findHands(self, img, draw=True):
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
results = self.hands.process(imgRGB)
if results.multi_hand_landmarks:
for handLms in results.multi_hand_landmarks:
if draw:
self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS)
return img
这部分定义了一个名为 findHands
的方法,用于在给定图像上进行手部检测。它接受一个图像(img
)和一个布尔值参数 draw
,用于指定是否绘制检测结果。
在方法中,首先将图像转换为RGB格式,然后使用手部检测器 hands
处理图像,返回结果。如果检测到了手部,就遍历每个检测到的手部标记点,然后在图像上绘制出手部标记和连接线。最后,返回绘制了标记的图像。
def findPosition(self,img,handNO=0,draw = True):
lmList = []
if self.results.multi_hand_landmarks:
myHand = self.results.multi_hand_landmarks[handNO]
for id, lm in enumerate(myHand.landmark):
h, w, c = img.shape
cx, cy = int(lm.x * w), int(lm.y * h)
lmList.append([id,cx,cy])
if draw:
cv2.circle(img, (cx, cy), 10, (255, 255, 0), cv2.FILLED)
return lmList
这部分定义了 findPosition
方法,用于获取手部标记点的坐标。方法接收一个图像(img
)、一个可选的 handNO
参数(表示检测到的手部编号,默认为0)和一个布尔值参数 draw
。方法首先检查是否有检测到的手部,如果有,就获取指定编号的手部标记点信息。然后,遍历手部标记点,计算并保存标记点的坐标,并在图像上绘制圆圈。最后,返回标记点坐标的列表。
def main():
pTime = 0
cTime = 0
cap = cv2.VideoCapture(0)
detector = handDetector(maxHands=1)
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, 155), 3)
cv2.imshow("Image", img)
cv2.waitKey(1)
if __name__ == '__main__':
main()
这部分定义了一个名为 main
的函数,用于主要的程序逻辑。在其中,首先初始化了摄像头捕获对象 cap
,然后创建了一个 handDetector
的实例,即手部检测器。
进入主循环,不断从摄像头捕获图像,然后调用 detector.findHands(img)
进行手部检测和绘制,将结果显示在窗口中。还计算并绘制了帧率信息。
最后,使用 cv2.waitKey(1)
来处理键盘输入,允许用户退出程序。
总体来说,这段代码实现了从摄像头捕获图像,并使用 mediapipe
进行手部检测和标记绘制,同时还显示了帧率信息。这可以用于实时手势识别和交互应用。
帧率在三十左右