Qt篇——简单调用yolov3模型识别常见物品
下面仅为一个简单的举例:
一、首先需要引入opencv库。这个就不细讲了,各位可以自行百度。
#在pro文件中引入opencv库,我是用的opencv454 mingw64位的
opencv {
win32 {
INCLUDEPATH += $$PWD/3rdparty/opencv454/include
INCLUDEPATH += $$PWD/3rdparty/opencv454/include/opencv2
LIBS += $$PWD/3rdparty/opencv454/libopencv_world454.dll.a
}
}
#这只是一种引入方式,具体大家可以网上搜索,或者评论区留言我给opencv454库下载链接
二、下载yolov3的模型文件yolov3.weights、yolov3.cfg、coco.names。
网上搜索可以下载到,或者在评论区留言我给模型下载链接
三、代码调用(yolov3模型文件和识别的图片1.png放在exe同级目录下)
dnntest.h头文件
#ifndef DNNTEST_H
#define DNNTEST_H
#include <QString>
#include <opencv2/dnn.hpp>
#include <fstream>
class DnnTest
{
public:
DnnTest();
std::vector<std::string> getClasses(const QString &classesFile) {
std::vector<std::string> classes;
std::ifstream ifs(classesFile.toStdString().c_str());
std::string line;
while (getline(ifs, line)) {
classes.push_back(line);
}
return classes;
}
cv::dnn::Net loadModel(QString modelConfiguration, QString modelWeights) {
return cv::dnn::readNetFromDarknet(modelConfiguration.toStdString(), modelWeights.toStdString());
}
void startTest(const cv::Mat &frame, cv::dnn::Net &net, const std::vector<std::string> &classes);
};
#endif // DNNTEST_H
dnntest.cpp源文件
#include "dnntest.h"
#include <QString>
#include <QDebug>
#include <opencv2/imgcodecs.hpp>
#include <QCoreApplication>
#include <QDir>
DnnTest::DnnTest()
{
QString exeDir = QCoreApplication::applicationDirPath();
QString filePathPic = QDir(exeDir).filePath("1.png");
QString filePathClasses = QDir(exeDir).filePath("coco.names");
QString filePathModelWeights = QDir(exeDir).filePath("yolov3.weights");
QString filePathModelConfiguration = QDir(exeDir).filePath("yolov3.cfg");
cv::Mat image = cv::imread(filePathPic.toStdString());
auto net = loadModel(filePathModelConfiguration, filePathModelWeights);
auto classes = getClasses(filePathClasses);
startTest(image, net, classes);
}
void DnnTest::startTest(const cv::Mat &frame, cv::dnn::Net &net, const std::vector<std::string> &classes) {
cv::Mat blob;
cv::dnn::blobFromImage(frame, blob, 1 / 255.0, cv::Size(416, 416), cv::Scalar(0, 0, 0), true, false);
net.setInput(blob);
std::vector<cv::Mat> outs;
net.forward(outs, net.getUnconnectedOutLayersNames());
// 后处理:解析检测结果
for (const auto &output : outs) {
auto *data = reinterpret_cast<float*>(output.data);
for (int j = 0; j < output.rows; ++j, data += output.cols) {
float confidence = data[4];
if (confidence > 0.1) { // 过滤低置信度的物体
int classId = -1;
float maxConfidence = -1;
for (int k = 5; k < output.cols; ++k) {
if (data[k] > maxConfidence) {
maxConfidence = data[k];
classId = k - 5;
}
}
if (classId >= 0 && maxConfidence > 0.1) {
QString label = QString::fromStdString(classes[classId]);
qDebug() << "x,y,w,h" << data[0] << data[1] << data[2] << data[3];
qDebug() << "Detected object:" << label << "with confidence:" << maxConfidence;
}
}
}
}
}
日志打印如下:
x,y,w,h 0.200591 0.493517 0.17878 0.380748
Detected object: "apple" with confidence: 0.916478
x,y,w,h 0.19109 0.520369 0.193458 0.385598
Detected object: "apple" with confidence: 0.930474
x,y,w,h 0.199505 0.521505 0.17687 0.35982
Detected object: "apple" with confidence: 0.960644
x,y,w,h 0.190564 0.542987 0.198303 0.37466
Detected object: "apple" with confidence: 0.366576
x,y,w,h 0.198655 0.542039 0.19229 0.374069
Detected object: "apple" with confidence: 0.748606
注:x,y,w,h的数值都是基于图片的比例,demo识别的图片1.png内容是:桌上有一个苹果。