在Python中使用 OpenCV 进行手部检测的亮度控制
在本文中,我们将制作一个Python项目,使用 OpenCV 和 Mediapipe 来查看手势,并相应地将系统的亮度设置为 0-100 的范围。
我们使用了一个 HandTracking 模块,该模块跟踪手上的所有点并检测手部标志,计算拇指尖和食指尖之间的距离,并根据亮度范围映射拇指尖和食指尖之间的距离。
所需的库
- Mediapipe:它是 Google 的开源框架,用于媒体处理。它是跨平台的,或者我们可以说它是平台友好的。它可以在 Android、iOS 和 Web 上运行,这就是跨平台的意思,可以在任何地方运行。
pip install mediapipe
- OpenCV :它是一个Python库,旨在解决计算机视觉问题。 OpenCV 支持多种编程语言,如 C++、 Python、 Java等。支持多种平台,包括 Windows、Linux 和 MacOS。
pip install opencv-python
- 屏幕亮度控制:它 是一个用于控制显示器亮度的Python工具。支持 Windows 和大多数版本的 Linux。
pip install screen-brightness-control
- 麻木:它 是一个通用的数组处理包。它提供了一个高性能的多维数组对象,以及用于处理这些数组的工具。它是使用Python进行科学计算的基础包。
pip install numpy
逐步实施
第 1 步:导入所有必需的库
Python3
# Importing Libraries
import cv2
import mediapipe as mp
from math import hypot
import screen_brightness_control as sbc
import numpy as np
Python3
# Initializing the Model
mpHands = mp.solutions.hands
hands = mpHands.Hands(
static_image_mode=False,
model_complexity=1,
min_detection_confidence=0.75,
min_tracking_confidence=0.75,
max_num_hands=2)
Draw = mp.solutions.drawing_utils
Python3
# Start capturing video from webcam
cap = cv2.VideoCapture(0)
while True:
# Read video frame by frame
_,frame = cap.read()
#Flip image
frame=cv2.flip(frame,1)
# Convert BGR image to RGB image
frameRGB = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
# Process the RGB image
Process = hands.process(frameRGB)
landmarkList = []
# if hands are present in image(frame)
if Process.multi_hand_landmarks:
# detect handmarks
for handlm in Process.multi_hand_landmarks:
for _id,landmarks in enumerate(handlm.landmark):
# store height and width of image
height,width,color_channels = frame.shape
# calculate and append x, y coordinates
# of handmarks from image(frame) to lmList
x,y = int(landmarks.x*width),int(landmarks.y*height)
landmarkList.append([_id,x,y])
# draw Landmarks
Draw.draw_landmarks(frame,handlm,mpHands.HAND_CONNECTIONS)
# If landmarks list is not empty
if landmarkList != []:
# store x,y coordinates of (tip of) thumb
x_1,y_1 = landmarkList[4][1],landmarkList[4][2]
# store x,y coordinates of (tip of) index finger
x_2,y_2 = landmarkList[8][1],landmarkList[8][2]
# draw circle on thumb and index finger tip
cv2.circle(frame,(x_1,y_1),7,(0,255,0),cv2.FILLED)
cv2.circle(frame,(x_2,y_2),7,(0,255,0),cv2.FILLED)
# draw line from tip of thumb to tip of index finger
cv2.line(frame,(x_1,y_1),(x_2,y_2),(0,255,0),3)
# calculate square root of the sum
# of squares of the specified arguments.
L = hypot(x_2-x_1,y_2-y_1)
# 1-D linear interpolant to a function
# with given discrete data points
# (Hand range 15 - 220, Brightness range 0 - 100),
# evaluated at length.
b_level = np.interp(L,[15,220],[0,100])
# set brightness
sbc.set_brightness(int(b_level))
# Display Video and when 'q' is entered,
# destroy the window
cv2.imshow('Image', frame)
if cv2.waitKey(1) & 0xff == ord('q'):
break
Python3
# Importing Libraries
import cv2
import mediapipe as mp
from math import hypot
import screen_brightness_control as sbc
import numpy as np
# Initializing the Model
mpHands = mp.solutions.hands
hands = mpHands.Hands(
static_image_mode=False,
model_complexity=1,
min_detection_confidence=0.75,
min_tracking_confidence=0.75,
max_num_hands=2)
Draw = mp.solutions.drawing_utils
# Start capturing video from webcam
cap = cv2.VideoCapture(0)
while True:
# Read video frame by frame
_, frame = cap.read()
# Flip image
frame = cv2.flip(frame, 1)
# Convert BGR image to RGB image
frameRGB = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Process the RGB image
Process = hands.process(frameRGB)
landmarkList = []
# if hands are present in image(frame)
if Process.multi_hand_landmarks:
# detect handmarks
for handlm in Process.multi_hand_landmarks:
for _id, landmarks in enumerate(handlm.landmark):
# store height and width of image
height, width, color_channels = frame.shape
# calculate and append x, y coordinates
# of handmarks from image(frame) to lmList
x, y = int(landmarks.x*width), int(landmarks.y*height)
landmarkList.append([_id, x, y])
# draw Landmarks
Draw.draw_landmarks(frame, handlm,
mpHands.HAND_CONNECTIONS)
# If landmarks list is not empty
if landmarkList != []:
# store x,y coordinates of (tip of) thumb
x_1, y_1 = landmarkList[4][1], landmarkList[4][2]
# store x,y coordinates of (tip of) index finger
x_2, y_2 = landmarkList[8][1], landmarkList[8][2]
# draw circle on thumb and index finger tip
cv2.circle(frame, (x_1, y_1), 7, (0, 255, 0), cv2.FILLED)
cv2.circle(frame, (x_2, y_2), 7, (0, 255, 0), cv2.FILLED)
# draw line from tip of thumb to tip of index finger
cv2.line(frame, (x_1, y_1), (x_2, y_2), (0, 255, 0), 3)
# calculate square root of the sum of
# squares of the specified arguments.
L = hypot(x_2-x_1, y_2-y_1)
# 1-D linear interpolant to a function
# with given discrete data points
# (Hand range 15 - 220, Brightness
# range 0 - 100), evaluated at length.
b_level = np.interp(L, [15, 220], [0, 100])
# set brightness
sbc.set_brightness(int(b_level))
# Display Video and when 'q' is entered, destroy
# the window
cv2.imshow('Image', frame)
if cv2.waitKey(1) & 0xff == ord('q'):
break
第 2 步:初始化 Hands 模型
Python3
# Initializing the Model
mpHands = mp.solutions.hands
hands = mpHands.Hands(
static_image_mode=False,
model_complexity=1,
min_detection_confidence=0.75,
min_tracking_confidence=0.75,
max_num_hands=2)
Draw = mp.solutions.drawing_utils
让我们看看手模型的参数:
Hands( static_image_mode=False, model_complexity=1 min_detection_confidence=0.75, min_tracking_confidence=0.75, max_num_hands=2 )
Where:
- static_image_mode: It is used to specify whether the input image must be static images or as a video stream. The default value is False.
- model_complexity: Complexity of the hand landmark model: 0 or 1. Landmark accuracy, as well as inference latency, generally go up with the model complexity. Default to 1.
- min_detection_confidence: It is used to specify the minimum confidence value with which the detection from the person-detection model needs to be considered as successful. Can specify a value in [0.0,1.0]. The default value is 0.5.
- min_tracking_confidence: It is used to specify the minimum confidence value with which the detection from the landmark-tracking model must be considered as successful. Can specify a value in [0.0,1.0]. The default value is 0.5.
- max_num_hands: Maximum number of hands to detect. Default it is 2.
步骤 3:处理图像并根据拇指和食指尖之间的距离应用亮度
使用 OpenCV 从相机连续捕获帧并将 BGR 图像转换为 RGB 图像,并使用初始化的手模型进行预测。模型所做的预测保存在 results 变量中,我们可以使用 results.multi_hand_landmarks 从中访问地标,如果帧中存在手,则检测手部地标,然后计算拇指尖和食指尖之间的距离。用亮度范围映射拇指尖和食指尖的距离,即根据它们之间的距离,系统的亮度会改变。
Python3
# Start capturing video from webcam
cap = cv2.VideoCapture(0)
while True:
# Read video frame by frame
_,frame = cap.read()
#Flip image
frame=cv2.flip(frame,1)
# Convert BGR image to RGB image
frameRGB = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
# Process the RGB image
Process = hands.process(frameRGB)
landmarkList = []
# if hands are present in image(frame)
if Process.multi_hand_landmarks:
# detect handmarks
for handlm in Process.multi_hand_landmarks:
for _id,landmarks in enumerate(handlm.landmark):
# store height and width of image
height,width,color_channels = frame.shape
# calculate and append x, y coordinates
# of handmarks from image(frame) to lmList
x,y = int(landmarks.x*width),int(landmarks.y*height)
landmarkList.append([_id,x,y])
# draw Landmarks
Draw.draw_landmarks(frame,handlm,mpHands.HAND_CONNECTIONS)
# If landmarks list is not empty
if landmarkList != []:
# store x,y coordinates of (tip of) thumb
x_1,y_1 = landmarkList[4][1],landmarkList[4][2]
# store x,y coordinates of (tip of) index finger
x_2,y_2 = landmarkList[8][1],landmarkList[8][2]
# draw circle on thumb and index finger tip
cv2.circle(frame,(x_1,y_1),7,(0,255,0),cv2.FILLED)
cv2.circle(frame,(x_2,y_2),7,(0,255,0),cv2.FILLED)
# draw line from tip of thumb to tip of index finger
cv2.line(frame,(x_1,y_1),(x_2,y_2),(0,255,0),3)
# calculate square root of the sum
# of squares of the specified arguments.
L = hypot(x_2-x_1,y_2-y_1)
# 1-D linear interpolant to a function
# with given discrete data points
# (Hand range 15 - 220, Brightness range 0 - 100),
# evaluated at length.
b_level = np.interp(L,[15,220],[0,100])
# set brightness
sbc.set_brightness(int(b_level))
# Display Video and when 'q' is entered,
# destroy the window
cv2.imshow('Image', frame)
if cv2.waitKey(1) & 0xff == ord('q'):
break
下面是完整的实现:
Python3
# Importing Libraries
import cv2
import mediapipe as mp
from math import hypot
import screen_brightness_control as sbc
import numpy as np
# Initializing the Model
mpHands = mp.solutions.hands
hands = mpHands.Hands(
static_image_mode=False,
model_complexity=1,
min_detection_confidence=0.75,
min_tracking_confidence=0.75,
max_num_hands=2)
Draw = mp.solutions.drawing_utils
# Start capturing video from webcam
cap = cv2.VideoCapture(0)
while True:
# Read video frame by frame
_, frame = cap.read()
# Flip image
frame = cv2.flip(frame, 1)
# Convert BGR image to RGB image
frameRGB = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Process the RGB image
Process = hands.process(frameRGB)
landmarkList = []
# if hands are present in image(frame)
if Process.multi_hand_landmarks:
# detect handmarks
for handlm in Process.multi_hand_landmarks:
for _id, landmarks in enumerate(handlm.landmark):
# store height and width of image
height, width, color_channels = frame.shape
# calculate and append x, y coordinates
# of handmarks from image(frame) to lmList
x, y = int(landmarks.x*width), int(landmarks.y*height)
landmarkList.append([_id, x, y])
# draw Landmarks
Draw.draw_landmarks(frame, handlm,
mpHands.HAND_CONNECTIONS)
# If landmarks list is not empty
if landmarkList != []:
# store x,y coordinates of (tip of) thumb
x_1, y_1 = landmarkList[4][1], landmarkList[4][2]
# store x,y coordinates of (tip of) index finger
x_2, y_2 = landmarkList[8][1], landmarkList[8][2]
# draw circle on thumb and index finger tip
cv2.circle(frame, (x_1, y_1), 7, (0, 255, 0), cv2.FILLED)
cv2.circle(frame, (x_2, y_2), 7, (0, 255, 0), cv2.FILLED)
# draw line from tip of thumb to tip of index finger
cv2.line(frame, (x_1, y_1), (x_2, y_2), (0, 255, 0), 3)
# calculate square root of the sum of
# squares of the specified arguments.
L = hypot(x_2-x_1, y_2-y_1)
# 1-D linear interpolant to a function
# with given discrete data points
# (Hand range 15 - 220, Brightness
# range 0 - 100), evaluated at length.
b_level = np.interp(L, [15, 220], [0, 100])
# set brightness
sbc.set_brightness(int(b_level))
# Display Video and when 'q' is entered, destroy
# the window
cv2.imshow('Image', frame)
if cv2.waitKey(1) & 0xff == ord('q'):
break
输出: