概述:用Opencv进行目标检测时,识别的结果显示在控制台上,若将图像显示到QT界面上,需要进行图像的格式转换。关于识别的文本结果,我选择用QLabel控件进行显示,以为可以像C++中cout那样直接输出,实际写的时候发现不是那回事,牵扯到int转换成QString,QString 的用法,QString与string的转化,解决中文乱码等问题。
于是在此做个总结,写了个可视化的界面案例。
VS2019+QT5.13.2+Opencv4.4
(其中Opencv版本必须在4.4及以上,否则不支持YOLOv4)
关于环境的配置参考我之前的博客:
https://blog.csdn.net/qq_45445740/article/details/109582260
①显示文字 (普通文本、html)
label->setText(“Hello, World!”);
②显示图片
//首先定义QPixmap对象
QPixmap pixmap;
//然后加载图片
pixmap.load(":/Image/boat.jpg");
//最后将图片设置到QLabel中
QLabel *label = new QLabel;
label.setPixmap(pixmap);
(PS:QLabel还可以显示gif动画或网页链接)
Qt OpenCV 在界面显示图片 通过Lable方式 和GraphicsView 方式 https://www.cnblogs.com/ybqjymy/p/12356801.html
QString中间是可以包含’\0’符号的,QString也存在append()函数。
参考:https://www.cnblogs.com/qianqiannian/p/6415329.html
//将int转换成QString
QString::number(int)
//QT中QString与string的转化,解决中文乱码问题
QString::fromLocal8Bit("支持中文!")
#include "ConsoleShowLabel.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ConsoleShowLabel w;
w.show();
return a.exec();
}
ConsoleShowLabel.h
#pragma once
#include
#include "ui_ConsoleShowLabel.h"
#include
#include
#include
#include
using namespace std;
using namespace cv;
using namespace cv::dnn;
class ConsoleShowLabel : public QWidget
{
Q_OBJECT
public:
ConsoleShowLabel(QWidget *parent = Q_NULLPTR);
private:
Ui::ConsoleShowLabelClass ui;
//槽函数
private slots:
void Startdetect();
};
ConsoleShowLabel.cpp
#include "ConsoleShowLabel.h"
ConsoleShowLabel::ConsoleShowLabel(QWidget *parent): QWidget(parent)
{
ui.setupUi(this);
}
void ConsoleShowLabel::Startdetect()
{
//加载类别
ifstream classNamesFile("./model/coco.names"); //ifstream默认以输入方式打开文件
vector<string> classNamesVec;
if (classNamesFile.is_open())
{
string className = "";
while (std::getline(classNamesFile, className))
classNamesVec.push_back(className);
}
//模型设置
String cfg = "./model/yolov4.cfg";
String weight = "./model/yolov4.weights";
//模型读入
dnn::Net net = readNetFromDarknet(cfg, weight);
//预处理读取的图像,并将图像读入网络
Mat frame = imread("./image/test.jpg");
//imshow("src", frame);
Mat inputBlob = blobFromImage(frame, 1.0 / 255, Size(608, 608), Scalar());
net.setInput(inputBlob);
//获取未连接输出层
std::vector<String> outNames = net.getUnconnectedOutLayersNames();
std::vector<Mat> outs;
net.forward(outs, outNames);
//目标检测
float* data;
Mat scores;
vector<Rect> boxes;
vector<int> classIds;
vector<float> confidences;
int centerX, centerY, width, height, left, top;
float confidenceThreshold = 0.2; // 置信度设置
double confidence;
Point classIdPoint;
//找出所有的目标及其位置
for (size_t i = 0; i < outs.size(); ++i)
{
data = (float*)outs[i].data;
for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols)
{
scores = outs[i].row(j).colRange(5, outs[i].cols);
minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
//minMaxLoc(src, minVal, maxVal, minLoc, maxLoc, mask)在一个数组中找到全局最小值和全局最大值
if (confidence > confidenceThreshold)
{
centerX = (int)(data[0] * frame.cols);
centerY = (int)(data[1] * frame.rows);
width = (int)(data[2] * frame.cols);
height = (int)(data[3] * frame.rows);
left = centerX - width / 2;
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.3, 0.2, indices);
//效果展示
Scalar rectColor, textColor; //box 和 text 的颜色
Rect box, textBox;
int idx; //类别索引
String className;
Size labelSize;
QString show_text;
show_text = QString::fromLocal8Bit("当前图像的尺寸:"); // QString与string的转化,解决中文乱码问题
show_text.append(QString::number(frame.size().width)); //将int转换成QString
show_text.append(QString::fromLocal8Bit("×"));
show_text.append(QString::number(frame.size().height));
show_text.append("\n");
cout << "当前图像的尺寸:" << frame.size() << endl;
for (size_t i = 0; i < indices.size(); ++i)
{
idx = indices[i];
className = classNamesVec[classIds[idx]];
labelSize = getTextSize(className, FONT_HERSHEY_SIMPLEX, 0.5, 1, 0);
box = boxes[idx];
textBox = Rect(Point(box.x - 1, box.y),
Point(box.x + labelSize.width, box.y - labelSize.height));
rectColor = Scalar(idx * 11 % 256, idx * 22 % 256, idx * 33 % 256);
textColor = Scalar(255 - idx * 11 % 256, 255 - idx * 22 % 256, 255 - idx * 33 % 256);
rectangle(frame, box, rectColor, 2, 8, 0);
rectangle(frame, textBox, rectColor, -1, 8, 0);
putText(frame, className.c_str(), Point(box.x, box.y - 2), FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1, 8);
// API参考:https://blog.csdn.net/KYJL888/article/details/82217192
cout << className << ":" << "width:" << box.width << ",height:" << box.height << ",center:" << (box.tl() + box.br()) / 2 << endl;
show_text.append(QString::fromLocal8Bit(className.c_str())); //string转化成Qstring类型
show_text.append(": width:");
show_text.append(QString::number(box.width));
show_text.append(", height:");
show_text.append(QString::number(box.height));
show_text.append(", center:");
int center_x = (box.tl().x + box.br().x) / 2;
show_text.append(QString::number(center_x));
show_text.append(",");
int center_y = (box.tl().y + box.br().y) / 2;
show_text.append(QString::number(center_y));
show_text.append("\n");
}
ui.labelshow->setText(show_text);
Mat show_detect_img;
cvtColor(frame, show_detect_img, COLOR_BGR2RGB); // 图像格式转换
QImage disImage = QImage((const unsigned char*)(show_detect_img.data), show_detect_img.cols, show_detect_img.rows, QImage::Format_RGB888);
ui.label_detect_display->setPixmap(QPixmap::fromImage(disImage.scaled(ui.label_detect_display->size(), Qt::KeepAspectRatio)));
}
上述工程源文件:
链接:https://pan.baidu.com/s/1AettF7WmCmi1sp-vM6LxCg
提取码:vkrd