YOLO是基于COCO数据集,共80种类别,还是比较有限的。
一、YOLO V3模型以及配置文件下载
地址:https://pjreddie.com/darknet/yolo/
二、cfg文件下载以及打开方法
从githu上面下载cfg文件的时候显示的是代码而不是文件。
去下载方法总结如下:
1.参考:github上直接下载文件的两种方式
2.第二种方法就是复制代码到notepad然后另存为即可。
三、查看输入图像的要求
即输入图像为:416*416的尺寸大小,通道顺序为RGB、均值为0,放缩:1/255
输出:多个输出层,输出结构为【C,center_x,center_y,width,heigth】,通过NMS取掉重复Box
四、全部代码
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;
using namespace cv;
using namespace cv::dnn;
void image_detection();
String yolo_cfg = "D:/opencv-4.1.0/models/yolov3/yolov3.cfg";
String yolo_model = "D:/opencv-4.1.0/models/yolov3/yolov3.weights";
int main(int argc, char** argv)
{
image_detection();
}
void image_detection() {
//加载网络模型
Net net = readNetFromDarknet(yolo_cfg, yolo_model);
//net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
net.setPreferableTarget(DNN_TARGET_CPU);
std::vector<String> outNames = net.getUnconnectedOutLayersNames();
for (int i = 0; i < outNames.size(); i++) {
printf("output layer name : %s\n", outNames[i].c_str());
}
vector<string> classNamesVec;
ifstream classNamesFile("D:/opencv-4.1.0/models/yolov3/object_detection_classes_yolov3.txt");
if (classNamesFile.is_open())
{
string className = "";
while (std::getline(classNamesFile, className))
classNamesVec.push_back(className);
}
// 加载图像
Mat frame = imread("D:/images/pedestrian.png");
Mat inputBlob = blobFromImage(frame, 1 / 255.F, Size(416, 416), Scalar(), true, false);
net.setInput(inputBlob);
// 检测
std::vector<Mat> outs;
net.forward(outs, outNames);
vector<double> layersTimings;
double freq = getTickFrequency() / 1000;
double time = net.getPerfProfile(layersTimings) / freq;
ostringstream ss;
ss << "detection time: " << time << " ms";
putText(frame, ss.str(), Point(20, 20), 0, 0.5, Scalar(0, 0, 255));
vector<Rect> boxes;
vector<int> classIds;
vector<float> confidences;
for (size_t i = 0; i<outs.size(); ++i)
{
// Network produces output blob with a shape NxC where N is a number of
// detected objects and C is a number of classes + 4 where the first 4
// numbers are [center_x, center_y, width, height]
float* data = (float*)outs[i].data;
for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols)
{
Mat scores = outs[i].row(j).colRange(5, outs[i].cols);
Point classIdPoint;
double confidence;
minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
if (confidence > 0.5)
{
int centerX = (int)(data[0] * frame.cols);
int centerY = (int)(data[1] * frame.rows);
int width = (int)(data[2] * frame.cols);
int height = (int)(data[3] * frame.rows);
int left = centerX - width / 2;
int top = centerY - height / 2;
classIds.push_back(classIdPoint.x);
confidences.push_back((float)confidence);
boxes.push_back(Rect(left, top, width, height));
}
}
}
vector<int> indices;
NMSBoxes(boxes, confidences, 0.5, 0.2, indices);
for (size_t i = 0; i < indices.size(); ++i)
{
int idx = indices[i];
Rect box = boxes[idx];
String className = classNamesVec[classIds[idx]];
putText(frame, className.c_str(), box.tl(), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255, 0, 0), 2, 8);
rectangle(frame, box, Scalar(0, 0, 255), 2, 8, 0);
}
imshow("YOLOv3-Detections", frame);
waitKey(0);
return;
}
五、效果显示