香橙派ZERO2 Nanodet官方案例
nanodet参考:https://blog.csdn.net/Zhonexixi/article/details/130458254
ZERO 2参考:http://www.orangepi.cn/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-Zero-2.html
用户手册:http://www.orangepi.cn/html/hardWare/computerAndMicrocontrollers/service-and-support/Orange-Pi-Zero-2.html
1.ncnn安装
以下内容节选自zero2用户手册:
1.1 下载NCNN
第一种方法:下载 Orang Pi 百度云盘中提供的 ncnn.tar.gz 压缩包从下面的百度云盘链接可以下载 ncnn.tar.gz源码压缩包。进入 ncnn 文件夹中就能看到.
链接:https://pan.baidu.com/s/1vWQmCmSYdH7iCDFyKpJtVw
提取码:zero
1.2编译安装
tar zxf ncnn.tar.gz
cd ncnn
mkdir build
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/aarch64-linux-gnu.toolchain.cmake -DNCNN_SIMPLEOCV=ON -DNCNN_BUILD_EXAMPLES=ON ..
make -j$(nproc)
注:此过程需要20-25分钟
2.测试识别图片
mkdir nanodet_demo
cp ncnn/build/examples/nanodet nanodet_demo
nanodet 模型文件下载地址如下所示
https://github.com/nihui/ncnn-assets/tree/master/models
打开上面的链接,找 nanodet_m.bin 和 nanodet_m.param 这两个文件,然后下载下来,再上传到开发板 Linux 系统的 nanodet_demo 文件夹中。
将上述图片放置在nanodet_demo目录下,执行下面的命令完成识别:
./nanodet car.png
3修改识别视频
3.1修改源码
测试视频摄像头识别效果,速替换原文件中的draw_objects,main函数,重新执行1.2中的make -j$(nproc)编译即可。
static void draw_objects(const cv::Mat& bgr, const std::vector<Object>& objects, int real_fps)
{
static const char* class_names[] = {
"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
"fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
"elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
"skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
"tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
"sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
"microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
"hair drier", "toothbrush"
};
cv::Mat image = bgr.clone();
for (size_t i = 0; i < objects.size(); i++)
{
const Object& obj = objects[i];
fprintf(stderr, "%d = %.5f at %.2f %.2f %.2f x %.2f\n", obj.label, obj.prob,
obj.rect.x, obj.rect.y, obj.rect.width, obj.rect.height);
cv::rectangle(image, obj.rect, cv::Scalar(255, 0, 0));
char text[256];
sprintf(text, "%s %.1f%%", class_names[obj.label], obj.prob * 100);
int baseLine = 0;
cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
int x = obj.rect.x;
int y = obj.rect.y - label_size.height - baseLine;
if (y < 0)
y = 0;
if (x + label_size.width > image.cols)
x = image.cols - label_size.width;
cv::rectangle(image, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)),
cv::Scalar(255, 255, 255), -1);
cv::putText(image, text, cv::Point(x, y + label_size.height),
cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
// 在帧上绘制实时帧率
std::ostringstream ss;
ss << "Real-time FPS: " << real_fps;
cv::putText(image, ss.str(), cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
cv::imshow("image", image);
//cv::imwrite("output_image.jpg", image);
//cv::waitKey(0);
}
}
int main(int argc, char** argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s [imagepath]\n", argv[0]);
return -1;
}
const char* imagepath = argv[1];
cv::Mat m = cv::imread(imagepath, 1);
// 打开视频文件
cv::VideoCapture cap("video.mp4");
// 获取视频的帧率和总帧数
double fps = cap.get(cv::CAP_PROP_FPS);
int total_frames = cap.get(cv::CAP_PROP_FRAME_COUNT);
// 创建窗口
//cv::namedWindow("Video", cv::WINDOW_NORMAL);
// 循环读取视频帧
cv::Mat frame;
auto start_time = std::chrono::steady_clock::now();
int frame_count = 0;
while (cap.read(frame)) {
// 显示当前帧
if (frame.empty())
{
fprintf(stderr, "cv::imread %s failed\n", imagepath);
return -1;
}
cv::resize(frame, frame, cv::Size(680, 480));
std::vector<Object> objects;
detect_nanodet(frame, objects);
// 计算实时帧率
frame_count++;
auto end_time = std::chrono::steady_clock::now();
auto elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count() / 1000.0;
double real_fps = frame_count / elapsed_time;
draw_objects(frame, objects, real_fps);
frame_count = 0;
// 等待一段时间,以达到正确的帧率
cv::waitKey(1000 / fps);
// 更新计时器
start_time = std::chrono::steady_clock::now();
}
return 0;
}
3.2
放置测试视频
https://qizhiguo-oss-01.oss-cn-qingdao.aliyuncs.com/video.mp4
./nanodet car.png
部署视频识别效果
帧率略低,后期换香橙派5再测试下。
识别效果