人体骨骼关键点检测OKS评价的个人见解

1公式展示

OKS的公式来源于AI Challenger。链接:AI Challenger.
主体思想为关键点位置的加权欧氏距离。
对一个人物p,OKS分数定义如下(与原公式略有改动):
O K S p = Σ i e x p { − d p i 2 / ( 2 S p 2 σ p i 2 ) } δ ( v p i = 1 , v p i ′ = 1 ) Σ i δ ( v p i = 1 ) OKS _p= \frac{\Sigma_{i}exp\{-d_{pi}^{2}/(2S_p^{2}\sigma_{pi}^{2})\}\delta(v_{pi}=1,v_{pi}'=1)}{\Sigma_{i}\delta(v_{pi}=1)} OKSp=Σiδ(vpi=1)Σiexp{dpi2/(2Sp2σpi2)}δ(vpi=1vpi=1)
其中各个符合代表的意思,见下文详解。

2 计算思想(猜测)

2.1 预测点与真实点距离

一个人物的关键点有多个比如头顶、左肩、左肘、左腕。。。
假设头顶这个点编号为1,真实坐标为 ( x 1 , y 1 ) (x_{1},y_{1}) (x1,y1),模型预测值为 ( x 1 ′ , y 1 ′ ) (x_{1}',y_{1}') (x1,y1).如图1圆形代表真实位置,三角形代表预测位置。

d 1 2 = ( x 1 ′ − x 1 ) 2 + ( y 1 ′ − y 1 ) 2 d_1^2 = (x_1'-x_1)^2+(y_1'-y_1)^2 d12=(x1x1)2+(y1y1)2
显然模型预测的位置与真实位置越近(距离越小)越好,反之越差,也就说距离与最后得分OKS成正比
d i 2 = ( x i ′ − x i ) 2 + ( y i ′ − y i ) 2 d_i^2 = (x_i'-x_i)^2+(y_i'-y_i)^2 di2=(xixi)2+(yiyi)2
d i d_i di表示人物编号为i的关键点欧式距离。
欧式距离的平方可以看成两维的,为了与下面提到的面积保持维度一致性,所以这里采用欧式距离的平方。

2.2 人体在图像中的大小

如果A模型预测某个关键点的欧式距离,和B模型预测某个关键点欧式距离一样,我们就说这两个模型一样好吗?不!
如图2,两个预测点欧式距离一样。但是如果右边的人物放大,预测点欧式距离也会变大!

所以说欧式距离一样时,预测人物在图像中的大小越大越差,反之越好。人物面积大小与最后OKS得分成反比
S 2 = w h S^2 = wh S2=wh
S S S代表人物在图像中所占面积的平方根。 S 2 S^2 S2代表面积。这样写与上面的欧式距离的平方在写法上保持一致。
此外面积单位是像素。

2.3 人工标注位置偏移

如果A模型和B模型预测的欧式距离一样,预测的人物面积一样,那么两个模型优劣是否就一样呢?不!
在上文计算的时候,用的所谓真实位置,也不过是人工标注的位置,而不同的关键点,人工标注位置与真实位置偏移不一样。因为人的肩部、臀部可标注的地方要比人的眼睛、鼻子大,因此人的肩部、臀部的偏移量往往比眼睛、鼻子多。
科学的做法是取一大批样本,然后度量不同关键点的标准偏差 σ \sigma σ。但是实际操作有困难。这里也存在一个悖论,如果能度量出人工标注位置的偏移,那在人工标注的时候就可以避免这个偏移。
故本文应用统计的方式计算 σ = E ( d / s ) \sigma=E(d/s) σ=E(d/s).来代替这个标准偏差。
想法就是预测的离散程度越大,说明人工标注位置偏移越大。
人工标注位置的偏移度与最后OKS得分成反比
本文列举两种统计方式:
如图3 圆形代表真实坐标值,空心三角形代表模型A的预测值,实心三角形代表模型B的预测值。

假设头顶编号为1,左脚踝编号为12。
( x 1 , 1 , y 1 , 1 ) (x_{1,1},y_{1,1}) (x1,1,y1,1)代表编号为1的关键点,第1个目标,真实坐标
( x 1 , 1 A , y 1 , 1 A ) (x_{1,1}^A,y_{1,1}^A) (x1,1A,y1,1A)代表编号为1的关键点,第1个目标,A预测坐标
( x 12 , 2 , y 12 , 2 ) (x_{12,2},y_{12,2}) (x12,2,y12,2)代表编号为12的关键点,第2个目标,真实坐标
( x 12 , 2 B , y 12 , 2 B ) (x_{12,2}^B,y_{12,2}^B) (x12,2B,y12,2B)代表编号为12的关键点,第2个目标,B预测坐标
两种统计方式:
第一种,考虑所有目标相同编号点的所有模型预测的离散程度。
r i , j m = ( x i , j m − x i , j ) 2 + ( y i , j m − y i , j ) 2 w i h i r_{i,j}^m=\sqrt{\frac{(x_{i,j}^m-x_{i,j})^2+(y_{i,j}^m-y_{i,j})^2}{w_ih_i}} ri,jm=wihi(xi,jmxi,j)2+(yi,jmyi,j)2
r i , j m r_{i,j}^m ri,jm代表模型m在目标j上关键点i的预测偏移值。

先求平均值,

r 1 ‾ = r 1 , 1 A + r 1 , 2 A + r 1 , 1 B + r 1 , 2 B 4 \overline{r_1}=\frac{r_{1,1}^A+r_{1,2}^A+r_{1,1}^B+r_{1,2}^B}{4} r1=4r1,1A+r1,2A+r1,1B+r1,2B
r 12 ‾ = r 12 , 1 A + r 12 , 2 A + r 12 , 1 B + r 12 , 2 B 4 \overline{r_{12}}=\frac{r_{12,1}^A+r_{12,2}^A+r_{12,1}^B+r_{12,2}^B}{4} r12=4r12,1A+r12,2A+r12,1B+r12,2B
在求均方差,
σ 1 = E ( d 1 S ) = ( r 1 , 1 A − r 1 ‾ ) 2 + ( r 1 , 2 A − r 1 ‾ ) 2 + ( r 1 , 1 B − r 1 ‾ ) 2 + ( r 1 , 2 B − r 1 ‾ ) 2 4 \sigma_1=E(\frac{d_1}{S})=\sqrt{\frac{(r_{1,1}^A-\overline{r_1})^2+(r_{1,2}^A-\overline{r_1})^2+(r_{1,1}^B-\overline{r_1})^2+(r_{1,2}^B-\overline{r_1})^2}{4}} σ1=E(Sd1)=4(r1,1Ar1)2+(r1,2Ar1)2+(r1,1Br1)2+(r1,2Br1)2

σ 12 = E ( d 12 S ) = ( r 12 , 1 A − r 12 ‾ ) 2 + ( r 12 , 2 A − r 12 ‾ ) 2 + ( r 12 , 1 B − r 12 ‾ ) 2 + ( r 12 , 2 B − r 12 ‾ ) 2 4 \sigma_{12}=E(\frac{d_{12}}{S})=\sqrt{\frac{(r_{12,1}^A-\overline{r_{12}})^2+(r_{12,2}^A-\overline{r_{12}})^2+(r_{12,1}^B-\overline{r_{12}})^2+(r_{12,2}^B-\overline{r_{12}})^2}{4}} σ12=E(Sd12)=4(r12,1Ar12)2+(r12,2Ar12)2+(r12,1Br12)2+(r12,2Br12)2
第二种,各自模型考虑各自模型的预测所有目标的相同编号点的离散程度。
先求平均值,

r 1 A ‾ = r 1 , 1 A + r 1 , 2 A 2 \overline{r_1^A}=\frac{r_{1,1}^A+r_{1,2}^A}{2} r1A=2r1,1A+r1,2A
r 12 A ‾ = r 12 , 1 A + r 12 , 2 A 2 \overline{r_{12}^A}=\frac{r_{12,1}^A+r_{12,2}^A}{2} r12A=2r12,1A+r12,2A
在求均方差,
σ 1 A = E ( d 1 S ) = ( r 1 , 1 A − r 1 A ‾ ) 2 + ( r 1 , 2 A − r 1 A ‾ ) 2 2 \sigma_1^A=E(\frac{d_1}{S})=\sqrt{\frac{(r_{1,1}^A-\overline{r_1^A})^2+(r_{1,2}^A-\overline{r_1^A})^2}{2}} σ1A=E(Sd1)=2(r1,1Ar1A)2+(r1,2Ar1A)2

σ 12 A = E ( d 12 S ) = ( r 12 , 1 A − r 12 A ‾ ) 2 + ( r 12 , 2 A − r 12 A ‾ ) 2 2 \sigma_{12}^A=E(\frac{d_{12}}{S})=\sqrt{\frac{(r_{12,1}^A-\overline{r_{12}^A})^2+(r_{12,2}^A-\overline{r_{12}^A})^2}{2}} σ12A=E(Sd12)=2(r12,1Ar12A)2+(r12,2Ar12A)2
通常用第二种方式即可。

2.4 克罗内克函数

× 人工标注数据的时候,每个关键点有三种属性 v v v
v = 0 v = 0 v=0,表示这个关键点不可见,不在图中,或者无法推测在哪;
v = 1 v = 1 v=1,表示这个关键点可见;
v = 2 v = 2 v=2,表示这个关键点不可见,但是可以推测出在哪;
× 预测出来的关键点也分两种属性 v ′ v' v
v ′ = 0 v' = 0 v=0,表示这个关键点未预测出来;
v ′ = 1 v' = 1 v=1,表示这个关键点预测出来了;
在计算OKS的时候,分子只计算人工标注出来可见,且预测出来的点。分母只计算人工标注出可见的点。
克罗内克函数,
δ ( v i = 1 ) = { 1 , i f v i = 1 0 , i f v i ≠ 1 , \delta(v_i=1)=\left\{ \begin{array}{lr} 1, if v_i=1 & \\ 0 ,if v_i \neq1, & \end{array} \right. δ(vi=1)={1,ifvi=10,ifvi̸=1,
也就是 v i = 1 v_i=1 vi=1时,函数取值为1, v i ≠ 1 v_i\neq1 vi̸=1时,函数取值为0.

2.5 归一化

指数函数 e x p ( − x ) = e − x = 1 e x exp(-x)=e^-x=\frac{1}{e^x} exp(x)=ex=ex1的作用是把
d i 2 / ( 2 S 2 σ i 2 ) d_{i}^{2}/(2S^{2}\sigma_{i}^{2}) di2/(2S2σi2)
的取值范围限定在0到1上,且使得距离,人体面积,人工标注偏移与OKS得分和上述分析的增减性保持一致。

3 平均准确率(AP)

平均准确率(AP)给定OKS阈值s,预测的结果在整个测试集上的平均准确率 ( A P @ s ) (AP@s) AP@s可由测试集中所有图片的OKS指标计算得到:
A P @ s = Σ p δ ( O K S p > s ) Σ p 1 AP@s=\frac{\Sigma_p\delta(OKS_p>s)}{\Sigma_p1} AP@s=Σp1Σpδ(OKSp>s)

4 平均准确率(AP)的均值(mAP)

最终指标mAP的计算方式如下所示:
m A P = m e a n { A P @ ( 0.50 : 0.05 : 0.95 ) } mAP=mean\{AP@(0.50:0.05:0.95)\} mAP=mean{AP@(0.50:0.05:0.95)}
从给定阈值0.5到0.95按照0.05步长递计算AP后,再取平均值。

<think>好的,用户想了解如何在YOLOv8姿态估计中修改损失函数为OKS。首先,我需要回顾一下YOLOv8的姿态估计模块的结构和现有的损失函数。根据引用[3],YOLOv8_pose的关键点损失函数目前使用的是BCELoss来计算关键点的可见性置信度。而OKS(Object Keypoint Similarity)是COCO数据集中常用的关键点检测评估指标,直接将其作为损失函数可能更符合评估标准,但需要理解OKS的计算方式以及如何将其转化为可微的损失函数。 首先,我需要确认YOLOv8的代码结构,特别是损失函数部分。根据引用[2],YOLOv8的损失函数替换通常涉及修改分类损失函数的位置,比如FocalLoss、VFLoss、SlideLoss等,用户需要找到对应的代码位置进行替换。同样,对于姿态估计的损失函数,应该是在关键点检测的相关模块中。 接下来,OKS的计算公式需要转化为损失函数。OKS的公式通常是基于预测关键点与真实关键点之间的欧氏距离,并根据每个关键点的尺度进行归一化。具体来说,OKS的计算可能类似于: $$ OKS = \frac{\sum_i \exp(-d_i^2 / (2s^2 \kappa_i^2)) \cdot \delta(v_i > 0)}{\sum_i \delta(v_i > 0)} $$ 其中,$d_i$是预测点与真实点的欧氏距离,$s$是目标尺度(如面积平方根),$\kappa_i$是关键点类型相关的常数,$\delta(v_i > 0)$表示关键点可见时的指示函数。但作为损失函数,需要将其转换为可优化的形式,例如使用1 - OKS作为损失项,以最小化差异。 然后,需要考虑如何在YOLOv8的代码中实现OKS Loss。根据引用[3],关键点的损失计算位于Loss_Kpts_obj,使用BCELoss。因此,需要替换这部分代码,将BCELoss替换为自定义的OKS Loss。同时,需要确保在训练过程中,OKS的计算是可微的,涉及到的参数如关键点坐标、可见性等需要正确地从模型的输出中提取。 另外,需要注意YOLOv8的姿态估计输出结构。通常,模型会输出每个关键点的坐标(x, y)以及置信度。在计算OKS时,需要将预测的坐标与真实坐标进行比较,同时考虑可见性标签。此外,可能需要调整损失函数的权重,与其他损失项(如边界框损失、分类损失)进行平衡。 实现步骤可能包括: 1. 在代码中找到关键点损失的计算部分(根据引用[3],是Loss_Kpts_obj)。 2. 创建一个新的OKS损失类,继承自nn.Module,实现前向传播函数,计算OKS并返回损失。 3. 替换原有的BCELoss为自定义的OKS Loss。 4. 调整超参数,如OKS中的尺度参数和关键点权重,可能需要进行调优。 还需要注意梯度计算的问题,确保所有操作都是可微的。例如,欧氏距离的计算、指数运算等都需要在PyTorch的张量操作中完成,以保留梯度信息。此外,处理可见性标签时,可能需要过滤掉不可见的关键点,避免对损失计算产生影响。 测试和验证也是重要的步骤。修改后需要确保模型能够正常训练,损失下降合理,并且关键点检测的精度有所提升。可能需要参考COCO的评估方法来监控OKS指标的变化。 最后,根据引用[1]的建议,修改损失函数通常是在模型结构调整之后进行的优化步骤。因此,用户需要确保在修改损失函数之前已经完成了其他可能的结构优化,以充分发挥OKS Loss的效果。</think>在YOLOv8姿态估计模型中修改损失函数为OKS(Object Keypoint Similarity)的实现方法可分为以下步骤: ### 1. **理解OKS的计算原理** OKS基于预测关键点与真实关键点的欧氏距离,结合目标尺度和关键点权重: $$ OKS = \frac{\sum_i \exp(-d_i^2 / (2s^2 \kappa_i^2)) \cdot \delta(v_i)}{\sum_i \delta(v_i)} $$ 其中: - $d_i$为预测点与真实点的欧氏距离 - $s$为目标尺度(通常取边界框面积的平方根) - $\kappa_i$为关键点类型相关的归一化因子(COCO数据集中预先定义) - $\delta(v_i)$为关键点可见性指示函数(可见时为1,否则为0) ### 2. **定位YOLOv8的关键点损失代码** 根据引用[3],关键点损失位于`Loss_Kpts_obj`模块,原代码使用`BCELoss`计算置信度: ```python # 原代码片段(基于引用[3]) self.bce = nn.BCEWithLogitsLoss() ... loss_kpts_obj = self.bce(pred_kpts_conf, tgt_kpts_vis) ``` ### 3. **实现OKS损失函数** 创建自定义损失类,继承`nn.Module`并实现前向传播: ```python class OKSLoss(nn.Module): def __init__(self, sigmas, eps=1e-7): super().__init__() self.sigmas = torch.tensor(sigmas) # COCO关键点归一化因子 self.eps = eps def forward(self, pred_kpts, tgt_kpts, tgt_vis, tgt_area): """ pred_kpts: [B, N, 2] 预测关键点坐标(x,y) tgt_kpts: [B, N, 2] 真实关键点坐标 tgt_vis: [B, N] 可见性标签(0/1) tgt_area: [B] 目标区域面积 """ s = torch.sqrt(tgt_area).unsqueeze(-1).unsqueeze(-1) # [B,1,1] d_sq = torch.sum((pred_kpts - tgt_kpts)**2, dim=-1) # [B,N] exponent = -d_sq / (2 * (s**2) * (self.sigmas**2).to(pred_kpts.device) + self.eps) oks = torch.sum(tgt_vis * torch.exp(exponent), dim=-1) / (torch.sum(tgt_vis, dim=-1) + self.eps) return 1 - torch.mean(oks) # 损失=1-平均OKS ``` ### 4. **修改模型配置** 在`loss.py`中找到关键点损失模块并进行替换: ```python # 修改后的代码片段(替换BCELoss) class PoseLoss(DetectionLoss): def __init__(self, model): super().__init__(model) # 原BCELoss注释掉 # self.bce = nn.BCEWithLogitsLoss(reduction='none') self.oks_loss = OKSLoss(sigmas=[.26, .25, ..., .35]) # COCO定义的17个关键点σ ``` ### 5. **调整损失计算流程** 在关键点损失计算阶段调用OKS损失: ```python def __call__(self, pred_kpts, tgt_kpts, tgt_vis, tgt_areas): # 原BCELoss计算注释 # loss_kpts_obj = self.bce(pred_kpts_conf, tgt_kpts_vis) loss_kpts = self.oks_loss(pred_kpts[:, :, :2], tgt_kpts, tgt_vis, tgt_areas) return loss_kpts * self.kpt_factor ``` ### 6. **注意事项** 1. **梯度稳定性**:指数运算需添加微小量`eps`防止数溢出 2. **权重平衡**:通过`self.kpt_factor`调整OKS损失在总损失中的权重(默认建议0.1) 3. **数据预处理**:确保`tgt_area`来自标注数据的边界框面积 4. **评估对齐**:验证集应使用官方OKS评估指标,确保训练目标与评估标准一致 ### 引用验证 修改损失函数应在完成模型结构调整后进行[^1],且需通过消融实验验证效果。实现时可参考COCO官方关键点归一化参数[^3]。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值