整体逻辑非常简洁,核心分为「初始化 → 读图封装 → 推理检测 → 解析结果 → 释放资源」五步,不用对接 RKMedia 视频链路,适合验证 RockX 环境、快速调试算法效果,也是视频流检测的基础单元。
一、整体流程总览

1. 拿图片路径 先存下你运行程序时输的图片文件名,比如你输./rockx_face_detection test.jpg,它就把test.jpg记下来。 但这里没做任何判断,要是你忘输图片名,程序直接就崩了,写得比较糙。
2. 初始化 AI 模型 先造一个 "配置容器",往里面填模型路径 ------ 告诉 AI:模型文件都在/userdata/rockx_data/这个文件夹里,你去这找人脸检测的模型。 然后调用rockx_create,把人脸检测模型加载到板子的 NPU(专门跑 AI 的硬件)里,准备干活。 要是加载失败(比如路径错了、模型文件丢了),就打印一句失败,直接退出。
3. 读取图片 用 RockX 自带的rockx_image_read把图片读进内存,最后那个参数1是把图片转成 RGB 格式。 这个自带的读图函数特别 "娇气",带透明通道的 png、编码特殊的 jpg,它经常读不出来,甚至直接让程序崩掉 ------ 这也是你之前换张图就段错误的核心原因。
4. AI 执行人脸检测 先准备一个 "结果筐",然后调用rockx_face_detect,把图片喂给 AI,让 NPU 跑算法算一遍。算出来的所有人脸坐标、置信度,都存到这个结果筐里。 计算失败就报错退出。
5. 在图上画人脸框 先把图片数据包装成 OpenCV 能认的格式,方便画图。这里是直接复用同一块内存,不额外拷贝数据,省时间,嵌入式里常用这种写法。 然后循环遍历每一张检测到的人脸,算出框的位置和大小,用 OpenCV 在图上画一个青色的矩形框。
6. 保存图片 + 收尾 把画好框的图片存成output_face_det.jpg,然后卸载 AI 模型、释放 NPU 资源,程序结束。
二、完整可运行代码
下面是可以直接编译运行的完整单图人脸检测代码,适配 RV1126 平台:
#include <stdio.h>
#include <memory.h>
#include <sys/time.h>
#include "rknn_rockx_include/rockx_type.h"
#include "rknn_rockx_include/utils/rockx_config_util.h"
#include "rknn_rockx_include/utils/rockx_image_util.h"
#include "rockx.h"
#include <opencv2/opencv.hpp>
#include <opencv2/imgcodecs.hpp>
using namespace cv;
int main(int argc, char **argv)
{
const char * img_path = argv[1];
rockx_config_t * face_detect_config = rockx_create_config();
rockx_add_config(face_detect_config,ROCKX_CONFIG_DATA_PATH, "/userdata/rockx_data/");
rockx_handle_t face_detect_handle;
rockx_ret_t rockx_ret;
rockx_module_t face_rockx_module = ROCKX_MODULE_FACE_DETECTION_V2;
rockx_ret = rockx_create (&face_detect_handle, face_rockx_module,face_detect_config, 0);
if(rockx_ret != ROCKX_RET_SUCCESS)
{
printf("rockx_creat failed...\n");
return -1;
}
rockx_image_t face_rockx_image;
rockx_image_read(img_path, &face_rockx_image, 1);
rockx_object_array_t face_array;
rockx_ret = rockx_face_detect(face_detect_handle, &face_rockx_image, &face_array,nullptr);
if(rockx_ret != ROCKX_RET_SUCCESS)
{
printf("face_detect failed...\n");
return -1;
}
Mat rockx_face_mat = Mat(face_rockx_image.height, face_rockx_image.width, CV_8UC3, face_rockx_image.data);
for(int i = 0; i < face_array.count; i++)
{
int left = face_array.object[i].box.left;
int top = face_array.object[i].box.top;
int w = face_array.object[i].box.right - face_array.object[i].box.left;
int h = face_array.object[i].box.bottom - face_array.object[i].box.top;
Rect boundingRect(left, top, w, h);
rectangle(rockx_face_mat, boundingRect, Scalar(255,255,0), 1);
}
imwrite("output_face_det.jpg",rockx_face_mat);
rockx_destroy(face_detect_handle);
return 0;
}
2.1 初始化 rockx 人脸检测框架
int main(int argc, char **argv)
{
const char * img_path = argv[1];
rockx_config_t * face_detect_config = rockx_create_config();
rockx_add_config(face_detect_config,ROCKX_CONFIG_DATA_PATH, "/userdata/rockx_data/");
rockx_handle_t face_detect_handle;
rockx_ret_t rockx_ret;
rockx_module_t face_rockx_module = ROCKX_MODULE_FACE_DETECTION_V2;
rockx_ret = rockx_create (&face_detect_handle, face_rockx_module,face_detect_config, 0);
if(rockx_ret != ROCKX_RET_SUCCESS)
{
printf("rockx_creat failed...\n");
return -1;
}
初始化首先要使用rockx_create_config 分配rockx_config_t结构体,并使用rockx_add_config 把对应的rockx路径配置进去,在我们的板子里面在**/userdata/rockx_data** 里面,并使用rockx_create创建rockx_handle_t句柄。
2.2 读取人脸图片
rockx_image_t face_rockx_image;
rockx_image_read(img_path, &face_rockx_image, 1);
读取对应的人脸图片,在rockx里面用rockx_image_read来读取对应的人脸图片。并把人脸的特征数据传入到rockx_image_t结构体里面。
2.3 调用 rockx 的人脸检测 API 对其进行人脸检测
rockx_object_array_t face_array;
rockx_ret = rockx_face_detect(face_detect_handle, &face_rockx_image, &face_array,nullptr);
if(rockx_ret != ROCKX_RET_SUCCESS)
{
printf("face_detect failed...\n");
return -1;
}
调用rockx_face_detect 对图片进行人脸检测,这里的输入的是input_image ,这个是由rockx_image_read 读取的图片数据,输出的数据是rockx_object_array_t , 后面的数据则都是通过rockx_object_array_t来处理。
2.4 循环人脸数量并使用 Opencv 进行画框
Mat rockx_face_mat = Mat(face_rockx_image.height, face_rockx_image.width, CV_8UC3, face_rockx_image.data);
for(int i = 0; i < face_array.count; i++)
{
int left = face_array.object[i].box.left;
int top = face_array.object[i].box.top;
int w = face_array.object[i].box.right - face_array.object[i].box.left;
int h = face_array.object[i].box.bottom - face_array.object[i].box.top;
Rect boundingRect(left, top, w, h);
rectangle(rockx_face_mat, boundingRect, Scalar(255,255,0), 1);
}
循环人脸数量,人脸数量是face_array.count。然后获取人脸的坐标属性,这里的坐标属性就是left、top、w、h,并用OPENCV把input_image转换成Mat矩阵( Mat tmp_img = Mat(input_image.height, input_image.width, CV_8UC3, input_image.data)),转换完成之后再使用rectangle把坐标转换成矩形。
2.5 保存人脸检测的图片
imwrite("output_face_det.jpg",rockx_face_mat);
rockx_destroy(face_detect_handle);
最后用imwrite保存人脸检测后的图片,并使用rockx_destroy销毁rockx_handle_t。

三、高频踩坑点总结
1. 初始化失败,返回非 0 错误码
90% 是模型路径不对:
- 必须写绝对路径,不能写相对路径;
- 路径要指到
rockx_data根目录,不要指到face_det子目录里; - 确认目录下有对应算法的模型文件,权限正常可读。
2. 模块 ID 不匹配
不同版本的 RockX SDK,人脸检测模块名可能不同:
- 老版本:
ROCKX_MODULE_FACE_DETECT - 新版本 V2:
ROCKX_MODULE_FACE_DETECTION_V2 - 用错模块 ID 会初始化失败,和你的 SDK 版本对应上就行。
四、和视频流检测的关系
单图检测是视频流检测的「单帧单元」,视频流场景只是把「读单图」换成了「RKMedia 取帧」,后面的封装、推理、解析结果、画框的逻辑100% 完全通用。 建议先跑通单张图片的 demo,确认环境、算法都正常,再把检测逻辑移植到你之前的视频线程里,调试成本会低很多。