1. Face Detect Demo
这个Demo是基于RKNN-Model-Zoo里的RetinaFace来做实时识别。 使用OpenCV + Gstreamer来实现。
1.1 模型转换
需要把RetinaFace的ONNX模型转换成RKNN, 转换步骤请参考Yolo11 Demo里的模型转换。
1.2 C++代码
关于OpenCV + Gstreamer设计部分, 在Yolo11 Demo有说明, 此处就不再赘述。
更改main函数, 使用摄像头获取的视频数据流进行推理识别, 如下:
/*-------------------------------------------
Main Function
-------------------------------------------*/
int main(int argc, char **argv)
{
if (argc != 3)
{
std::cerr << "Usage: " << argv[0] << " <cam_id> <model_path>" << std::endl;
return -1;
}
std::signal(SIGINT, signalHandler);
const char *model_path = argv[2];
int cam_id = std::stoi(argv[1]);
int ret;
rknn_app_context_t rknn_app_ctx;
memset(&rknn_app_ctx, 0, sizeof(rknn_app_context_t));
ret = init_retinaface_model(model_path, &rknn_app_ctx);
if (ret != 0)
{
printf("init_retinaface_model fail! ret=%d model_path=%s\n", ret, model_path);
g_exit.store(true);
return -1;
}
image_buffer_t src_image;
std::string window_name = "Neardi ReinaFace demo";
cv::namedWindow(window_name);
try {
//MemoryPool h264pool(4, 1, 1024, 768); // 768k
MemoryPool pool(4, 1, width, height); // 4 preallocated NV12 dma buffers
// create separate DMA buffer for RGA destination (BGR)
DMABuffer dstBuf;
size_t dst_size = size_t(width) * height * 3; // BGR888
if (!dstBuf.alloc(DMA_HEAP_DMA32_UNCACHED_PATH, dst_size)) {
cerr << "alloc dst dma failed\n";
return -1;
}
std::string cam_dev = "/dev/video" + std::to_string(cam_id);
// start camera thread
thread cam_thread(camera_thread_func, std::ref(pool), cam_dev.c_str(), width, height);
auto dataQ = pool.getDataQueue(0);
auto idleQ = pool.getIdleQueue(0);
cout << "main loop start\n";
while (!g_exit.load(std::memory_order_relaxed)) {
shared_ptr<NV12FrameDMABuf> frame;
if (!dataQ->pop(frame)) {
this_thread::sleep_for(chrono::milliseconds(1));
continue;
}
// Run RGA: src = frame->buf->fd (NV12), dst = dstBuf.fd (BGR)
int src_fd = frame->buf->fd;
int src_size = frame->buf->size;
int dst_fd = dstBuf.fd;
int dst_size_int = int(dstBuf.size);
int ret = rga_nv12_fd_to_bgr_fd(src_fd, src_size, dst_fd, dst_size_int, width, height);
if (ret != 0) {
cerr << "rga convert failed\n";
idleQ->push(frame);
continue;
}
idleQ->push(frame);
// ensure device->cpu sync before reading dstBuf.va
dma_sync_device_to_cpu(dst_fd);
cv::Mat bgr(height, width, CV_8UC3, dstBuf.va);
memset(&src_image, 0, sizeof(image_buffer_t));
if (!mat_to_image_buffer(bgr, src_image, IMAGE_FORMAT_RGB888)) {
printf("mat to image buffer failed\n");
continue;
}
retinaface_result result;
ret = inference_retinaface_model(&rknn_app_ctx, &src_image, &result);
if (ret != 0)
{
printf("init_retinaface_model fail! ret=%d\n", ret);
g_exit.store(true);
break;
}
for (int i = 0; i < result.count; ++i)
{
int rx = result.object[i].box.left;
int ry = result.object[i].box.top;
int rw = result.object[i].box.right - result.object[i].box.left;
int rh = result.object[i].box.bottom - result.object[i].box.top;
draw_rectangle(&src_image, rx, ry, rw, rh, COLOR_GREEN, 3);
char score_text[20];
snprintf(score_text, 20, "%0.2f", result.object[i].score);
// printf("face @(%d %d %d %d) score=%f\n", result.object[i].box.left, result.object[i].box.top,
// result.object[i].box.right, result.object[i].box.bottom, result.object[i].score);
draw_text(&src_image, score_text, rx, ry, COLOR_RED, 20);
for (int j = 0; j < 5; j++)
{
draw_circle(&src_image, result.object[i].ponit[j].x, result.object[i].ponit[j].y, 2, COLOR_ORANGE, 4);
}
}
imshow(window_name, bgr);
if (cv::waitKey(30) >= 0)
{
g_exit.store(true);
break;
}
if (cv::getWindowProperty(window_name, cv::WND_PROP_AUTOSIZE) < 0) // If the window is closed, exit the loop
{
std::cout << "user close this window" << std::endl;
g_exit.store(true);
break;
}
} // end while loop
cam_thread.detach();
} catch (const exception &e) {
cerr << "fatal: " << e.what() << endl;
return -1;
}// end try
ret = release_retinaface_model(&rknn_app_ctx);
if (ret != 0)
{
printf("release_retinaface_model fail! ret=%d\n", ret);
}
return 0;
}
从此处下载完整的代码
1.3 编译
首先需要确保安装OpenCV及gcc, 可以如下命令安装:
sudo apt update
sudo apt install build-essential libopencv-dev
接着更改CMakefile.txt文件, 修改内容如下:
diff --git a/examples/RetinaFace/cpp/CMakeLists.txt b/examples/RetinaFace/cpp/CMakeLists.txt
old mode 100644
new mode 100755
index 788dd6a..97a9821
--- a/examples/RetinaFace/cpp/CMakeLists.txt
+++ b/examples/RetinaFace/cpp/CMakeLists.txt
@@ -22,8 +22,12 @@ endif()
file(GLOB SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+find_package(OpenCV REQUIRED)
+include_directories(${OpenCV_INCLUDE_DIRS})
+
add_executable(${PROJECT_NAME}
main.cc
+ dma_alloc.cpp
${retinaface_file}
)
@@ -33,6 +37,8 @@ target_link_libraries(${PROJECT_NAME}
imagedrawing
${LIBRKNNRT}
dl
+ rga
+ ${OpenCV_LIBS}
)
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
如下命令进行编译:
neardi@LPA3588:~/rknn/rknn_model_zoo$ ./build-linux.sh -t rk3588 -a aarch64 -d RetinaFace -b Release
./build-linux.sh -t rk3588 -a aarch64 -d RetinaFace -b Release
aarch64-linux-gnu
===================================
BUILD_DEMO_NAME=RetinaFace
BUILD_DEMO_PATH=examples/RetinaFace/cpp
TARGET_SOC=rk3588
TARGET_ARCH=aarch64
BUILD_TYPE=Release
ENABLE_ASAN=OFF
DISABLE_RGA=OFF
DISABLE_LIBJPEG=OFF
INSTALL_DIR=/home/neardi/rknn/rknn_model_zoo/install/rk3588_linux_aarch64/rknn_RetinaFace_demo
BUILD_DIR=/home/neardi/rknn/rknn_model_zoo/build/build_rknn_RetinaFace_demo_rk3588_linux_aarch64_Release
CC=aarch64-linux-gnu-gcc
CXX=aarch64-linux-gnu-g++
===================================
-- Configuring done
-- Generating done
-- Build files have been written to: /home/neardi/rknn/rknn_model_zoo/build/build_rknn_RetinaFace_demo_rk3588_linux_aarch64_Release
Consolidate compiler generated dependencies of target audioutils
Consolidate compiler generated dependencies of target imagedrawing
Consolidate compiler generated dependencies of target fileutils
Consolidate compiler generated dependencies of target imageutils
[ 16%] Built target audioutils
[ 33%] Built target imagedrawing
[ 50%] Built target imageutils
[ 66%] Built target fileutils
Consolidate compiler generated dependencies of target rknn_retinaface_demo
[ 75%] Building CXX object CMakeFiles/rknn_retinaface_demo.dir/main.cc.o
[ 83%] Linking CXX executable rknn_retinaface_demo
[100%] Built target rknn_retinaface_demo
[ 16%] Built target imageutils
[ 33%] Built target fileutils
[ 50%] Built target imagedrawing
Consolidate compiler generated dependencies of target rknn_retinaface_demo
[ 83%] Built target rknn_retinaface_demo
[100%] Built target audioutils
Install the project...
-- Install configuration: "Release"
-- Installing: /home/neardi/rknn/rknn_model_zoo/install/rk3588_linux_aarch64/rknn_RetinaFace_demo/./rknn_retinaface_demo
-- Set runtime path of "/home/neardi/rknn/rknn_model_zoo/install/rk3588_linux_aarch64/rknn_RetinaFace_demo/./rknn_retinaface_demo" to "$ORIGIN/../lib"
-- Installing: /home/neardi/rknn/rknn_model_zoo/install/rk3588_linux_aarch64/rknn_RetinaFace_demo/model/test.jpg
-- Installing: /home/neardi/rknn/rknn_model_zoo/install/rk3588_linux_aarch64/rknn_RetinaFace_demo/model/RetinaFace.rknn
-- Installing: /home/neardi/rknn/rknn_model_zoo/install/rk3588_linux_aarch64/rknn_RetinaFace_demo/lib/librknnrt.so
-- Installing: /home/neardi/rknn/rknn_model_zoo/install/rk3588_linux_aarch64/rknn_RetinaFace_demo/lib/librga.so
1.4 运行及测试
执行如下命令运行程序:
neardi@LPA3588:~/rknn/rknn_model_zoo/install/rk3588_linux_aarch64/rknn_RetinaFace_demo$ ./rknn_retinaface_demo 11 ./model/RetinaFace.rknn
model input num: 1, output num: 3
input tensors:
index=0, name=input0, n_dims=4, dims=[1, 320, 320, 3], n_elems=307200, size=307200, fmt=NHWC, type=INT8, qnt_type=AFFINE, zp=-14, scale=1.074510
output tensors:
index=0, name=output0, n_dims=3, dims=[1, 4200, 4, 0], n_elems=16800, size=16800, fmt=UNDEFINED, type=INT8, qnt_type=AFFINE, zp=0, scale=0.044699
index=1, name=572, n_dims=3, dims=[1, 4200, 2, 0], n_elems=8400, size=16800, fmt=UNDEFINED, type=FP16, qnt_type=AFFINE, zp=0, scale=1.000000
index=2, name=571, n_dims=3, dims=[1, 4200, 10, 0], n_elems=42000, size=42000, fmt=UNDEFINED, type=INT8, qnt_type=AFFINE, zp=-22, scale=0.086195
model is NHWC input fmt
model input height=320, width=320, channel=3
main loop start
camera_thread started
[
您的浏览器不支持 video 标签。
](/videos/face.mp4)