英文:
Mediapipe Display Body Landmarks Only
问题
我已经安装了Python (3.7.0)在Windows 11上使用Mediapipe (0.9.0.1)。
我已成功地让Mediapipe为图像、视频和网络摄像头流生成了关键点(用于面部和身体)。
现在,我想让Mediapipe 只 绘制身体特定的关键点(即排除面部关键点)。
我了解我可以使用OpenCV(或Czone)来实现这个目标,但我希望使用Mediapipe(即使用Mediapipe库中的draw_landmarks
函数)来实现我的目标。
我尝试的特定代码部分(但出现了错误)如下:
#初始化一个列表来存储检测到的关键点。
landmarks = []
#遍历Mediapipe检测到的关键点。
for landmark in results.pose_landmarks.landmark:
#将Mediapipe关键点添加到列表中。
landmarks.append((int(landmark.x * width), int(landmark.y * height),
(landmark.z * width)))
#为特定的关键点创建索引列表
body_landmark_indices = [11,12,13,14,15,16,23,24,25,26,27,28,29,30,31,32]
landmark_list_body = []
#创建一个仅包含所需关键点的列表
for index in body_landmark_indices:
landmark_list_body.append(landmarks[index - 1])
mp_drawing.draw_landmarks(
image=output_image,
landmark_list=landmark_list_body,
connections=mp_pose.POSE_CONNECTIONS,
landmark_drawing_spec=landmark_drawing_spec,
connection_drawing_spec=connection_drawing_spec)`
执行上述代码时,我收到错误信息`'list' object has no attribute 'pose_landmarks'`。
我已经用`landmark_list=landmark_list_body`替换了`landmark_list=landmark_list_body.pose_landmarks`,但仍然出现错误。
我现在非常疲倦并且没有更多的想法。是否有无需斗篷的英雄可以帮助?
谢谢。
<details>
<summary>英文:</summary>
I have installed Mediapipe (0.9.0.1) using Python (3.7.0) on windows 11.
I have been able to successfully get Mediapipe to generate landmarks (for face and body); for an image, video, and webcam stream.
I would like to now get Mediapipe to **only** draw body specific landmarks (i.e. exclude facial landmarks).
I understand that I may use OpenCV (or Czone) to accomplish this goal, however, I am looking to achieve my objective using Mediapipe (i.e. using the `draw_landmarks` function in the MediaPipe library).
The specific bit of code I am trying (but with errors) is the following:
#Initialize a list to store the detected landmarks.
landmarks = []
# Iterate over the Mediapipe detected landmarks.
for landmark in results.pose_landmarks.landmark:
# Append the Mediapipe landmark into the list.
landmarks.append((int(landmark.x * width), int(landmark.y * height),
(landmark.z * width)))
#create index list for specific landmarks
body_landmark_indices = [11,12,13,14,15,16,23,24,25,26,27,28,29,30,31,32]
landmark_list_body = []
#Create a list which only has the required landmarks
for index in body_landmark_indices:
landmark_list_body.append(landmarks[index - 1])
mp_drawing.draw_landmarks(
image=output_image,
landmark_list=landmark_list_body.pose_landmarks,
connections=mp_pose.POSE_CONNECTIONS,
landmark_drawing_spec=landmark_drawing_spec,
connection_drawing_spec=connection_drawing_spec)`
Executing the above I get the error `'list' object has no attribute 'pose_landmarks'
I have replaced `landmark_list=landmark_list_body.pose_landmarks,` with `landmark_list=landmark_list_body` but with errors.
I am now very tiered and out of ideas. Is there a capeless hero out there?
Thanks.
</details>
# 答案1
**得分**: 5
你可以尝试以下方法:
```python
import cv2
import mediapipe as mp
import numpy as np
from mediapipe.python.solutions.pose import PoseLandmark
from mediapipe.python.solutions.drawing_utils import DrawingSpec
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_pose = mp.solutions.pose
custom_style = mp_drawing_styles.get_default_pose_landmarks_style()
custom_connections = list(mp_pose.POSE_CONNECTIONS)
# 要从绘图中排除的关键点列表
excluded_landmarks = [
PoseLandmark.LEFT_EYE,
PoseLandmark.RIGHT_EYE,
PoseLandmark.LEFT_EYE_INNER,
PoseLandmark.RIGHT_EYE_INNER,
PoseLandmark.LEFT_EAR,
PoseLandmark.RIGHT_EAR,
PoseLandmark.LEFT_EYE_OUTER,
PoseLandmark.RIGHT_EYE_OUTER,
PoseLandmark.NOSE,
PoseLandmark.MOUTH_LEFT,
PoseLandmark.MOUTH_RIGHT ]
for landmark in excluded_landmarks:
# 改变被排除关键点的绘制方式
custom_style[landmark] = DrawingSpec(color=(255,255,0), thickness=None)
# 删除包含这些关键点的所有连接
custom_connections = [connection_tuple for connection_tuple in custom_connections
if landmark.value not in connection_tuple]
IMAGE_FILES = ["test.jpg"]
BG_COLOR = (192, 192, 192)
with mp_pose.Pose(
static_image_mode=True,
model_complexity=2,
enable_segmentation=True,
min_detection_confidence=0.5) as pose:
for idx, file in enumerate(IMAGE_FILES):
image = cv2.imread(file)
image_height, image_width, _ = image.shape
results = pose.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
annotated_image = image.copy()
mp_drawing.draw_landmarks(
annotated_image,
results.pose_landmarks,
connections = custom_connections, # 传递修改后的连接列表
landmark_drawing_spec=custom_style) # 和绘制样式
cv2.imshow('landmarks', annotated_image)
cv2.waitKey(0)
它修改了DrawingSpec
和POSE_CONNECTIONS
来“隐藏”一部分关键点。但是,由于在Mediapipe中实现draw_landmarks()
函数的方式,还需要在drawing_utils.py
中添加一个条件(位于site-packages/mediapipe/python/solutions
):
if drawing_spec.thickness == None: continue
在第188行之前添加这行代码(查看MediaPipe GitHub 仓库,# White circle border
)。结果应该是这样的:
...
drawing_spec = landmark_drawing_spec[idx] if isinstance(
landmark_drawing_spec, Mapping) else landmark_drawing_spec
if drawing_spec.thickness == None: continue
# White circle border
circle_border_radius = max(drawing_spec.circle_radius + 1,
int(drawing_spec.circle_radius * 1.2))
...
这个改变是为了完全消除绘制在关键点周围的白色边框,而不考虑它们的绘制规范。
希望对你有所帮助。
英文:
You can try the following approach:
import cv2
import mediapipe as mp
import numpy as np
from mediapipe.python.solutions.pose import PoseLandmark
from mediapipe.python.solutions.drawing_utils import DrawingSpec
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_pose = mp.solutions.pose
custom_style = mp_drawing_styles.get_default_pose_landmarks_style()
custom_connections = list(mp_pose.POSE_CONNECTIONS)
# list of landmarks to exclude from the drawing
excluded_landmarks = [
PoseLandmark.LEFT_EYE,
PoseLandmark.RIGHT_EYE,
PoseLandmark.LEFT_EYE_INNER,
PoseLandmark.RIGHT_EYE_INNER,
PoseLandmark.LEFT_EAR,
PoseLandmark.RIGHT_EAR,
PoseLandmark.LEFT_EYE_OUTER,
PoseLandmark.RIGHT_EYE_OUTER,
PoseLandmark.NOSE,
PoseLandmark.MOUTH_LEFT,
PoseLandmark.MOUTH_RIGHT ]
for landmark in excluded_landmarks:
# we change the way the excluded landmarks are drawn
custom_style[landmark] = DrawingSpec(color=(255,255,0), thickness=None)
# we remove all connections which contain these landmarks
custom_connections = [connection_tuple for connection_tuple in custom_connections
if landmark.value not in connection_tuple]
IMAGE_FILES = ["test.jpg"]
BG_COLOR = (192, 192, 192)
with mp_pose.Pose(
static_image_mode=True,
model_complexity=2,
enable_segmentation=True,
min_detection_confidence=0.5) as pose:
for idx, file in enumerate(IMAGE_FILES):
image = cv2.imread(file)
image_height, image_width, _ = image.shape
results = pose.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
annotated_image = image.copy()
mp_drawing.draw_landmarks(
annotated_image,
results.pose_landmarks,
connections = custom_connections, # passing the modified connections list
landmark_drawing_spec=custom_style) # and drawing style
cv2.imshow('landmarks', annotated_image)
cv2.waitKey(0)
It modifies the DrawingSpec
and POSE_CONNECTIONS
to "hide" a subset of landmarks.
However, due to the way the draw_landmarks()
function is implemented in Mediapipe, it is also required to add a condition in drawing_utils.py
(located in site-packages/mediapipe/python/solutions
):
if drawing_spec.thickness == None: continue
Add it before Line 188 (see MediaPipe GitHub repo, # White circle border
). The result should look like this:
...
drawing_spec = landmark_drawing_spec[idx] if isinstance(
landmark_drawing_spec, Mapping) else landmark_drawing_spec
if drawing_spec.thickness == None: continue
# White circle border
circle_border_radius = max(drawing_spec.circle_radius + 1,
int(drawing_spec.circle_radius * 1.2))
...
This change is required in order to completely eliminate the white border that is drawn around landmarks regardless of their drawing specification.
Hope it helps.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论