OKS (Object Keypoint Similarity)公式详细解释
OKS (Object Keypoint Similarity) 是一种用于评估人体姿态估计准确性的指标。OKS 衡量检测到的关键点位置与真实位置之间的匹配程度。详细解释一下 OKS 的简化版计算公式:
O K S = ∑ i exp ( − d i 2 2 s k 2 σ i 2 ) ⋅ δ ( v i > 0 ) ∑ i δ ( v i > 0 ) , OKS = \frac{\sum_{i} \exp\left( - \frac{d_i^2}{2s_k^{2}\sigma_i^{2}} \right) \cdot \delta\left( v_i > 0 \right)}{\sum_{i} \delta\left( v_i > 0 \right)}, OKS=∑iδ(vi>0)∑iexp(−2sk2σi2di2)⋅δ(vi>0),
公式中包括以下几个参数:
exp ( − d i 2 2 s k 2 σ i 2 ) \exp \left( -\frac{d_i^2}{2 s_k^2 \sigma_i^2} \right) exp(−2sk2σi2di2) (高斯衰减项)
高斯衰减项 exp ( − d i 2 2 s k 2 σ i 2 ) \exp \left( -\frac{d_i^2}{2 s_k^2 \sigma_i^2} \right) exp(−2sk2σi2di2) 通常用于机器学习和数据分析中的核方法。这一项描述了数据点之间基于欧几里德距离的相似度。让我们详细解析这个公式中的每个部分:
-
负指数函数 exp ( x ) \exp(x) exp(x):
- 负指数函数是一个增长或衰减非常快的函数。对于负指数,它表示随着输入值的增加,输出值迅速减小。
- 负指数函数 f ( x ) = e − x f(x) = e^{-x} f(x)=e−x 的图像是一条从左上方逐渐下降并接近 x x x 轴的曲线:
- 当 x x x 取较大的负值时,图像在接近无穷大,即 e − ( − ∞ ) = e ∞ = ∞ e^{-(-\infty)} = e^{\infty} = \infty e−(−∞)=e∞=∞。
- 随着 x x x 增加,函数值迅速下降。
- 当 x x x 趋近于零时,函数值接近于1。
- 当
x
x
x 增加到正无穷大时,函数值逐渐接近于0。
这些性质使负指数函数在很多领域(例如物理学、统计学和工程学)中都有广泛的应用。
-
d i d_i di(预测关键点与真实位置的欧几里德距离):
- d i d_i di 是第 i i i 个关键点的预测位置和真实位置之间的欧氏距离。这是两个数据点之间的距离度量,通常用来衡量它们的相似度。距离越大,表示两点之间的相似度越低。
-
s k s_k sk (物体的尺度):
- s k s_k sk 通常是指目标物体的面积或其边界框的宽度和高度等。 是目标的尺度大小,一般选取目标的边界框的面积。
- 归一化尺度差异:在实际应用中,目标物体的大小可能会有很大的差异。例如,一个人在图像中可能看起来很大,因为他离摄像机很近,而另一个人在图像中可能看起来很小,因为他离摄像机很远。引入物体的尺度有助于消除这些大小差异带来的影响,从而实现不同大小的目标之间的公平比较。
-
σ i \sigma_i σi (每个关键点的标准误差,常数):
- σ i \sigma_i σi 是第 i i i 个关键点的标准误差,通常是一个事先设定的常数,用于反映不同关键点的重要性和尺度不确定性。
- σ i \sigma_i σi 可以看作是对每个关键点的重要性赋予权重。在合理设定 σ i \sigma_i σi 的情况下,更重要的关键点(例如头部、四肢的连接点)可以被赋予较小的 σ i \sigma_i σi值,这意味着它们的位置匹配需要更高的精度,从而对 OKS 的贡献更大。
- 对于较不重要的关键点,可以赋予较大的 σ i \sigma_i σi值,使得即使这些关键点的位置预测误差比较大,对总体的 OKS 值影响也较小。
- 通过适当地设置 σ i \sigma_i σi,OKS 能够更准确地反映关键点检测的整体性能,使评估结果更加公平和合理。综合以上因素,(\sigma_i) 对 OKS 值有直接的影响,决定了不同的关键点对最终相似度评分的贡献大小。
-
exp ( − d i 2 2 s k 2 σ i 2 ) \exp \left( -\frac{d_i^2}{2 s_k^2 \sigma_i^2} \right) exp(−2sk2σi2di2) (高斯衰减项):
- 这个项表示基于欧几里德距离的高斯衰减。距离越大,该项值越小,表示相似度越低。
- 其中的每一项 exp ( − d i 2 2 s k 2 σ i 2 ) \exp\left( - \frac{d_i^2}{2 s_k^2 \sigma_i^2} \right) exp(−2sk2σi2di2)表示的是单个关键点的相似度,数值在 0 0 0 到 1 1 1 之间,当 d i = 0 d_i = 0 di=0 时达到最大值 1 1 1,当距离 d i d_i di 越大时,结果越接近 0 0 0。
- 高斯函数使得 OKS 对于检测水平的敏感性较低,即使在检测某些关键点时存在一定误差,只要误差不是很大,OKS 仍然可以给出一个较高的分值。
-
δ ( v i > 0 ) \delta(v_i > 0) δ(vi>0) (可见性标记):
- v i v_i vi 是第 i i i 个关键点的可见性标识。当 v i > 0 v_i > 0 vi>0 时,关键点是可见的;否则不可见。该项用于过滤不可见的关键点,避免对不可见关键点的误差计算影响整体评价。这是一个指示函数,用于忽略不可见的关键点。如果第 i i i 个关键点是可见的(即 v i > 0 v_i > 0 vi>0),则 δ ( v i > 0 ) = 1 \delta(v_i > 0) = 1 δ(vi>0)=1;否则 δ ( v i > 0 ) = 0 \delta(v_i > 0) = 0 δ(vi>0)=0。
- 通过 δ ( v i > 0 ) \delta(v_i > 0) δ(vi>0) 函数忽略了那些不可见的关键点,只计算可见关键点的相似度,从而更准确地反映检测结果的质量。
-
∑ i δ ( v i > 0 ) \sum_{i} \delta(v_i > 0) ∑iδ(vi>0) (归一化的因子):
- 这是用于归一化的因子,即可见关键点的总数量,确保 OKS 值在 ( 0 ) 到 ( 1 ) 之间。
-
总结分数:
- 分子部分是所有可见关键点的高斯衰减项之和。
- 分母部分是所有可见关键点的数量。
分析
-
加权平均:
公式实质上是计算所有可见关键点的加权平均值。 -
高斯惩罚:
使用的是高斯惩罚,预测距离越远,该罚分越多,对整体 OKS 的贡献值就越低。
应用实例
从两组关键点之间计算OKS。假设有两组关键点:真实关键点(ground truth keypoints)和预测关键点(predicted keypoints),以及每个关键点的可见性。
以下是优化后的代码,其中包括两个具有相同维度的关键点集合以及一个对应的可见性数组:
import numpy as np
def calculate_oks(gt_keypoints, pred_keypoints, visibility, s, k):
"""
计算两个关键点集合之间的OKS
参数:
gt_keypoints: 真实关键点的坐标数组,形状为 (N, 2)
pred_keypoints: 预测关键点的坐标数组,形状为 (N, 2)
visibility: 每个关键点的可见性数组,形状为 (N,)
s: 图片的尺度因子(标量)
k: 每个关键点的系数数组,形状为 (N,)
返回值:
oks: 计算得到的OKS值
"""
# 计算每个关键点的欧几里德距离
distances = np.linalg.norm(gt_keypoints - pred_keypoints, axis=1)
# 计算OKS分子
numerator = np.sum(visibility * np.exp(-distances**2 / (2 * (s**2) * (k**2))))
# 计算OKS分母
denominator = np.sum(visibility)
# 计算OKS
oks = numerator / denominator if denominator != 0 else 0.0
return oks
# 示例关键点数据
gt_keypoints = np.array([
[100, 150],
[120, 160],
[130, 170],
[140, 180],
[150, 190]
])
pred_keypoints = np.array([
[102, 148],
[119, 161],
[132, 169],
[145, 182],
[148, 188]
])
# 可见性数组
visibility = np.array([1, 0, 1, 1, 0])
# 关键点系数数组(假设所有关键点系数为 1)
k = np.ones(len(gt_keypoints))
# 图片的尺度因子(假设为 1000),检测框的面积
s = 1000
# 计算 OKS
oks = calculate_oks(gt_keypoints, pred_keypoints, visibility, s, k)
print("OKS:", oks)
代码解析
-
定义
calculate_oks
函数:gt_keypoints
:形状为 ((N, 2)) 的真实关键点坐标数组,(N) 表示关键点的数量。pred_keypoints
:形状为 ((N, 2)) 的预测关键点坐标数组。visibility
:形状为 ((N,)) 的每个关键点的可见性数组。s
:图片的尺度因子,假设为标量。k
:形状为 ((N,)) 的每个关键点的系数数组。
-
计算欧几里德距离:
distances = np.linalg.norm(gt_keypoints - pred_keypoints, axis=1)
- 使用
np.linalg.norm
计算每个关键点的欧几里德距离。
- 使用
-
计算 OKS 分子:
numerator = np.sum(visibility * np.exp(-distances**2 / (2 * (s**2) * (k**2))))
- 利用 NumPy 进行矢量化操作,计算所有可见关键点影响下的加权距离指数。
-
计算 OKS 分母:
denominator = np.sum(visibility)
- 通过求和
visibility
数组,得到可见关键点的数目。
- 通过求和
-
计算 OKS:
oks = numerator / denominator if denominator != 0 else 0.0
- 通过分子除以分母计算 OKS,如果分母为0则返回0.0,防止除以0的错误发生。
-
示例数据:
gt_keypoints
和pred_keypoints
是二维数组,包含5个关键点的x和y坐标。visibility
数组表示每个关键点是否可见。- 假设关键点系数为1且尺度因子为1000。
-
计算并打印 OKS:
oks = calculate_oks(gt_keypoints, pred_keypoints, visibility, s, k) print("OKS:", oks)
这样,通过定义的 calculate_oks
函数,可以更灵活地计算任意两个关键点集合之间的OKS值。
总结
OKS 是通过高斯衰减函数,对所有关键点的误差进行加权平均得到的关键点相似度度量。OKS 的引入有效处理了不同关键点的可见性和尺度差异问题,从而提供了一个鲁棒的姿态估计评估标准。
深入阅读
什么是标准误差 σ \sigma σ
标准误差是一个统计学概念,通常用于描述一组数据的离散程度。
- 公式:
σ
=
1
N
∑
i
=
1
N
(
x
i
−
μ
)
2
\sigma = \sqrt{\frac{1}{N} \sum_{i=1}^{N} (x_i - \mu)^2}
σ=N1∑i=1N(xi−μ)2
- 其中, σ \sigma σ 为标准误差
- N N N 为测量总次数
- x i x_i xi 为第 i i i 次测量的结果
- μ \mu μ 为平均值
在实际应用中,每个关键点都会有一个具体的 σ 值,是个常数。以下是一些可能的场景:
-
人脸关键点:
- 眼睛、鼻子、嘴巴等位置的 σ 值通常较小。
- 相对较难定位的边界关键点(如下巴边缘)的 σ 值会大一些。
-
身体姿态关键点:
- 关节(如膝盖、肘部)的 σ 值通常较小,因为这些部位的定位较为确定。
- 躯干部位(如脊柱中段)的 σ 值可能较大。
什么是负指数函数 exp ( − x ) \exp(-x) exp(−x)
负指数函数是一类函数,其形式通常为 f ( x ) = e − x f(x) = e^{-x} f(x)=e−x,其中 e e e 是自然对数的底数,约为 2.71828。函数 f ( x ) = e − x f(x) = e^{-x} f(x)=e−x的特点如下:
性质
-
递减性:负指数函数是严格递减的函数,即对于所有 x 1 < x 2 x_1 < x_2 x1<x2,有 f ( x 1 ) > f ( x 2 ) f(x_1) > f(x_2) f(x1)>f(x2)。
-
正值性:在定义域内,负指数函数的值始终为正数,即 f ( x ) > 0 f(x) > 0 f(x)>0 对所有实数 x x x 都成立。
-
趋近于零:随着 x x x 趋近于无穷大,负指数函数的值趋近于零。数学上表示为 lim x → + ∞ e − x = 0 \lim_{{x \to +\infty}} e^{-x} = 0 limx→+∞e−x=0。
-
在零点的值:当 x = 0 x = 0 x=0时,负指数函数的值为1,即 e − 0 = 1 e^{-0} = 1 e−0=1。
图像分析
负指数函数 f ( x ) = e − x f(x) = e^{-x} f(x)=e−x 的图像是一条从左上方逐渐下降并接近 x x x 轴的曲线:
- 当 x x x 取较大的负值时,图像在接近无穷大,即 e − ( − ∞ ) = e ∞ = ∞ e^{-(-\infty)} = e^{\infty} = \infty e−(−∞)=e∞=∞。
- 随着 x x x 增加,函数值迅速下降。
- 当 x x x 趋近于零时,函数值接近于1。
- 当 x x x 增加到正无穷大时,函数值逐渐接近于0。
这些性质使负指数函数在很多领域(例如物理学、统计学和工程学)中都有广泛的应用。
什么是高斯衰减 exp ( − 2 s k 2 σ i 2 d i 2 ) \exp\left(- \frac{2s}{k^2 \sigma_i^2} d_i^2 \right) exp(−k2σi22sdi2)
高斯衰减项 exp ( − 2 s k 2 σ i 2 d i 2 ) \exp\left(- \frac{2s}{k^2 \sigma_i^2} d_i^2 \right) exp(−k2σi22sdi2) 通常用于机器学习和数据分析中的核方法。这一项描述了数据点之间基于欧几里德距离的相似度。让我们详细解析这个公式中的每个部分:
-
指数函数 exp ( x ) \exp(x) exp(x): 指数函数是一个增长或衰减非常快的函数。对于负指数,它表示随着输入值的增加,输出值迅速减小。
-
欧几里德距离 d i d_i di: 这是两个数据点之间的距离度量,通常用来衡量它们的相似度。距离越大,表示两点之间的相似度越低。
-
方差 σ i 2 \sigma_i^2 σi2: 这一项通常用来调节高斯函数的宽幅。方差越大,表示高斯函数更宽,对距离的敏感度低;方差越小,表示高斯函数更窄,对距离的敏感度更高。
-
常数项 2 s k 2 \frac{2s}{k^2} k22s:
- s s s 是一个缩放因子,用来调整最终结果的范围。
- k k k 是另一个参数,通常用来调节核函数的尺度,可以理解成控制高斯衰减的速度。
综合在一起,整个公式 exp ( − 2 s k 2 σ i 2 d i 2 ) \exp\left(- \frac{2s}{k^2 \sigma_i^2} d_i^2 \right) exp(−k2σi22sdi2) 表示:
- 当两个数据点非常接近时(即 d i d_i di 很小),负指数项接近于0,计算出的高斯衰减项接近于1,意味着相似度非常高。
- 随着两个数据点之间的距离 d i d_i di 增加,负指数项变得很大,导致高斯衰减项接近于0,表示相似度非常低。
这个高斯衰减项能够有效地捕捉数据点之间的局部相似度,适用于各种机器学习和模式识别中的核方法。
什么是欧几里德距离(Euclidean Distance)
欧几里德距离(Euclidean Distance)是指在欧几里德空间中,用来测量两点之间的“直线”距离的一种度量方式。它是最常见的距离度量方法之一,广泛应用于几何、统计学、机器学习和许多其他科学领域。
二维空间中的欧几里德距离
在二维空间中,如果有两个点 A ( x 1 , y 1 ) A(x_1, y_1) A(x1,y1) 和 B ( x 2 , y 2 ) B(x_2, y_2) B(x2,y2),它们之间的欧几里德距离 d d d 可以通过以下公式计算:
d = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2} d=(x2−x1)2+(y2−y1)2
这个公式的推导基于毕达哥拉斯定理:任意一个直角三角形的斜边的平方等于两个直角边的平方和。
三维空间中的欧几里德距离
在三维空间中,如果有两个点 ( A(x_1, y_1, z_1) ) 和 ( B(x_2, y_2, z_2) ),它们之间的欧几里德距离 ( d ) 如下计算:
d = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 + ( z 2 − z 1 ) 2 d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2 + (z_2 - z_1)^2} d=(x2−x1)2+(y2−y1)2+(z2−z1)2
n 维空间中的欧几里德距离
在更高维度的空间中,如果有两个点 ( A(x_1, x_2, \ldots, x_n) ) 和 ( B(y_1, y_2, \ldots, y_n) ),它们之间的欧几里德距离 ( d ) 公式如下:
d = ∑ i = 1 n ( y i − x i ) 2 d = \sqrt{\sum_{i=1}^{n} (y_i - x_i)^2} d=i=1∑n(yi−xi)2
公式的推导本质上是将各维度上的距离平方和后取平方根,与二维和三维的公式是一致的,只是扩展到了 n 维。
例子
假设有两个点 ( A(1, 2, 3) ) 和 ( B(4, 0, 5) ),它们的欧几里德距离计算如下:
d = ( 4 − 1 ) 2 + ( 0 − 2 ) 2 + ( 5 − 3 ) 2 = 3 2 + ( − 2 ) 2 + 2 2 = 9 + 4 + 4 = 17 d = \sqrt{(4 - 1)^2 + (0 - 2)^2 + (5 - 3)^2} = \sqrt{3^2 + (-2)^2 + 2^2} = \sqrt{9 + 4 + 4} = \sqrt{17} d=(4−1)2+(0−2)2+(5−3)2=32+(−2)2+22=9+4+4=17
在Python中的实现
我们可以使用Numpy库来计算欧几里德距离:
import numpy as np
# 定义两个点
point_A = np.array([1, 2, 3])
point_B = np.array([4, 0, 5])
# 计算欧几里德距离
distance = np.linalg.norm(point_A - point_B)
print("Euclidean Distance:", distance)
上述代码中,np.linalg.norm
函数计算了两个向量之间的范数(默认是 2 范数,也就是欧几里德距离)。
欧几里德距离在实际应用中,例如在机器学习领域用于度量数据点之间的相似性或在图像处理领域用于图像的匹配和比较,非常有用。
指示函数(Indicator Function)
在数学中,指示函数 ( \mathbb{I}_A ) 或 (\delta_A) 通常定义为:
I A ( x ) = { 1 , 如果 x ∈ A 0 , 如果 x ∉ A \mathbb{I}_A(x) = \begin{cases} 1, & \text{如果 } x \in A \\ 0, & \text{如果 } x \notin A \end{cases} IA(x)={1,0,如果 x∈A如果 x∈/A
在这个定义中,集合 (A) 是我们关心的一个子集。如果元素 (x) 属于集合 (A),则指示函数的值为1;否则,它的值为0。
对于 (\delta(v_i > 0)),条件 (v_i > 0) 本质上也形成了一个集合 ({v_i \mid v_i > 0})。因此:
δ ( v i > 0 ) = { 1 , 如果 v i > 0 0 , 如果 v i ≤ 0 \delta(v_i > 0) = \begin{cases} 1, & \text{如果 } v_i > 0 \\ 0, & \text{如果 } v_i \leq 0 \end{cases} δ(vi>0)={1,0,如果 vi>0如果 vi≤0
综上所述, δ ( v i > 0 ) \delta(v_i > 0) δ(vi>0) 是一个表示条件判断的指示函数的符号。它用于将布尔条件的结果(是否满足某个条件)转化为数值(1或0)。这种表示在数学和编程中都有广泛应用,方便我们在数值计算和逻辑判断中使用。