在Ubuntu18.04下用c++ opencv4.5
代码如下
vector classes_yolo5;
float Sigmoid(float x) {
return static_cast(1.f / (1.f + exp(-x)));
}
void draw(int classId, float conf, int left, int top, int right, int bottom, Mat& frame) // Draw the predicted bounding box
{
//Draw a rectangle displaying the bounding box
rectangle(frame, Point(left, top), Point(right, bottom), Scalar(0, 0, 255), 3);
string label = format("%.2f", conf);
label = classes_yolo5[classId] + ":" + label;
int baseLine;
Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
top = max(top, labelSize.height);
putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 255, 0), 1);
}
void postprocess_yolo5(Mat& frame, vector& outs,int inpWidth, int inpHeight){
float anchors[3][6] = {{10.0, 13.0, 16.0, 30.0, 33.0, 23.0}, {30.0, 61.0, 62.0, 45.0, 59.0, 119.0},{116.0, 90.0, 156.0, 198.0, 373.0, 326.0}};
float stride[3] = { 8.0, 16.0, 32.0 };
float confThreshold = 0.9;
float nmsThreshold = 0.05;
float objThreshold = 0.9;
vector<int> classIds;
vector<float> confidences;
vector<Rect> boxes;
float ratioh = (float)frame.rows / inpHeight;
float ratiow = (float)frame.cols / inpWidth;
int n = 0, q = 0, i = 0, j = 0, nout = classes_yolo5.size() + 5, c = 0;
float* pdata = (float*)outs[0].data;
for (n = 0; n < 3; n++)
{
int num_grid_x = (int)(inpWidth / stride[n]);
int num_grid_y = (int)(inpHeight / stride[n]);
for (q = 0; q < 3; q++)
{
const float anchor_w = anchors[n][q * 2];
const float anchor_h = anchors[n][q * 2 + 1];
for (i = 0; i < num_grid_x; i++){
for (j = 0; j < num_grid_y; j++){
float box_score = Sigmoid(pdata[4]);
if (box_score > objThreshold){
cv::Mat scores(1, classes_yolo5.size(), CV_32FC1, pdata + 5);
Point classIdPoint;
double max_class_socre;
minMaxLoc(scores, 0, &max_class_socre, 0, &classIdPoint);
max_class_socre = Sigmoid((float)max_class_socre);
if (max_class_socre > objThreshold) {
//rect [x,y,w,h]
float x = (Sigmoid(pdata[0]) * 2.f - 0.5f + j) * stride[n]; //x
float y = (Sigmoid(pdata[1]) * 2.f - 0.5f + i) * stride[n]; //y
float w = powf(Sigmoid(pdata[2]) * 2.f, 2.f) * anchor_w; //w
float h = powf(Sigmoid(pdata[3]) * 2.f, 2.f) * anchor_h; //h
int left = (x - 0.5*w)*ratiow;
int top = (y - 0.5*h)*ratioh;
classIds.push_back(classIdPoint.x);
confidences.push_back(max_class_socre);
boxes.push_back(Rect(left, top, int(w*ratiow), int(h*ratioh)));
}
}
pdata += nout;
}
}
}
}
vector<int> indices;
NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
for (size_t i = 0; i < indices.size(); ++i)
{
int idx = indices[i];
Rect box = boxes[idx];
draw(classIds[idx], confidences[idx], box.x, box.y,
box.x + box.width, box.y + box.height, frame);
}
}
void Quickdemo::yolov5()
{
int inpWidth = 640;//448
int inpHeight =640;
string classesFile = "/home/jzf/Documents/darknet/data/mydata.names";
string yolo5path = "/home/jzf/opencv_test/yolov5/v5lite-sim.onnx";
ifstream ifs(classesFile.c_str());
string line;
while(getline(ifs,line)) classes_yolo5.push_back(line);
Net net = readNetFromONNX(yolo5path);
Mat srcimg;
srcimg = imread("/home/jzf/Documents/darknet/07.jpg");//VOCdevkit/VOC2007/JPEGImages/
//capture.read(srcimg);
Mat blob;
blobFromImage(srcimg, blob, 1 / 255.0, Size(inpWidth, inpHeight), Scalar(0, 0, 0), true, false);
net.setInput(blob);
vector<Mat> outs;
net.forward(outs, net.getUnconnectedOutLayersNames());
postprocess_yolo5(srcimg,outs,inpWidth,inpHeight);
vector<double> layersTimes;
double freq = getTickFrequency() / 1000;
double t = net.getPerfProfile(layersTimes) / freq;
string lable = format("Inference time for a frame : %.2f ms", t);
putText(srcimg,lable,Point(0,15),FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,255));
namedWindow("yolo5", 0);
imshow("yolo5", srcimg);
imwrite("/home/jzf/opencv_test/yolov5.png",srcimg);
}