杰瑞科技汇

Python如何绘制关键点?

Of course! Drawing keypoints on an image is a fundamental task in computer vision, especially for tasks like pose estimation, object detection, and facial recognition.

Python如何绘制关键点?-图1
(图片来源网络,侵删)

The most common and powerful library for this is OpenCV. I'll guide you through several methods, from the simplest to more advanced customizations.

Prerequisites

You need to have OpenCV installed. If you don't, you can install it using pip:

pip install opencv-python

Method 1: The Basics with cv2.circle and cv2.line

This is the most fundamental approach. You manually draw circles for each keypoint and lines to connect them. This is great for understanding the underlying process.

Scenario: Detecting a face with 68 landmarks

We'll use a pre-trained face detector and landmark predictor from the DLIB library, which works perfectly with OpenCV.

Python如何绘制关键点?-图2
(图片来源网络,侵删)

Step 1: Install DLIB

pip install dlib

Step 2: Get the pre-trained models You need two files:

  1. Face Detector: shape_predictor_68_face_landmarks.dat (You can find it in the DLIB model zoo or by searching online).
  2. Face Detector: mmod_human_face_detector.dat (A more modern, optional face detector).

After downloading them, place them in the same directory as your Python script for simplicity.

Step 3: The Python Code

Python如何绘制关键点?-图3
(图片来源网络,侵删)

This script will:

  1. Load an image.
  2. Detect faces and their 68 keypoints.
  3. Draw a circle for each keypoint.
  4. Draw lines connecting the keypoints to form the facial structure.
import cv2
import dlib
# --- 1. Load the image and models ---
image_path = 'your_face_image.jpg' # <-- Replace with your image path
predictor_path = 'shape_predictor_68_face_landmarks.dat' # <-- Replace with your model path
if not cv2.haveImageReader(image_path) or not predictor_path:
    print("Error: Image or predictor model not found.")
    exit()
image = cv2.imread(image_path)
if image is None:
    print(f"Error: Could not read image from {image_path}")
    exit()
# Initialize dlib's face detector and landmark predictor
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predictor_path)
# --- 2. Detect faces and find keypoints ---
# Convert the image to grayscale for face detection
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Detect faces in the grayscale image
faces = detector(gray)
# --- 3. Define the connections for the facial landmarks ---
# This is a list of tuples, where each tuple contains two landmark indices to connect.
# You can find the full index map online for the 68-point model.
CONNECTIONS = [
    (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (13, 14), (14, 15), (15, 16),
    (17, 18), (18, 19), (19, 20), (20, 21),
    (22, 23), (23, 24), (24, 25), (25, 26),
    (27, 28), (28, 29), (29, 30), (31, 32), (32, 33), (33, 34), (34, 35),
    (36, 37), (37, 38), (38, 39), (39, 40), (40, 41), (41, 36), (36, 42), (42, 43), (43, 44), (44, 45), (45, 46), (46, 47), (47, 36),
    (31, 48), (48, 49), (49, 50), (50, 51), (51, 52), (52, 53), (53, 54), (54, 55), (55, 56), (56, 57), (57, 58), (58, 31),
    (9, 59), (59, 60), (60, 61), (61, 62), (62, 63), (63, 64), (64, 65), (65, 66), (66, 67), (67, 59)
]
# --- 4. Loop over each detected face and draw keypoints ---
for face in faces:
    # Get the facial landmarks
    landmarks = predictor(gray, face)
    # Draw circles for each keypoint
    for i in range(68):
        # Get the (x, y) coordinates of the landmark
        x = landmarks.part(i).x
        y = landmarks.part(i).y
        # Draw a small green circle
        cv2.circle(image, (x, y), 2, (0, 255, 0), -1) # -1 means filled circle
    # Draw lines to connect the keypoints
    for connection in CONNECTIONS:
        start_point = (landmarks.part(connection[0]).x, landmarks.part(connection[0]).y)
        end_point = (landmarks.part(connection[1]).x, landmarks.part(connection[1]).y)
        cv2.line(image, start_point, end_point, (0, 0, 255), 1) # Red line, thickness 1
# --- 5. Display the result ---
cv2.imshow('Keypoints', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Method 2: The Easiest Way with cv2.drawKeypoints

OpenCV has a built-in function specifically for drawing keypoints, which is much simpler. It's designed to work with keypoint objects from the cv2.KeyPoint class, which is often generated by feature detectors like SIFT, SURF, ORB, etc.

This method is less flexible for custom connections but is incredibly concise for simple visualization.

import cv2
import numpy as np
# Create a blank image
image = np.zeros((500, 500, 3), dtype=np.uint8)
# Create a list of (x, y) coordinates for keypoints
# These could be from any algorithm, not just OpenCV's
keypoints_coords = [
    (100, 100), (150, 120), (200, 100), (250, 130), (300, 100),
    (120, 200), (180, 220), (240, 210), (280, 230),
    (150, 300), (200, 320), (250, 310)
]
# Convert coordinates to a list of cv2.KeyPoint objects
# The 'size' parameter is the diameter of the keypoint circle.
keypoints = [cv2.KeyPoint(coord[0], coord[1], size=10) for coord in keypoints_coords]
# Draw the keypoints using the built-in function
# -1 means random color. You can also pass a specific color tuple like (0, 255, 0)
output_image = cv2.drawKeypoints(image, keypoints, outImage=None, color=(0, 255, 255), flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# The 'DRAW_RICH_KEYES' flag adds a circle and orientation if available.
# Display the image
cv2.imshow('Keypoints with cv2.drawKeypoints', output_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Method 3: Advanced Customization with Matplotlib

For more control over colors, styles, and adding labels, you can use Matplotlib. This is ideal for generating publication-quality figures or interactive visualizations.

import cv2
import matplotlib.pyplot as plt
import numpy as np
# Load an image
image_path = 'your_face_image.jpg'
image = cv2.imread(image_path)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # Convert to RGB for Matplotlib
# Let's use the same DLIB setup as in Method 1 to get keypoints
import dlib
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = detector(gray)
if not faces:
    print("No faces detected.")
else:
    # Get keypoints for the first detected face
    landmarks = predictor(gray, faces[0])
    # Extract coordinates into two lists
    x_coords = [landmarks.part(i).x for i in range(68)]
    y_coords = [landmarks.part(i).y for i in range(68)]
    # --- Plotting with Matplotlib ---
    plt.figure(figsize=(10, 8))
    # Display the image
    plt.imshow(image_rgb)
    # Plot the keypoints as a scatter plot
    # We can use different colors for different parts of the face
    plt.scatter(x_coords, y_coords, c='lime
分享:
扫描分享到社交APP
上一篇
下一篇