Parsing and Visualizing COCO Keypoint Detection Annotations with Python
This tutorial explains how to explore the COCO keypoint detection annotation files, describes their JSON structure and fields, and provides step‑by‑step Python code using json, Pillow, and matplotlib to load images, extract keypoints, and draw both points and skeletal connections for visual analysis.
The article introduces the COCO dataset's keypoint detection annotation files, emphasizing the importance of understanding dataset structure before working with code or projects. It guides readers to download the COCO 2017 dataset, locate the train2017 , val2017 , and annotations directories, and identify the two JSON files containing keypoint annotations for training and validation sets.
It then breaks down the main sections of the annotation JSON: info (basic description), licenses (usage restrictions), images (metadata such as file name, width, height), annotations (the core data with fields like keypoints , num_keypoints , area , iscrowd , image_id , category_id , and id ), and categories (definition of the "person" category and its keypoint list). The keypoints array stores 17 body joints, each represented by three values (x, y, visibility), totaling 51 numbers per instance.
To make the data concrete, the article provides a complete Python script that reads the JSON file, selects a specific image by its image_id , loads the corresponding image with Pillow, and visualizes the keypoints using matplotlib. The required libraries are imported as follows:
import json
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, ConnectionPatch
from PIL import ImagePaths to the annotation file and image folder are set, and the target image_id (e.g., 481386) is specified:
# COCO annotation file path
annotations_file_path = r'D://数据集//coco2017//annotations//person_keypoints_val2017.json'
# Image folder path
images_folder_path = r'D://数据集//coco2017//val2017//'
# Specify image ID
image_id = 481386 # replace with desired IDThe script loads the JSON, extracts the image metadata and all annotations for that image, and displays the image:
# Load COCO annotation file
with open(annotations_file_path, 'r') as f:
coco_data = json.load(f)
# Find image info
image_info = next(item for item in coco_data['images'] if item['id'] == image_id)
# Find annotations for the image
annotations = [ann for ann in coco_data['annotations'] if ann['image_id'] == image_id]
# Show image
image_path = images_folder_path + image_info['file_name']
image = Image.open(image_path)
plt.imshow(image)
plt.axis('off')Keypoints are plotted only when their visibility flag is greater than zero:
# Plot keypoints
for ann in annotations:
keypoints = ann['keypoints']
for i in range(0, len(keypoints), 3):
x, y, v = keypoints[i], keypoints[i+1], keypoints[i+2]
if v > 0: # draw visible keypoints
plt.scatter(x, y, color='r', s=10)The skeletal connections are defined by a list of joint pairs (using 1‑based indices) and drawn with ConnectionPatch objects after converting to 0‑based indices:
# Define skeleton connections (1‑based indices)
skeleton = [[16,14],[14,12],[17,15],[15,13],[12,13],[6,12],[7,13],[6,7],[6,8],[7,9],[8,10],[9,11],[2,3],[1,2],[1,3],[2,4],[3,5],[4,6],[5,7]]
for connection in skeleton:
start_point = (annotations[0]['keypoints'][3*(connection[0]-1)],
annotations[0]['keypoints'][3*(connection[0]-1)+1])
end_point = (annotations[0]['keypoints'][3*(connection[1]-1)],
annotations[0]['keypoints'][3*(connection[1]-1)+1])
line = ConnectionPatch(start_point, end_point, "data", "data", color='r', linewidth=2)
plt.gca().add_patch(line)Finally, the script calls plt.show() to render the image with overlaid keypoints and skeleton. The article concludes with a summary encouraging readers to experiment with the code, debug any issues, and ask questions in the comments.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.