Python爬虫实战构建SDPose-Wholebody训练数据集想要训练一个精准的SDPose-Wholebody模型高质量的数据集是关键。本文将手把手教你如何用Python爬虫构建专属的133关键点训练数据集。在实际开发SDPose-Wholebody模型时最大的挑战往往不是算法本身而是如何获取足够多且标注准确的数据。市面上的公开数据集虽然丰富但针对特定场景的需求我们往往需要构建自己的专用数据集。1. 理解SDPose-Wholebody的数据需求SDPose-Wholebody需要的是包含133个关键点的标注数据这比传统的17关键点人体姿态估计要复杂得多。这133个关键点包括17个身体关键点头、颈、肩、肘、腕等主要关节42个手部关键点每只手21个关键点覆盖所有手指关节68个面部关键点眼睛、鼻子、嘴巴等面部特征点6个脚部关键点每只脚3个关键点这样的标注粒度要求我们的数据集必须包含清晰可见的手部、面部和脚部细节。普通的人体图片往往无法满足这种需求我们需要专门寻找高质量的多角度人体图像。2. 爬虫策略设计与目标网站选择构建爬虫前首先要明确数据来源。基于SDPose-Wholebody的需求我推荐以下几类网站高质量图像源优先级专业摄影图库如Unsplash、Pexels健身教学视频截图舞蹈教程素材瑜伽姿势库多人互动场景图片避免使用版权受限或质量不佳的源。我选择Unsplash作为示例因为它提供高质量、多样化的免费商用图片正好满足我们的需求。3. 环境准备与依赖安装开始编写爬虫前确保安装必要的Python库pip install requests beautifulsoup4 selenium opencv-python tqdm对于需要JavaScript渲染的网站我们使用Selenium# 还需要安装浏览器驱动 pip install webdriver-manager4. 爬虫核心代码实现4.1 基础爬取功能首先实现一个基础的图片爬取类import requests from bs4 import BeautifulSoup import os import time from urllib.parse import urljoin import json class PoseImageCrawler: def __init__(self, save_dir./pose_dataset): self.save_dir save_dir self.image_count 0 self.failed_urls [] # 创建保存目录 os.makedirs(save_dir, exist_okTrue) os.makedirs(os.path.join(save_dir, images), exist_okTrue) os.makedirs(os.path.join(save_dir, metadata), exist_okTrue) def download_image(self, img_url, filename): 下载单张图片 try: response requests.get(img_url, streamTrue, timeout30) if response.status_code 200: filepath os.path.join(self.save_dir, images, filename) with open(filepath, wb) as f: for chunk in response.iter_content(1024): f.write(chunk) self.image_count 1 return True except Exception as e: print(f下载失败 {img_url}: {str(e)}) self.failed_urls.append(img_url) return False4.2 针对Unsplash的专用爬虫class UnsplashPoseCrawler(PoseImageCrawler): def __init__(self, search_terms, max_images1000): super().__init__() self.search_terms search_terms self.max_images max_images self.base_url https://unsplash.com/s/photos/ def crawl_by_search_term(self, search_term): 根据搜索词爬取图片 search_url f{self.base_url}{search_term.replace( , -)} page 1 downloaded 0 while downloaded self.max_images: try: response requests.get(f{search_url}?page{page}) soup BeautifulSoup(response.text, html.parser) # 解析图片链接 img_elements soup.find_all(img, {data-test: photo-grid-multi}) if not img_elements: break for img in img_elements: if downloaded self.max_images: break img_url img.get(src) if img_url and https://images.unsplash.com/ in img_url: # 获取高清大图 high_res_url img_url.split(?)[0] ?w1080q80 filename f{search_term}_{downloaded:04d}.jpg if self.download_image(high_res_url, filename): downloaded 1 print(f已下载 {downloaded} 张 {search_term} 图片) page 1 time.sleep(1) # 礼貌性延迟 except Exception as e: print(f爬取页面失败: {str(e)}) break4.3 高级爬取策略对于需要处理JavaScript渲染的网站使用Seleniumfrom selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from webdriver_manager.chrome import ChromeDriverManager class SeleniumCrawler(PoseImageCrawler): def __init__(self): super().__init__() self.driver webdriver.Chrome(ChromeDriverManager().install()) def crawl_dynamic_site(self, url, scroll_times10): 爬取需要JavaScript渲染的网站 self.driver.get(url) # 等待页面加载 WebDriverWait(self.driver, 10).until( EC.presence_of_element_located((By.TAG_NAME, img)) ) # 滚动加载更多内容 for _ in range(scroll_times): self.driver.execute_script(window.scrollTo(0, document.body.scrollHeight);) time.sleep(2) # 提取图片 img_elements self.driver.find_elements(By.TAG_NAME, img) for idx, img in enumerate(img_elements): img_url img.get_attribute(src) if img_url and img_url.startswith(http): filename fdynamic_site_{idx:04d}.jpg self.download_image(img_url, filename) def close(self): self.driver.quit()5. 数据清洗与筛选爬取到的原始数据需要经过严格清洗import cv2 import numpy as np from tqdm import tqdm class DataCleaner: def __init__(self, image_dir): self.image_dir image_dir def filter_by_aspect_ratio(self, min_ratio0.5, max_ratio2.0): 过滤长宽比不合适的图片 valid_images [] for img_name in os.listdir(self.image_dir): img_path os.path.join(self.image_dir, img_name) img cv2.imread(img_path) if img is not None: h, w img.shape[:2] aspect_ratio w / h if min_ratio aspect_ratio max_ratio: valid_images.append(img_name) return valid_images def remove_duplicates(self, threshold0.95): 使用感知哈希去除重复图片 from PIL import Image import imagehash hashes {} duplicates [] for img_name in tqdm(os.listdir(self.image_dir)): img_path os.path.join(self.image_dir, img_name) try: with Image.open(img_path) as img: img_hash imagehash.average_hash(img) # 检查是否已有相似哈希 for existing_hash in hashes: if img_hash - existing_hash 5: # 相似度阈值 duplicates.append(img_name) break else: hashes[img_hash] img_name except: continue return duplicates def enhance_quality(self, target_size(1024, 768)): 增强图片质量并统一尺寸 enhanced_dir os.path.join(self.image_dir, enhanced) os.makedirs(enhanced_dir, exist_okTrue) for img_name in tqdm(os.listdir(self.image_dir)): if img_name enhanced: continue img_path os.path.join(self.image_dir, img_name) img cv2.imread(img_path) if img is not None: # 调整尺寸 img_resized cv2.resize(img, target_size, interpolationcv2.INTER_LANCZOS4) # 轻度锐化 kernel np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]]) img_sharpened cv2.filter2D(img_resized, -1, kernel) # 保存增强后的图片 enhanced_path os.path.join(enhanced_dir, img_name) cv2.imwrite(enhanced_path, img_sharpened)6. 自动化标注流程虽然完整的关键点标注需要人工校验但我们可以先用预训练模型进行初步标注class AutoAnnotator: def __init__(self, model_pathNone): # 这里可以集成现有的姿态估计模型进行初步标注 pass def generate_initial_annotations(self, image_dir, output_json): 生成初步的标注文件 annotations [] for img_name in tqdm(os.listdir(image_dir)): if not img_name.lower().endswith((.png, .jpg, .jpeg)): continue img_path os.path.join(image_dir, img_name) annotation { image_name: img_name, keypoints: self.predict_keypoints(img_path), bbox: self.detect_person(img_path), image_size: self.get_image_size(img_path) } annotations.append(annotation) # 保存为COCO格式 coco_format self.convert_to_coco_format(annotations) with open(output_json, w) as f: json.dump(coco_format, f, indent2) def predict_keypoints(self, image_path): 使用预训练模型预测关键点 # 这里可以集成MMPose、OpenPose等工具 # 返回133个关键点的坐标和置信度 return []7. 构建完整的数据处理流水线将各个模块组合成完整的数据处理流程def build_pose_dataset(search_terms, total_images5000): 完整的SDPose数据集构建流程 print(开始爬取图像数据...) crawler UnsplashPoseCrawler(search_terms, max_imagestotal_images) for term in search_terms: crawler.crawl_by_search_term(term) print(f共爬取 {crawler.image_count} 张图片) print(开始数据清洗...) cleaner DataCleaner(./pose_dataset/images) # 过滤不合适的长宽比 valid_images cleaner.filter_by_aspect_ratio() print(f长宽比过滤后剩余 {len(valid_images)} 张图片) # 去除重复图片 duplicates cleaner.remove_duplicates() for dup in duplicates: os.remove(os.path.join(./pose_dataset/images, dup)) print(f去除 {len(duplicates)} 张重复图片) # 增强图片质量 cleaner.enhance_quality() print(生成初步标注...) annotator AutoAnnotator() annotator.generate_initial_annotations( ./pose_dataset/images/enhanced, ./pose_dataset/annotations/initial_annotations.json ) print(数据集构建完成) print(下一步人工校验和修正标注) # 使用示例 if __name__ __main__: search_terms [ yoga-pose, dance-move, workout-exercise, martial-arts, gymnastics, parkour, athlete-training, ballet-dance, capoeira ] build_pose_dataset(search_terms, total_images2000)8. 实际应用中的注意事项在实际构建SDPose-Wholebody数据集时有几个关键点需要特别注意数据多样性保障确保包含各种体型、年龄、肤色的人群覆盖不同的光照条件和背景环境包含各种难度级别的姿态简单站姿到复杂动作标注质量把控初步自动标注后必须进行人工校验建立标注质量标准和质量检查流程对于模糊或不明确的图片宁可舍弃也不要错误标注法律合规性确保所有图片都有合法使用权限尊重模特肖像权必要时获取授权避免使用有争议或敏感的内容从实际项目经验来看一个高质量的SDPose-Wholebody数据集通常需要2000-5000张精心标注的图像。虽然爬虫可以帮我们快速收集原始素材但后续的清洗和标注工作同样重要这部分往往需要投入相当的人力资源。记得在正式使用前一定要仔细检查数据质量差的数据比没有数据更糟糕。好的开始是成功的一半在数据准备阶段多花些功夫模型训练阶段就会顺利很多。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。