dlib人脸识别中Cosine Similarity大于1的问题及正确计算方法
如何正确计算人脸识别中的余弦相似度?
我在VS Code中使用dlib进行人脸识别测试,原代码以欧氏距离(Euclidean distance)小于0.6判定为同一人脸。编写了计算Cosine Similarity的代码,但得到的结果大于1,结果明显有误,请问如何获取正确的Cosine Similarity?
相关代码:
fig, ax = plt.subplots(1, figsize=(20, 20)) ax.imshow(img_rgb) for i, desc in enumerate(descriptors): found = False for name, saved_desc in descs.items(): dist = np.linalg.norm([desc] - saved_desc, axis=1) # my code : compute cosine similarity cosine = np.dot([desc],saved_desc)/(norm([desc]),norm(saved_desc)) if dist < 0.6: found = True text = ax.text(rects[i][0][0], rects[i][0][1], name, color='b', fontsize=40, fontweight='bold') text2 = ax.text(rects[i][1][0], rects[i][1][1], cosine, color='b', fontsize=20, fontweight='bold') text.set_path_effects([path_effects.Stroke(linewidth=10, foreground='white'), path_effects.Normal()]) rect = patches.Rectangle(rects[i][0], rects[i][1][1] - rects[i][0][1], rects[i][1][0] - rects[i][0][0], linewidth=2, edgecolor='w', facecolor='none') ax.add_patch(rect) break
当前错误输出:
neo [1.35159114 1.36754706] neo [1.15541134 1.10536481] trinity [1.13942505 1.03432384] morpheus [1.26643039 1.28631887] neo [1.28240694 1.31706417] trinity [1.4723583 1.43481646]
期望得到小于1的Cosine Similarity。
问题原因
- 分母错误使用逗号:
(norm([desc]),norm(saved_desc))创建了一个元组,而非两个范数的乘积。Numpy会将其视为对分子进行广播除法,导致结果异常。 - 维度冗余:
[desc]将一维的人脸描述符转为二维数组,增加了计算复杂度,还可能引发维度不匹配的隐性问题。
修正后的代码
将余弦相似度计算代码替换为以下内容:
# 修正后的余弦相似度计算 desc_norm = np.linalg.norm(desc) saved_desc_norm = np.linalg.norm(saved_desc) # 避免除以0的异常情况 if desc_norm == 0 or saved_desc_norm == 0: cosine = 0.0 else: cosine = np.dot(desc, saved_desc) / (desc_norm * saved_desc_norm)
额外说明
- 余弦相似度的取值范围是**[-1, 1]**,值越接近1表示两个特征向量越相似,适合用来衡量人脸特征的匹配度。
- 若
saved_desc是存储多个人脸描述符的二维数组,可调整为:cosine = np.dot(desc, saved_desc.T) / (desc_norm * np.linalg.norm(saved_desc, axis=1))
内容的提问来源于stack exchange,提问作者Luke
相关产品推荐
相关产品推荐

