RetinaFace 与 CurricularFace 推理脚本排错记录
你大概率也碰到过这种情况:镜像已经拉好,环境看着没问题,推理脚本一跑还是报错。不是模块找不到,就是 CUDA 版本不对;更烦的是,偶尔能跑通,但相似度结果忽高忽低,没法判断到底是模型问题还是输入有问题。这里不打算讲原理课,只记录一件事:在 Python 3.11.14 环境里,怎么把 RetinaFace + CurricularFace 这条人脸检测和识别链路跑稳。
这套镜像不是简单把两个模型拼在一起。RetinaFace 先做检测,找出图里的脸,通常会优先取最大、最完整的那张;CurricularFace 再接着做特征提取和比对。中间少了手工裁剪和格式转换,流程确实省事,但排错也更依赖环境本身。Python 3.11.14、PyTorch 2.5.0+cu121、CUDA 12.1 这些组合,任何一处不对都可能让脚本在最后一步倒下。
| 组件 | 版本 | 关键说明 |
|---|---|---|
| Python | 3.11.14 | 部分旧包兼容性一般,镜像里已经换成可用版本 |
| PyTorch | 2.5.0+cu121 | 需要配套 CUDA 12.1 驱动;nvidia-smi 显示过低就别硬跑 |
| CUDA / cuDNN | 12.1 / 8.9 | 镜像内已带好,但 nvcc --version 还是要确认 |
| ModelScope | 1.13.0 | 首次运行会下载权重,网络不通就会卡住 |
| 代码位置 | /root/Retinaface_CurricularFace | 脚本和示例图都在这里,目录别进错 |
镜像的思路很明确:能少装就少装,但日志和路径得给你留够线索。调试这种环境,靠猜没用,得先把最基础的入口跑通。
先把环境切对
cd /root/Retinaface_CurricularFace
conda activate torch25
激活成功后,提示符前面会出现 (torch25),which python 应该指向 /root/miniconda3/envs/torch25/bin/python。
常见的第一个坑是 conda: command not found。这不是环境没装,而是当前 shell 没加载初始化脚本。先执行 source /root/miniconda3/etc/profile.d/conda.sh,再激活。
如果报 CommandNotFoundError: 'torch25' is not a conda environment,多半是环境名记错了。这个镜像里就是 torch25,别拿别的项目里的名字来套。
还有一种情况更隐蔽:conda activate 看着成功了,但 python 还是系统自带的版本。这个时候直接跑脚本,torch 很可能找不到。先用 which python 看路径,不对就先清缓存:
hash -r
which python
先跑默认推理
python inference_face.py
正常情况下,日志会先加载 RetinaFace,再加载 CurricularFace,然后处理示例图片,最后给出相似度和判断结果。类似这样:
[INFO] Loading RetinaFace detector...
[INFO] Loading CurricularFace model...
[INFO] Processing ./imgs/face_recognition_1.png
[INFO] Detected 1 face (largest box: [124, 87, 263, 226])
[INFO] Processing ./imgs/face_recognition_2.png
[INFO] Detected 1 face (largest box: [131, 92, 270, 231])
[INFO] Cosine similarity: 0.872
[RESULT] Same person: YES (threshold=0.4)
这里最值得盯的是 Detected 1 face (largest box: [...])。它说明检测器真的把脸找出来了,不是你手工传了个裁剪好的结果。如果这里变成 Detected 0 face,先别怀疑模型,先检查图片本身:尺寸是不是太小、是不是全黑、是不是格式坏了。
几个常见报错也基本都和环境有关:
ModuleNotFoundError: No module named 'torch':多半是解释器没指到 conda 环境里的 Python,不要用/usr/bin/python。OSError: libcudnn.so.8: cannot open shared object file:通常是LD_LIBRARY_PATH没带上 CUDA 路径,补一下再跑。- 图片路径报错或者直接检测不到脸:先看
./imgs/目录还在不在,必要时用file ./imgs/face_recognition_1.png确认文件没坏。
export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATH
自定义图片时,路径比你想的更重要
python inference_face.py --input1 /home/user/pic1.jpg --input2 /home/user/pic2.jpg
这套脚本更适合用绝对路径。工作目录固定在 /root/Retinaface_CurricularFace,如果你图放在 /home 或 /data,相对路径大概率会解释错。这个坑很常见,也最没必要。
如果报 FileNotFoundError: [Errno 2] No such file or directory: '/home/user/pic1.jpg',先别急着怀疑代码,先确认路径拼对了,权限也够。ls -l 和 tab 补全比盯报错信息更快。
脚本也支持直接传 URL:
python inference_face.py --input1 https://example.com/a.jpg --input2 https://example.com/b.jpg
它内部会用 requests.get() 下载,并缓存到 ./cache/。省去手动下载这一步,调试时挺方便,但对网络比较挑。requests.exceptions.ConnectionError 或超时,通常不是代码错了,而是镜像默认没配代理,外网访问慢或者直接失败。先用 curl -I 看看连通性,不行就换能直连的地址,或者先下到本地。
还有一种更麻烦:URL 打开后不是图片,而是网页错误页。这个时候会报 PIL.UnidentifiedImageError: cannot identify image file。浏览器先看一眼,或者直接确认返回内容是不是图片,比反复重跑更省时间。
阈值不是固定值
python inference_face.py -i1 ./imgs/1.jpg -i2 ./imgs/2.jpg --threshold 0.6
这里的阈值是相似度判定线。0.4、0.6、0.2 不是谁更'正确',而是场景不同:宽松一点适合粗筛,严格一点适合身份核验。这个值别死记,实际效果要看你的图片质量、采集环境和业务容忍度。
调高阈值以后,原来能判成同一人的图可能会被判掉。这个现象不一定是模型退化,很多时候只是阈值变严了。反过来也一样,阈值太低,误判会明显变多。
如果还是不对,先查这几件事
which python指向的到底是不是torch25环境。nvidia-smi显示的驱动版本是否满足 CUDA 12.1。LD_LIBRARY_PATH里有没有/usr/local/cuda-12.1/lib64。- 输入图片是不是有效文件,而不是空文件或网页内容。
- 脚本参数有没有把本地路径和 URL 混着写。
这套流程不算复杂,但它特别吃环境一致性。脚本本身并不神秘,真正容易出问题的是路径、依赖和输入格式。先把这些基础条件收紧,RetinaFace 负责把脸找出来,CurricularFace 再去做比对,结果通常就会稳定很多。
