opencv dnn编写yolov5推理代码详解
代码可以跑通的。
1、数据加载和模型加载
net = dnn::readNetFromONNX(onnxfile);
Mat src = imread(testfile);
2、使用硬件推理
// 采用cpu推理
net.setPreferableBackend(dnn::DNN_BACKEND_OPENCV);
net.setPreferableTarget(dnn::DNN_TARGET_CPU);
// 采用gpu推理
net.setPreferableBackend(dnn::DNN_BACKEND_CUDA);
net.setPreferableTarget(dnn::DNN_TARGET_CUDA_FP16);
3、网络建立以及数据对象转换
// 是将输入的图像转换成一个blob对象,该对象里对图像的数据结构进行了封装,可以用于深度学习输入
Mat inputBlob = dnn::blobFromImage(src, 1.0 / 255, Size(640, 640), Scalar(), true, false);
net.setInput(inputBlob); //net模型里输入blob对象
Mat output = net.forward(); //预测结果
4、推理结果输出以及后处理
vector<Rect> boxes; //建立一个rect类型数据,存放bbox
vector<float> confidences;
vector<int> classIds;
vector<int> indexs;
void deal_pred(Mat& img, Mat& preds, vector<Rect>& boxes, vector<float>& confidences, vector<int>& classIds, vector<int>& indexs)
{
float w_ratio = img.cols / 640.0; //图像归一化
float h_ratio = img.rows / 640.0;
cout << "size1:" << preds.size[1] << endl;
cout << "size2:" << preds.size[2] << endl;
//创建一个矩阵,类型是CV_32F,存储85类的数据 85行*25200列
Mat data(preds.size[1], preds.size[2], CV_32F, preds.ptr<float>());
// data.rows=data(preds.size[2]), 25200= (20 * 20 + 40 * 40 + 80 * 80) * 3(其中,3指的是每个格子有3个不同大小anchor,20,40,80划分区域尺寸)
for (int i = 0; i < data.rows; i++)
{
//每一行的,前五个是需要的xywh score
// Mat.at(i,j) mat矩阵第i行第j列
float conf = data.at<float>(i, 4); //每一行的第5个是score(一共是(85*25200个数据))
if (conf < 0.45)
{
continue;
}
//第一个参数是x、y、w、h、score(5个),第二个参数是类别数目,所以后面参数为5+80=85
Mat clsP = data.row(i).colRange(5, 85); // 为指定列创建一个新的矩阵()
Point IndexId;
double score;