ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

男女性别检测数据集:VOC+YOLO双格式9769张图开箱即训

男女性别检测数据集:VOC+YOLO双格式9769张图开箱即训 简介这份数据集面向计算机视觉与目标检测方向的开发者与学生提供男女性别检测所需的图像与标注文件可直接用于训练YOLO、Faster R-CNN等模型。数据集合计9769张jpg图片并配套Pascal VOC格式xml与YOLO格式txt标注共标注9799个矩形框覆盖Female、Male两个类别其中女性框5491个、男性框4308个。压缩包内共2000个文件以xml标注文件为主并含txt说明文件整体大小104.49MB便于下载与解压。数据集使用labelImg工具按统一规则绘制矩形框类别划分清晰可满足性别识别、人员属性分析等场景的模型训练与验证需求。已有348人学习/下载适合需要高质量标注样本的算法工程师和学生使用。1. 男女性别检测数据集VOCYOLO双格式9769张图开箱即训做目标检测的都知道真正耗时间的往往不是训练而是数据准备。我给不少人调过模型发现最常卡住的地方就是标注格式网上找的公开数据集要么只有VOC格式要么只给YOLO的txt两边转换还要自己写脚本转换完之后还得验一遍坐标对不对。这份男女性别检测数据集一共9769张jpg图片VOC和YOLO两种格式的标注文件全部配齐每张图对应一个xml和一个txt2个类别共9799个框拿过来把路径一配就能直接开工训练省掉的是最脏最累的格式转换环节。适合正在做行人属性识别、安防监控、客流统计分析以及想拿YOLO系列跑通自定义数据集流程的人。2. 数据集内部结构三个同名文件与标注坐标的对应关系2.1 一张图三个文件命名一一对应解压后你会看到大量类似firc_gender_8473.jpg、firc_gender_8473.xml、firc_gender_8473.txt这样的三件套。这里的关键是jpg、xml、txt 三个文件的主文件名完全一致只是扩展名不同。这对后续做数据划分和脚本处理非常友好按主文件名做一次遍历就能完成所有配对工作。从文件名规律看数据集统一使用firc_gender_前缀加数字编号没有中文和特殊字符这本身就避免了训练时因路径问题导致的读取失败。文件结构如下表所示文件类型数量内容说明.jpg9769原始图片尺寸不一模型训练时的实际输入.xml9769Pascal VOC格式标注包含目标类别与像素坐标.txt9769YOLO格式标注类别ID归一化中心坐标与宽高三个文件数量完全对齐说明这份数据在制作时是用标注工具一次导出完成的没有出现中途丢标注的情况。拿到手后第一件事就是用命令统计一下三类文件数量是否都是9769这一步不能跳过后面避坑章节会细说为什么。2.2 VOC标注里的坐标是绝对像素值用任意文本编辑器打开一个xml文件典型结构如下annotation folderfirc_gender/folder filenamefirc_gender_8473.jpg/filename pathC:/dataset/firc_gender_8473.jpg/path source databaseUnknown/database /source size width640/width height480/height depth3/depth /size segmented0/segmented object nameFemale/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin120/xmin ymin80/ymin xmax380/xmax ymax460/ymax /bndbox /object /annotationVOC格式的坐标是像素绝对值也就是xmin/ymin/xmax/ymax直接对应图片上的像素位置左上角为原点。每个object节点代表一个标注框name是类别名这里是Female或Male。由于总框数9799大于图片数9769说明有一部分图里同时标了多个人object节点会重复出现。还有一个值得留意的细节path里写的是标注工具当时的绝对路径通常是C:/dataset/开头。这个路径在你自己机器上是不存在的但训练时会读取的其实是你自己配的路径xml里这个字段不影响使用不用改。2.3 YOLO标签的归一化计算逻辑YOLO格式的txt每一行对应一个框格式是类别ID x_center y_center width height五个值全部是相对图片宽高的归一化小数。以2.2里那个框为例如果图片是640x480对应的txt内容是0 0.390625 0.562500 0.406250 0.791667这个计算逻辑很重要后面校验标签时要用x_center ((xmin xmax) / 2) / width # 中心点x坐标除以图片宽度 y_center ((ymin ymax) / 2) / height # 中心点y坐标除以图片高度 box_w (xmax - xmin) / width # 框宽除以图片宽度 box_h (ymax - ymin) / height # 框高除以图片高度在yolov8、yolov5这些框架里txt文件放在labels目录下图片放在images目录下必须保持主文件名一致否则训练时找不到对应的标注。txt文件的类别ID是数字Female对应0Male对应1这个顺序在写数据集配置yaml时要前后对齐错一位整个训练就废了。3. 解压校验与目录组织从7z压缩包到可训练的YOLO工程3.1 7z压缩包的解压Linux和Windows两种方式拿到的是.7z压缩包。Windows上安装7-Zip后右键选择“解压到当前文件夹”即可如果解压中间弹出CRC报错说明文件在传输过程中损坏了不要直接忽略继续用后面训练时会出现图片打不开或标签读不了的问题。Linux服务器上我一般这样操作# 先看7z命令是否可用 which 7z || sudo apt install p7zip-full # 解压到指定目录-o后面不要留空格 7z x 男女性别检测数据集VOCYOLO格式9769张2类别.7z -o./gender_dataset解压参数里x表示解压并保留目录结构-o指定输出目录。注意-o和目录路径之间不能有空格写成-o ./gender_dataset中间有空格会导致识别路径异常这是7-Zip命令行常见的坑。解压完成后进入目录先做一个数量核对cd gender_dataset echo jpg数量: $(find . -name *.jpg | wc -l) echo xml数量: $(find . -name *.xml | wc -l) echo txt数量: $(find . -name *.txt | wc -l)三个数字应该都是9769。如果txt数量少于xml说明部分图片的YOLO标注在打包时遗漏了如果jpg少了说明有图片损坏或在传输中被丢弃。这里宁可多花十分钟查清楚也不要带着残缺数据进训练流程否则后面排查问题时很难定位是数据问题还是模型问题。3.2 目录结构重组按YOLO约定组织images和labels下载包解压后默认是jpg、xml、txt混在一起的平铺结构需要重组成yolov8约定的目录格式。yolov8训练时默认会读取images目录下的图片并从兄弟目录labels下找同名的txt。我习惯先在项目根目录建一套干净的目录树mkdir -p gender_dataset/{images/{train,val},labels/{train,val}}标准做法是把数据集拆成训练集和验证集两部分。拆分的原则是以图片文件为准xml和txt跟着图片走不能把同一张图的标注拆到不同集合里。我写了下面这个划分脚本控制验证集比例import os import random from shutil import copy2 # 配置路径改成你自己的实际路径 IMG_DIR gender_dataset/all_images # 解压后的jpg所在目录 XML_DIR gender_dataset/all_xml # 解压后的xml所在目录 TXT_DIR gender_dataset/all_txt # 解压后的txt所在目录 IMG_DST gender_dataset/images # 目标images根目录 LBL_DST gender_dataset/labels # 目标labels根目录 val_ratio 0.1 # 验证集比例 random.seed(42) # 固定随机种子保证每次划分结果一致 all_imgs [f for f in os.listdir(IMG_DIR) if f.endswith(.jpg)] random.shuffle(all_imgs) val_count int(len(all_imgs) * val_ratio) val_set set(all_imgs[:val_count]) train_set set(all_imgs[val_count:]) for split, imgs in [(train, train_set), (val, val_set)]: for img_name in sorted(imgs): base os.path.splitext(img_name)[0] src_img os.path.join(IMG_DIR, img_name) src_xml os.path.join(XML_DIR, base .xml) src_txt os.path.join(TXT_DIR, base .txt) # 三个文件必须同时存在才拷贝缺失就打印警告 if not (os.path.exists(src_img) and os.path.exists(src_xml) and os.path.exists(src_txt)): print(f[WARN] 文件缺失: {base}) continue copy2(src_img, os.path.join(IMG_DST, split)) copy2(src_xml, os.path.join(XML_DIR, split)) # xml放到xml训练目录留档 copy2(src_txt, os.path.join(LBL_DST, split)) print(ftrain images: {len(train_set)}) print(fval images: {len(val_set)})脚本逻辑分三步先读取全部图片名按比例随机切分为训练集和验证集然后遍历每个集合里的图片名用主文件名去拼接xml和txt的路径最后三个文件同时存在才执行拷贝有一个缺失就跳过并打印警告。random.seed(42)这一步很关键不固定种子的话每次跑出来的划分都不一样以后复现实验就困难了。xml文件在这个组织结构里已经不再被yolov8使用但建议保留一份带xml的完整副本万一后续要转成COCO格式或者做数据筛选时还能用得上。3.3 整理后的目录结构验证完成划分后最终的项目结构应该长这样gender_dataset/ ├── images/ │ ├── train/ # 8793张jpg │ └── val/ # 976张jpg ├── labels/ │ ├── train/ # 8793个txt │ └── val/ # 976个txt ├── all_xml/ # 原始xml备份留档 └── train_val_script.py # 划分脚本这里的数字是根据10%验证集比例算出来的实际以你自己跑出来的为准。验证一下labels里train和val的txt文件主文件名集合必须与images里对应目录下的jpg主文件名集合完全一致。cd gender_dataset # 对比train集合输出差异文件列表 diff (ls images/train | sed s/.jpg// | sort) (ls labels/train | sed s/.txt// | sort) diff (ls images/val | sed s/.jpg// | sort) (ls labels/val | sed s/.txt// | sort)如果diff命令没有输出说明文件名完全对齐可以进入下一步。这一步我每次都会坚持做一遍因为在不同的文件系统之间拷贝时偶尔会出现文件名截断或大小写被改的情况这种隐蔽问题用眼睛看不出来跑一下diff就现原形了。4. 训练前数据体检类别分布、边界框质量与yaml配置4.1 用脚本统计类别框数与分布在拿到一份数据集后我习惯先做一次彻底的“体检”而不是直接开训。体检查两个核心指标一是各类别的框数是否符合预期二是边界框坐标是否有异常。这份数据集的摘要信息里已经写明Female框数5491Male框数4308总框数9799。我用下面的脚本独立验一遍确认数据没有在传输中变质import os import xml.etree.ElementTree as ET XML_DIR gender_dataset/all_xml counter {} # 类别-框数 total_boxes 0 # 总框数 image_with_box 0 # 有标注的图片数 for xml_name in os.listdir(XML_DIR): if not xml_name.endswith(.xml): continue tree ET.parse(os.path.join(XML_DIR, xml_name)) root tree.getroot() objects root.findall(object) if len(objects) 0: image_with_box 1 for obj in objects: name obj.find(name).text.strip() # 注意strip掉空格 counter[name] counter.get(name, 0) 1 total_boxes 1 print(类别分布:, counter) print(总框数:, total_boxes) print(有标注的图片数:, image_with_box)跑完应该输出{Female: 5491, Male: 4308}。如果数字对不上优先检查是不是解压时丢了xml。这里有一个隐蔽问题obj.find(name).text.strip()里的.strip()不能省因为有些标注工具导出时会在类别名里带上换行符或空格导致Female 和Female被当成两个类别。万一出现这种情况在yaml里写类别名时也会对不上训练时会出现“标签索引越界”的报错。数据集中图片数9769但总框数9799说明有部分图片是多人标注这一点在脚本输出里image_with_box会小于9769属于正常现象。4.2 边界框坐标越界与尺寸异常检查标签坐标越界是数据体检里最值得警惕的问题。VOC格式要求xmin xmax、ymin ymax且四个值都必须在图片尺寸范围内。我一般再跑一段脚本检查这两类异常import os import xml.etree.ElementTree as ET XML_DIR gender_dataset/all_xml issue_count 0 for xml_name in os.listdir(XML_DIR): if not xml_name.endswith(.xml): continue tree ET.parse(os.path.join(XML_DIR, xml_name)) root tree.getroot() size root.find(size) width int(size.find(width).text) height int(size.find(height).text) for obj in root.findall(object): box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 四种异常情况越界、坐标反向、宽高为零 if xmin 0 or ymin 0 or xmax width or ymax height: print(f[越界] {xml_name}: ({xmin},{ymin},{xmax},{ymax}) vs 图片{width}x{height}) issue_count 1 elif xmin xmax or ymin ymax: print(f[反向] {xml_name}: xmin{xmin}, xmax{xmax}) issue_count 1 elif xmin xmax or ymin ymax: print(f[零宽高] {xml_name}: 宽度或高度为0) issue_count 1 print(f发现异常标注文件数: {issue_count})检查的内容有三类坐标是否超出图片边界、坐标是否反向、宽高是否为0。越界的标注会让模型在计算损失时出现坐标回归的不稳定因为目标框有一部分落在图片外部特征图上的对应区域可能没有有效的语义信息。零宽高的框更是直接废框参与训练只会干扰损失函数的收敛。正常情况下这份数据集应该输出0条异常记录因为摘要里明确说了“准确且合理标注”。如果真的查到有越界说明文件在传输中损坏建议重新下载而不是手动改坐标。4.3 配置yolov8的data.yaml文件目录组织好、数据也检查无误后写数据集配置文件。yolov8用yaml文件描述训练数据的信息包括路径、类别数和类别名。这里有一处必须严格对齐的顺序问题yaml里的names列表顺序必须和txt文件里标注的类别ID一致。本数据集txt中的0对应Female1对应Male所以配置写成# gender.yaml path: /home/user/gender_dataset # 数据集根目录改成你自己的绝对路径 train: images/train # 训练图片相对路径 val: images/val # 验证图片相对路径 nc: 2 # 类别数量固定为2 names: [Female, Male] # 顺序不能颠倒否则类别错乱yaml文件里的path建议写绝对路径不要用相对路径。用相对路径时yolov8会根据当前命令行所在的目录去拼接一旦你换了一个终端目录启动训练路径就失效了报错信息是“AssertionError: train dataset not found”排查起来很绕。nc和names的长度必须匹配这里都是2。如果你用脚本给txt文件重新编排过类别ID记得把这里的顺序也同步改掉。5. 避坑排查解压报错、标签错位与训练Loss不降的五个现场5.1 解压报“CRC错误”或“头部错误”但文件还在现象用7-Zip解压到一半弹出“CRC错误”或“Cannot open file as archive”但目录里已经解压出部分文件。原因压缩包在下载或拷贝过程中损坏或者WinRAR/低版本7-Zip对7z格式的兼容性问题。最常见的场景是用迅雷或浏览器断点续传下载进度显示100%但文件校验没通过。解决删除整个解压目录重新解压不要勾选“保留损坏文件”选项。如果是从网盘下载的重新下载一次再对比文件大小命令行解压时可以用7z t 文件名.7z先做完整性测试这条命令会单独校验压缩包的CRC不实际解压。从那以后我拿到任何7z包第一件事永远是跑一遍7z t这个习惯帮我避开了至少三次带着半截数据训练的事故。5.2 txt和xml的文件名有差异数量对不上现象数xml是9769个数txt只有9760个少了9个或者两者的主文件名集合不一致。原因数据在打包时个别txt写入失败或者在拷贝过程中因为文件名过长、特殊字符等问题被系统拒绝。解决用3.3节里的diff命令逐一比对。找到缺失的txt后如果对应xml还在就根据xml重新生成txtimport os import xml.etree.ElementTree as ET XML_DIR gender_dataset/all_xml TXT_DIR gender_dataset/all_txt def xml_to_yolo(xml_path): tree ET.parse(xml_path) root tree.getroot() width int(root.find(size/width).text) height int(root.find(size/height).text) lines [] for obj in root.findall(object): name obj.find(name).text.strip() cls_id 0 if name Female else 1 box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) x_center ((xmin xmax) / 2) / width y_center ((ymin ymax) / 2) / height w (xmax - xmin) / width h (ymax - ymin) / height lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) return lines #if 缺失的txt对应的xml存在就用下面的代码补生成 #xml_file gender_dataset/all_xml/firc_gender_8473.xml #txt_file gender_dataset/all_txt/firc_gender_8473.txt #with open(txt_file, w) as f: # f.write(\n.join(xml_to_yolo(xml_file)))这段脚本把xml里的VOC坐标读出来除以图片宽高完成归一化然后按cls_id x_center y_center w h的格式写入txt。生成之后务必用4.2节的越界检查脚本再跑一遍因为一旦坐标转换逻辑写错生成的txt可能全是无效值。5.3 训练时loss降不下去或者mAP一直是0现象yolov8训练了十几个epochbox_loss和cls_loss都不怎么下降或者训练完跑验证集mAP0。原因最常见的是train和val划分时存在数据泄漏——同一张图片既进了训练集又进了验证集模型等于“背过答案”验证集上mAP虚高或者测试集上泛化很差。另一种情况是txt里的类别ID超出了nc范围比如txt里写了2但yaml里nc: 2索引越界导致损失计算异常。解决先把数据划分脚本里的random.seed()固定确保每次划分出来的集合边界一致然后检查生成的txt里最大类别ID是否小于nc# 找出包含非法类别ID的txt合法值是0和1 grep -rE ^[2-9] gender_dataset/labels/ | head -20如果确实找到类别ID为2或更大的行说明这个txt对应的xml里name字段有意外值。另一种情况是模型自己的问题yolov8的损失函数由三部分组成box_loss边界框回归损失、cls_loss分类损失、dfl_loss分布焦点损失。如果box_loss降了但cls_loss纹丝不动优先怀疑类别标签错位如果三个loss都在震荡先调低学习率再看。5.4 图像路径含中文或空格导致训练中断现象训练启动时报FileNotFoundError或者图片无法解码但文件确实存在。原因数据集目录在带中文或空格的路径下比如/home/user/男女性别检测数据集/OpenCV在读取中文路径时偶尔会失败。这个问题在Linux上更常见和系统locale设置有关。解决把整个数据集移到纯英文路径下比如/home/user/gender_dataset。如果你必须保留中文路径可以在代码里对路径先编码再解码但最省事的做法还是目录全英文。数据集的图片文件名本身已经是纯英文数字组合所以只要外层目录不引入中文一般不会触发这个问题。5.5 用labelImg打开txt发现坐标全是0现象在labelImg里加载某张图片和对应的txt显示不出框或者框全部缩在左上角。原因txt文件的坐标格式不符合YOLO规范最常见的是框宽度或高度被写成了0或者坐标被写成了像素绝对值而不是归一化值。还有一种情况是读取时把x_center和y_center认成了xmin/ymin放的位置根本不对。解决先手动打开txt看数值范围。如果所有数值都在0到1之间说明是归一化坐标labelImg里会自动反算如果出现大于1的数要么是xml转txt时没有除以图片宽高要么是直接用了VOC坐标冒充YOLO格式。对比一下2.3节的转换逻辑检查脚本里x_center的计算是否漏了除以width。6. 用YOLOv8跑通验证从训练命令到混淆矩阵抽检数据集整理完毕yaml也配好了最后走一遍完整训练验证流程。这里用yolov8的命令行方式不需要额外写训练脚本。先安装ultralytics包然后用一行命令启动训练pip install ultralytics yolo detect train \ data/home/user/gender_dataset/gender.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ patience20 \ project/home/user/gender_dataset/runsmodelyolov8n.pt表示用官方预训练权重做迁移学习n是smallest版本显存不够可以先从它开始如果你显存充裕可以换成yolov8s.pt或yolov8m.pt精度会更高但训练时间也成倍增加。patience20含义是连续20个epoch验证集指标没有提升就提前停止训练这个参数能帮你节省时间但第一次训练建议设大一点或者不设先看看完整的学习曲线。imgsz640是yolov8默认的输入分辨率这份数据集的图片尺寸如果普遍大于640模型会自动缩放不需要手动预处理。训练结束后重点关注runs/detect/train目录下的confusion_matrix.png和results.png两个文件。results.png里能看到三组loss曲线和一个mAP曲线。我第一次跑这份数据时cls_loss在初期的下降速度明显慢于box_loss第一反应是学习率有问题后来检查发现是train和val划分时忘了固定随机种子训练集和验证集有少量重叠。重新划分后loss曲线就恢复正常了。这个经验让我养成了每次拿到新数据集先跑固定种子的划分脚本、再做一次重复实验的习惯。训练完再把验证集里的图批量跑一遍推理抽检结果yolo detect predict \ model/home/user/gender_dataset/runs/detect/train/weights/best.pt \ source/home/user/gender_dataset/images/val \ saveTrue \ conf0.25把输出目录里带预测框的图片人工翻看一遍重点看两类情况一是漏检画面里明显有清晰的人脸或上半身但没画框二是错检比如把背影或长发男性标成Female。人工抽检翻车率控制在5%以内才说明数据集质量可以接受。如果错检集中在某一类回过去检查对应类别的标注框是不是有明显偏大或偏小的问题。从那以后我每次拿到数据集都强制把“解压测试、数量校验、越界检查、固定种子划分、人工抽检”这五步走一遍再进训练流程。这套流程帮我过滤掉了很多表面光鲜但实际不能用的数据包希望也能帮你在训练路上少走几步弯路。本文还有配套的精品资源点击获取
返回列表