VS+QT+Opencv使用YOLOv4进行目标检测并显示目标坐标位置

概述:用Opencv进行目标检测时,识别的结果显示在控制台上,若将图像显示到QT界面上,需要进行图像的格式转换。关于识别的文本结果,我选择用QLabel控件进行显示,以为可以像C++中cout那样直接输出,实际写的时候发现不是那回事,牵扯到int转换成QString,QString 的用法,QString与string的转化,解决中文乱码等问题。
于是在此做个总结,写了个可视化的界面案例。

1.环境配置

VS2019+QT5.13.2+Opencv4.4
(其中Opencv版本必须在4.4及以上,否则不支持YOLOv4)
关于环境的配置参考我之前的博客:
https://blog.csdn.net/qq_45445740/article/details/109582260

2.QLabel控件的使用

2.1QLabel控件的应用

①显示文字 (普通文本、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

2.2QString 的用法

QString中间是可以包含’\0’符号的,QString也存在append()函数。
参考:https://www.cnblogs.com/qianqiannian/p/6415329.html

//将int转换成QString
QString::number(int)
//QT中QString与string的转化,解决中文乱码问题
QString::fromLocal8Bit("支持中文!")

3.源代码

在这里插入图片描述
main.cpp

#include "ConsoleShowLabel.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ConsoleShowLabel w;
    w.show();
    return a.exec();
}

ConsoleShowLabel.h

#pragma once

#include <QtWidgets/QWidget>
#include "ui_ConsoleShowLabel.h"

#include <opencv2/opencv.hpp>
#include<opencv2/dnn.hpp>
#include<fstream>
#include<iostream>

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

  • 7
    点赞
  • 143
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

boss-dog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值