其他分享
首页 > 其他分享> > (目标检测)基于opencv dnn模块的yolov5部署

(目标检测)基于opencv dnn模块的yolov5部署

作者:互联网

文章目录

opencv dnn模块的使用

onnx模型导出

python models/export.py --weights ./weights/yolov5s.pt --img 640 --batch 1

onnx模型分析

在这里插入图片描述

输出层数据处理

	int n = 0, q = 0, i = 0, j = 0, nout = this->classes.size() + 5, row_ind = 0;
	// 遍历三种大小的grid cell
	for (n = 0; n < 3; n++)   
	{
		int num_grid_x = (int)(this->inpWidth / this->stride[n]);
		int num_grid_y = (int)(this->inpHeight / this->stride[n]);
		// 遍历每个grid cell 的 3种大小 anchor box
		for (q = 0; q < 3; q++)    
		{
			const float anchor_w = this->anchors[n][q * 2];
			const float anchor_h = this->anchors[n][q * 2 + 1];
			// 每种anchor box 遍历每个grid cell
			for (i = 0; i < num_grid_y; i++)
			{
				for (j = 0; j < num_grid_x; j++)
				{
					// 访问第q种anchor box对应的数据
					float *ptrData = (float*)outs[n].data + q * num_grid_x * num_grid_y * nout;
                    //float* pdata = (float*)outs[0].data + q * num_grid_x * num_grid_y * nout;
					// 访问第 ij 个 grid cell 的10个数据
					int offset = i * num_grid_x * nout + j * nout;
					ptrData += offset;
					// 访问10个数据的 第5个数据 即 confidence置信度
					// cout << "pdata[4]:" << pdata[4] << endl ;
					auto pBox = ptrData + 4;
					// 归一化置信度
                    float box_score = sigmoid_xx(*pBox); 
					if (box_score > this->objThreshold)
					{
						// cout << "outs[n].cols: " << outs[n].cols << endl;
						// cout << "outs[n].rows: " << outs[n].rows << endl;
						// cout << "outs[n].row: " << outs[n].row(1) << endl;
						// cout << " outs[n].row(row_ind): " <<  outs[n].row(row_ind) << endl;
						// 取出10个数据的后5个 即类别信息 用以判断哪个类别
						Mat score_test ;
						for(uint8_t iter = 5 ; iter < nout ; iter ++){
							score_test.push_back(*(ptrData + iter)); 
						}
						// 把矩阵数据转化为队列
						score_test = score_test.reshape(0,1);
						// cout  << score_test.data << endl;
                        //Mat scores = outs[0].row(row_ind).colRange(5, outs[0].cols);
                        Point classIdPoint;
                        double max_class_socre;
                        // Get the value and location of the maximum score.
						// 获取类别数据中得分最高的数据 并返回索引
                        minMaxLoc(score_test, 0, &max_class_socre, 0, &classIdPoint);
						// 归一化得分最高的数据
                        max_class_socre = sigmoid_x((float)max_class_socre);
						if (max_class_socre > this->confThreshold)
						{
							//pxy的取值范围是[-0.5,1.5],pwh的取值范围是(0,4*anchors[i]]
							//用了跨网格匹配规则,要跨网格预测
							// 将每个grid cell中 bbox 的相对坐标 转换为正个图片的坐标
							float cx = (sigmoid_x(*ptrData) * 2.f - 0.5f + j) * this->stride[n];  ///cx
							float cy = (sigmoid_x(*(ptrData+1)) * 2.f - 0.5f + i) * this->stride[n];   ///cy
							float w = powf(sigmoid_x(*(ptrData+2)) * 2.f, 2.f) * anchor_w;   ///w
							float h = powf(sigmoid_x(*(ptrData + 3)) * 2.f, 2.f) * anchor_h;  ///h
							
							int left = (cx - 0.5*w)*ratiow;
							int top = (cy - 0.5*h)*ratioh;  
							//cout << "(left,top)" << Point2d(left,top) << endl;
							classIds.push_back(classIdPoint.x);
							confidences.push_back(max_class_socre);
							boxes.push_back(Rect(left, top, (int)(w*ratiow), (int)(h*ratioh)));
						}	
					}
					row_ind++;
				}
			}
		}
	}
	

后处理(非极大值抑制&画框)

	// Perform non maximum suppression to eliminate redundant overlapping boxes with
	// lower confidences
	vector<int> indices;
	NMSBoxes(boxes, confidences, this->confThreshold, this->nmsThreshold, indices);
	for (size_t i = 0; i < indices.size(); ++i)
	{
		int idx = indices[i];
		Rect box = boxes[idx];
		this->drawPred(classIds[idx], confidences[idx], box.x, box.y,
			box.x + box.width, box.y + box.height, frame);
		cout << "bbox x" << box.x << endl;
		cout << "bbox y" << box.y << endl;
		cout << "bbox width" << box.width << endl;
		cout << "bbox height" << box.height << endl;
		cout << "--------------" << endl;
		
	}

数据处理图解

在这里插入图片描述

标签:box,yolov5,float,int,dnn,opencv,num,grid,anchor
来源: https://blog.csdn.net/KNIGHT_HOY/article/details/122789180