1. 从COFW-68到YOLO:为什么你需要这份转换指南
如果你正在研究人脸关键点检测,尤其是想用YOLO这类单阶段检测器来训练自己的模型,那你很可能已经听说过COFW-68这个数据集了。它全称是“Caltech Occluded Faces in the Wild”,翻译过来就是“野外环境下的遮挡人脸”。这个名字听起来就很有挑战性,对吧?没错,这个数据集最大的特点就是包含了大量在真实场景下被遮挡的人脸,比如被手、眼镜、头发或者物体挡住一部分。这对于训练一个鲁棒性强、能在复杂环境下工作的人脸关键点模型来说,简直是块宝。
原始的COFW数据集标注了29个关键点,而COFW-68则是在其测试集上,由人工精心标注了更细致的68个关键点。这68个点的标注标准,和业界广泛使用的300-W、Dlib等数据集是一致的,涵盖了眉毛、眼睛、鼻子、嘴巴和脸部轮廓。这意味着,你在300-W上训练的模型,可以无缝地拿到COFW-68上来测试,看看它在面对遮挡时的表现到底有多“抗揍”。
但是,问题来了。COFW-68官方提供的数据格式是MATLAB的.mat文件。这对于习惯用Python和深度学习框架(如PyTorch、TensorFlow)的我们来说,用起来有点别扭。更关键的是,如果你想用当下非常流行的YOLO-Pose、YOLOv8-Pose甚至是专门为关键点优化的YOLO-Face等模型来训练,它们通常要求数据是YOLO格式的文本文件。直接拿.mat文件去训练?基本不可能。所以,把COFW-68转换成YOLO格式,就成了使用这个数据集、验证模型泛化能力的必经之路。这份指南,就是带你一步步走完这个转换过程,避开我踩过的那些坑,让你能快速把数据“喂”给YOLO模型。
2. 动手之前:彻底搞懂COFW-68的数据结构
磨刀不误砍柴工,在写代码转换之前,我们必须把COFW-68的数据结构摸得门儿清。我当初就是没仔细看,直接上手,结果坐标转换算得一塌糊涂。COFW-68的数据包通常叫cofw68-benchmark,下载解压后,你会看到类似COFW68_Data这样的文件夹。这里面藏着我们需要的所有信息,主要分为两部分,它们存放在不同的地方。
第一部分:图像本身。 COFW-68本身只提供了标注,原始图片需要从原始的COFW数据集中获取。你需要去下载COFW_color.zip(彩色版本)或COFW.zip(灰度版本)。解压后,你会得到一系列.jpg图片,命名像是cofw_test_0001.jpg。这些就是我们的原始图像素材。在转换时,我们的脚本需要知道这些图片放在哪里。
第二部分:标注信息。 这才是cofw68-benchmark包的核心。它主要包含两个东西:
cofw68_test_annotations/文件夹:这里面有507个.mat文件(对应507张测试图片)。每个文件都以图片名命名,例如cofw_test_0001.mat。用Python的scipy.io.loadmat加载它,你会得到一个字典,里面有两个关键数组:pts和visibility。pts是一个(68, 2)的数组,就是那68个关键点在图片上的(x, y)坐标。visibility是一个长度为68的数组,每个值是0或1,表示对应关键点是否可见(1可见,0被遮挡)。这个信息在训练时非常重要,我们可以忽略被遮挡的点,或者赋予它们更低的权重。cofw68_test_bboxes.mat文件:这个文件包含了所有507张图片的人脸边界框。加载后,你会得到一个bboxes数组,形状是(507, 4)。每一行对应一张图片,四个值分别是[x_min, y_min, width, height]。注意,这里的(x_min, y_min)是边界框左上角的坐标,然后给出宽和高。这个框据说是用和300-W数据集类似的检测方法生成的,这也是为什么模型可以跨数据集测试的原因。
理解这个结构至关重要。我们的转换任务,本质上就是读取这些.mat文件里的坐标,结合对应的图片,把它们变成YOLO能认识的格式。接下来,我们就来深入聊聊YOLO格式到底长什么样。
3. YOLO格式深度解析:不仅仅是中心点归一化
很多人一提到YOLO格式,就只知道“中心点归一化”。这个说法对,但不完整,尤其是对于关键点检测任务。我刚开始做转换的时候,就曾简单地把关键点坐标除以图片宽高,结果训练出来的模型完全不对。这里我们必须把YOLO格式,特别是YOLO-Pose这类支持关键点的变体格式,彻底掰开揉碎讲清楚。
首先,对于目标检测框(Bounding Box),YOLO格式确实是:class_id center_x center_y width height。这里的center_x, center_y, width, height都是归一化到[0, 1]之间的值。归一化的分母是图片的宽度(对于x和w)和图片的高度(对于y和h)。计算方式是:
center_x = (x_min + wid


321

被折叠的 条评论
为什么被折叠?



