代码
#include "opencv2/core/core.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "rknn_api.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <fstream>
#include <iostream>
#include "utils.h"
#include "ai-utils.h"
#include <chrono>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
rknn_context ctx = 0;
int ret;
int model_len = 0;
unsigned char* model;
const char* model_path = argv[1];
const char* img_path = argv[2];
if (argc != 3) {
printf("Usage: %s <rknn model> <image_path> \n", argv[0]);
return -1;
}
// Load image
cv::Mat orig_img = imread(img_path, cv::IMREAD_COLOR);
if (!orig_img.data) {
printf("cv::imread %s fail!\n", img_path);
return -1;
}
cv::Mat orig_img_rgb;
cv::cvtColor(orig_img, orig_img_rgb, cv::COLOR_BGR2RGB);
cv::Mat img = orig_img_rgb.clone();
std::vector<std::string> labels = readLabels(model_path);
cout << labels[0] << " " << labels[1] << endl;
std::vector<unsigned int> modelSize = readModelSize(model_path);
cout << modelSize[0] << " " << modelSize[1] << endl;
int tensor_h = modelSize[0];
int tensor_w = modelSize[1];
int overlap = 5;
uint class_num = labels.size();
ClfDetection clfDet(model_path, tensor_w, tensor_h, img.cols, class_num, overlap);
int big_w = img.cols;
int big_h = img.rows;
std::vector<cv::Rect> valid_areas;
valid_areas.push_back(cv::Rect(0, 0, big_w, big_h));
printf("%d, %d\n", big_h, big_w);
auto start = std::chrono::high_resolution_clock::now();
std::tuple<std::vector<cv::Rect>, std::vector<std::vector<float>>> result = clfDet.inference_big_prob(img, valid_areas);
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << "Execution time: " << duration << " milliseconds" << std::endl;
//推理100次,测试推理时间
for (int i = 0; i < 100; ++i) {
auto start = std::chrono::high_resolution_clock::now();
std::tuple<std::vector<cv::Rect>, std::vector<std::vector<float>>> result = clfDet.inference_big_prob(img, valid_areas);
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << "Execution time: " << duration << " milliseconds" << std::endl;
}
std::vector<cv::Rect> boxes = get<0>(result);
std::vector<std::vector<float>> imgs_probs = get<1>(result);
cout << boxes.size() << " " << imgs_probs.size() << endl;
// int res_big_h = 80;
// cv::Mat resImg = cv::Mat::zeros(res_big_h, big_w, CV_8UC1);
for (int ib = 0; ib < boxes.size(); ib++) {
std::vector<float> probs = imgs_probs[ib];
double prob = probs[0];
cv::Rect rect = boxes[ib];
cout << rect.tl() << rect.br() << " prob: " << prob << " "<< probs[1] << endl;
}
return 0;
}
代码解析
这段代码是一个C++程序,它使用OpenCV和RKNN(Rockchip Neural Network)API来执行一个图像分类或检测任务。以下是对代码主要功能的详细解释:
- 初始化和参数检查:
- 程序首先初始化RKNN的上下文和其他相关变量。
- 检查命令行参数的数量。如果参数数量不正确(不是3个),则打印用法信息并退出程序。
- 加载和处理图像:
- 使用OpenCV的
imread函数加载图像。 - 检查图像是否成功加载。
- 将图像从BGR颜色空间转换为RGB颜色空间,因为某些神经网络模型可能期望RGB输入。
- 使用OpenCV的
- 读取标签和模型尺寸:
- 从与模型相同的路径读取标签文件,这些标签通常用于标识模型输出的类别。
- 读取模型的输入尺寸(宽度和高度),这对于后续将图像调整为模型所需的尺寸是必要的。
- 初始化分类检测器:
- 创建一个
ClfDetection对象(这个类在代码段中没有给出定义,但可能是用于封装RKNN模型推理的自定义类)。 - 传递模型路径、模型的输入尺寸、图像的原始尺寸、类别数量和重叠区域大小来初始化这个对象。
- 创建一个
- 设置有效区域并执行推理:
- 定义一个有效区域,这里将整个图像设置为有效区域。
- 使用
ClfDetection对象的inference_big_prob方法进行推理,该方法可能负责将图像调整为模型所需的尺寸,并执行模型的前向传递。 - 测量并打印推理的执行时间。
- 多次推理性能测试:
- 为了测试推理性能,代码在一个循环中重复执行推理100次,并测量每次推理的时间。
- 处理推理结果:
- 从推理结果中提取检测到的边界框和对应的概率。
- 打印检测到的边界框数量和概率信息。
- 遍历每个检测到的边界框,并打印其位置和最高概率的类别。
需要注意的是,ClfDetection类和readLabels、readModelSize等函数没有在代码段中给出,它们可能是项目中的其他部分或外部库提供的。此外,inference_big_prob方法的具体实现也未在代码段中显示,但根据上下文,它可能负责图像的预处理、模型的推理以及后处理步骤,如非极大值抑制(NMS)等。
总的来说,这段代码是一个使用RKNN API和OpenCV进行图像分类或检测的示例,它展示了从加载图像到处理推理结果的全过程。
3634

被折叠的 条评论
为什么被折叠?



