CaffeProCFIQ 是一个面向 Linux x86_64 与 ARM64 的指纹图像质量评分工程。工程将 CFIQ 质量评分、前景分割、质量图生成和测试工具统一到 CMake 构建链中,并输出可直接部署的多架构运行包。
当前交付目标:
- 使用同一套源码构建
x86_64与aarch64两类 Linux 版本。 - 发布目录自带
libQualityCtrl.so、libnirvana-kernel.so.8.15.1、模型、测试工具和CFIQ.h。 - 支持 mode 1-6 的质量评分与质量图输出。
- 支持业务侧通过 C ABI 集成算法库。
- 支持多线程调用,但每个线程必须持有独立算法上下文。
| 架构 | 构建方式 | 交付目录 |
|---|---|---|
| x86_64 | Linux/WSL 原生构建 | out/x86_64-cmake/ |
| aarch64 | Linux/WSL 交叉编译 | out/aarch64-cmake/ |
建议构建和运行系统均使用 Ubuntu 24.04 或更高版本。当前发布包依赖 glibc 2.38+ 和 GCC 13 运行时符号,目标机不要求安装编译器,但必须满足运行时版本要求。
CaffeProCFIQ/
├── CMakeLists.txt
├── CMakePresets.json
├── cmake/
│ ├── StageRuntime.cmake
│ ├── VerifySameSha256.cmake
│ └── toolchains/
├── deps/
│ ├── x86_64/
│ └── aarch64/
├── include_cfiq/
│ └── CFIQ.h
├── src_cfiq/
├── test_cfiq/
└── out/
主要目录说明:
src_cfiq/:CFIQ 算法封装与质量模式实现。include_cfiq/CFIQ.h:对外 C ABI 头文件。deps/x86_64/:x86_64 架构依赖库。deps/aarch64/:ARM64 架构依赖库。test_cfiq/:测试程序源码、模型和样本输入。cmake/:运行包 staging、校验和交叉编译配置。out/<arch>-cmake/:构建后可直接打包发布的交付目录。
推荐在 Ubuntu 24.04 或更新版本上构建。Windows 开发机建议通过 WSL2 或 Git Bash 调用脚本进入 Linux 环境,不建议使用 Windows 原生 Visual Studio 生成器。
基础构建依赖:
sudo apt update
sudo apt install -y \
build-essential \
cmake \
make \
file \
binutils \
coreutils \
patchelfARM64 交叉编译还需要:
sudo apt install -y \
gcc-aarch64-linux-gnu \
g++-aarch64-linux-gnu \
binutils-aarch64-linux-gnu版本要求:
- Ubuntu 24.04 或更高版本。
glibc2.38 或更高版本。- GCC/G++ 13.x 或更高版本。
- CMake 3.16 或更高版本。
x86_64 与 ARM64 运行机器均建议使用 Ubuntu 24.04 或更高版本,并安装以下系统运行时依赖:
sudo apt update
sudo apt install -y \
ca-certificates \
libstdc++6 \
libgcc-s1 \
libc6 \
libgomp1 \
libglib2.0-0 \
libglx0 \
libglvnd0 \
libgl1 \
libx11-6 \
libxext6 \
libsm6 \
libice6 \
libtbb12 \
libgdcm3.0 \
libopenjp2-7 \
libopenexr-3-1-30 \
libgdal34
sudo ldconfig说明:
- Ubuntu 24.04 可能自动选择
libglib2.0-0t64、libgdcm3.0t64、libgdal34t64,这是正常的包名变体。 - 发布包已携带 OpenCV、protobuf、OpenBLAS 和 nirvana kernel 等核心运行库。
- OpenCV 的部分间接依赖仍需由目标系统提供。
libstdc++需要支持GLIBCXX_3.4.32。- ARM64 发布包中的
libblas.so.3和liblapack.so.3应优先解析到随包 OpenBLAS,避免落到系统参考 BLAS 导致性能下降。
运行前可检查:
uname -m
ldd --version | head -1
ldconfig -p | grep -E 'libGLX.so.0|libtbb.so.12|libgdcmMSFF.so.3.0|libgdcmDSED.so.3.0|libopenjp2.so.7|libOpenEXR-3_1.so.30|libgdal.so.34'工程通过 CMakePresets.json 管理构建入口。cmake --preset 负责生成 Unix Makefiles 构建目录,cmake --build --preset 会调用对应构建目录中的 Makefile 完成编译和 staging。
查看可用预设:
cmake --list-presets构建 x86_64 交付包:
cmake --preset x86_64-linux
cmake --build --preset x86_64-linux-stage构建 ARM64 交付包:
cmake --preset aarch64-linux
cmake --build --preset aarch64-linux-stage也可以使用脚本:
scripts/build-cmake.sh x86_64
scripts/build-cmake.sh aarch64构建完成后生成:
out/
├── x86_64-cmake/
└── aarch64-cmake/
这两个架构目录就是可直接打包发布的运行目录。
典型交付目录如下:
<arch>-cmake/
├── README.md
├── include/
│ └── CFIQ.h
├── lib/
│ ├── libQualityCtrl.so
│ ├── libnirvana-kernel.so.8
│ ├── libnirvana-kernel.so.8.15.1
│ └── ...
└── test/
├── FingerQualityCtrlTest
├── HeatMap.bin
├── FQNet_model/
└── SourceBmpLinuxTest36/
交付前建议检查:
cd out/<arch>-cmake
file lib/libQualityCtrl.so
file lib/libnirvana-kernel.so.8.15.1
sha256sum lib/libnirvana-kernel.so.8 lib/libnirvana-kernel.so.8.15.1
readelf -Ws lib/libnirvana-kernel.so.8.15.1 | grep GAFIS_ExtractBack
ldd test/FingerQualityCtrlTest | grep "not found" || true
ldd lib/*.so* | grep "not found" || true期望:
file显示目标架构正确。libnirvana-kernel.so.8与libnirvana-kernel.so.8.15.1内容一致。GAFIS_ExtractBack符号存在。ldd不输出not found。
测试程序:
test/FingerQualityCtrlTest
参数格式:
FingerQualityCtrlTest <deploy.prototxt> <caffemodel> <source-bmp-dir> <mode> <thread-count>
单线程 mode 6 分数测试:
cd out/x86_64-cmake/test
export LD_LIBRARY_PATH="../lib:$PWD${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
CFIQ_INLINE_THREAD=1 ./FingerQualityCtrlTest \
./FQNet_model/deploy.prototxt \
./FQNet_model/_iter_50000.caffemodel \
./SourceBmpLinuxTest36 \
6 \
1mode 1-5 会生成质量图。运行前建议清理并准备输出目录:
rm -rf SourceBmpLinux QualityBmpLinux
mkdir -p SourceBmpLinux QualityBmpLinux
CFIQ_INLINE_THREAD=1 ./FingerQualityCtrlTest \
./FQNet_model/deploy.prototxt \
./FQNet_model/_iter_50000.caffemodel \
./SourceBmpLinuxTest36 \
3 \
1输出文件:
Score_Linux.txt:样本质量分数。QualityBmpLinux/*.bmp:mode 1-5 的质量图。SourceBmpLinux/*.bmp:测试工具生成的中间图。
结果检查:
wc -l Score_Linux.txt
find QualityBmpLinux -type f -name '*.bmp' | wc -l
awk 'NR==1{min=$2;max=$2} {if($2<min)min=$2;if($2>max)max=$2} END{print "count=" NR, "min=" min, "max=" max}' Score_Linux.txt对外库和头文件:
lib/libQualityCtrl.so
include/CFIQ.h
核心 C ABI:
extern "C" void InitializeDll(
void **pForeGroundBuffer,
void **pRowColPairStruct,
void **pHeatMapFloat,
void **pCaffeNet,
void **pHInstance,
void **pQuality,
char *pPrototxtPath,
char *pCaffeModelPath);
extern "C" void GetQualityScore(
void *pForeGroundBuffer,
void *pRowColPairStruct,
void *pHeatMapFloat,
void *pCaffeNet,
void *pHInstance,
void *pQuality,
unsigned char *srcBmp,
int width,
int height,
int fgp,
int Core_X,
int Core_Y,
int localSize,
int stepSize,
unsigned char modeNumber,
float *QualityScore);
extern "C" void DestructDLL(
void **pForeGroundBuffer,
void **pRowColPairStruct,
void **pHeatMapFloat,
void **pCaffeNet,
void **pHInstance,
void **pQuality);关键参数:
srcBmp:640x640 灰度像素数据,不包含 BMP 文件头。width/height:固定传640/640。fgp:指位号,范围1-10。Core_X/Core_Y:中心点列号/行号;如果 Core 提取失败可传0,0。localSize:固定传48。stepSize:固定传16。modeNumber:1-6。QualityScore:输出质量分数,通常在0-1范围内。pQuality:mode 1-5 输出 BGR 质量图像素,大小为640 * 640 * 3。
单线程调用示例:
void *fg = nullptr;
void *row_col = nullptr;
void *heatmap = nullptr;
void *net = nullptr;
void *kernel = nullptr;
void *quality = nullptr;
InitializeDll(&fg, &row_col, &heatmap, &net, &kernel, &quality,
prototxt_path, caffemodel_path);
float score = 0.0f;
GetQualityScore(fg, row_col, heatmap, net, kernel, quality,
src_pixels, 640, 640, fgp,
core_x, core_y, 48, 16,
mode, &score);
DestructDLL(&fg, &row_col, &heatmap, &net, &kernel, &quality);| mode | 是否矫正算分 | 是否使用热图 | 是否输出质量图 | 质量图位置 |
|---|---|---|---|---|
| 1 | 是 | 是 | 是 | 矫正后位置 |
| 2 | 是 | 是 | 是 | 原始位置 |
| 3 | 是 | 是 | 是 | 完整前景,原始位置 |
| 4 | 是 | 否 | 是 | 完整前景,原始位置 |
| 5 | 否 | 否 | 是 | 完整前景,原始位置 |
| 6 | 是 | 是 | 否 | 不输出 |
建议:
- 只需要分数时使用 mode 6。
- 需要质量图并保留热图加权逻辑时使用 mode 1-3。
- 需要排除热图影响时使用 mode 4 或 mode 5。
- mode 3 会额外保留局部块网格边框样式,适合检查质量图覆盖区域。
多线程调用时,每个线程必须拥有独立的 InitializeDll 上下文。不要跨线程共享以下指针:
pForeGroundBufferpRowColPairStructpHeatMapFloatpCaffeNetpHInstancepQuality
CPP 伪代码:
struct ThreadContext {
void *fg = nullptr;
void *row_col = nullptr;
void *heatmap = nullptr;
void *net = nullptr;
void *kernel = nullptr;
void *quality = nullptr;
};
struct Job {
unsigned char *src_pixels;
int fgp;
int core_x;
int core_y;
unsigned char mode;
};
void worker(const std::vector<Job> &jobs,
char *prototxt_path,
char *caffemodel_path,
std::mutex &result_mutex,
std::map<std::string, float> &result) {
ThreadContext ctx;
InitializeDll(&ctx.fg, &ctx.row_col, &ctx.heatmap,
&ctx.net, &ctx.kernel, &ctx.quality,
prototxt_path, caffemodel_path);
for (const Job &job : jobs) {
float score = 0.0f;
GetQualityScore(ctx.fg, ctx.row_col, ctx.heatmap,
ctx.net, ctx.kernel, ctx.quality,
job.src_pixels,
640, 640,
job.fgp,
job.core_x,
job.core_y,
48, 16,
job.mode,
&score);
{
std::lock_guard<std::mutex> lock(result_mutex);
result[job_id(job)] = score;
}
if (job.mode >= 1 && job.mode <= 5) {
// ctx.quality points to a 640 * 640 * 3 BGR buffer.
// Copy it to a thread-local output buffer or write it
// to a unique filename before the next call reuses it.
}
}
DestructDLL(&ctx.fg, &ctx.row_col, &ctx.heatmap,
&ctx.net, &ctx.kernel, &ctx.quality);
}注意事项:
InitializeDll和DestructDLL必须在线程内成对调用。- 输出分数容器、日志和质量图文件名由调用方自行保证并发安全。
- 输入像素缓冲区必须在
GetQualityScore调用期间保持有效。 - 不建议多个线程同时写同一个输出文件。
当前版本包含以下规则:
- 局部质量块权重使用
1 / 3 / 5。 - 当
Core_X == 0 && Core_Y == 0时,视为 Core 提取失败。 - Core 提取失败时,使用指纹前景区域所有像素点的重心作为替代中心点。
Release 资产通常包含:
x86_64-cmake-<date>.tar.gzaarch64-cmake-<date>.tar.gzSHA256SUMS-<date>.txt
每个架构包都是完整运行目录,可独立部署。部署时保留目录内的 lib/、include/、test/ 和 README.md。
检查系统依赖和随包库路径:
cd out/<arch>-cmake/test
export LD_LIBRARY_PATH="../lib:$PWD${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
ldd ./FingerQualityCtrlTest | grep "not found" || true
ldd ../lib/*.so* | grep "not found" || true没有输出 not found 才表示动态库解析完整。
说明二进制架构不匹配,检查:
file ./FingerQualityCtrlTest
file ../lib/libQualityCtrl.so
file ../lib/libnirvana-kernel.so.8.15.1ARM64 机器上应显示 AArch64 或 ARM aarch64。
mode 6 只输出分数,不生成质量图。需要质量图时使用 mode 1-5,并确认输出目录存在:
mkdir -p SourceBmpLinux QualityBmpLinux优先检查:
- 两端是否使用同一批 BMP。
- 两端是否使用同一个 mode。
- 两端是否使用同一版模型和
HeatMap.bin。 - 两端是否加载了同一版本
libQualityCtrl.so与libnirvana-kernel.so.8.15.1。 - ARM64 是否优先使用随包 OpenBLAS。
GAFIS_ExtractBack是否能在当前 kernel 中查到。
请确认调用方在首次 GetQualityScore 前已经成功执行 InitializeDll,并且 srcBmp、模型路径、动态库路径均有效。当前工程已在初始化流程中处理 kernel 冷启动路径,业务侧不需要额外预热。