知识总结:
1.将Mat对象显示到QLabel中,需要类转换(Mat->QImage->QPixmap)
Mat在转换成QImage对象时
QImage((const uchar*)(mat->data),mat->cols,mat->rows,mat->cols*3,QImage::Format_RGB888);
第四参数要传进去,不传QT不会报错显示图片会出现乱图
2.QMessageBox的应用
3.connect函数(lambda表达式)
4.灰度图的图像通道为1
5.画的线在图片中有时候显示不出来是因为在QLabel中缩放的原因,加粗该线或者扩大显示尺寸
6.rectangle绘图函数
这篇文章有介绍这个函数的使用:https://blog.csdn.net/jiangjiao4726/article/details/75220479
widget.cpp:
#include "widget.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
Mat *src = new Mat;
Mat *mat = new Mat;
// namedWindow("Demo");
// imshow("Dome",src);
// waitKey(0);
QImage image;
QPixmap qPixmap;
//设置窗口大小
this->setFixedSize(700,600);
//布置一个label显示图片
QLabel *qLabel = new QLabel(this);
//qLabel->setFixedSize(200,200);
//qLabel->setText("Qlabel");
//布置三个按钮
QPushButton *but1 = new QPushButton("打开显示文件",this);
but1->setGeometry(50,550,100,30);
QPushButton *but2 = new QPushButton("转换灰度图",this);
but2->setGeometry(200,550,100,30);
QPushButton *but3 = new QPushButton("识别",this);
but3->setGeometry(350,550,100,30);
//显示检测到人的数量的label
QTextEdit *people=new QTextEdit(this);
people->setGeometry(610,550,70,30);
QLabel *text = new QLabel(this);
text->setGeometry(520,550,90,30);
text->setText("检测出人数:");
//连接按钮点击事件
//按钮1
connect(but1,&QPushButton::clicked,[=]()mutable{
qDebug() << "but1鼠标单击" << endl;
//QFileDialog qFileDialog(this);
//qFileDialog.setWindowTitle("打开文件");
QString str = QFileDialog::getOpenFileName();//打开文件
if(str.isEmpty())
{
qDebug() << "文件打开失败" << endl;
QMessageBox::information(this,"information","文件打开失败",QMessageBox::Ok,QMessageBox::Ok);
return;
}
qDebug() << str << endl;
*src = imread(str.toStdString(),-1); //第二个参数小于0返回原图带alpha通道
if(!src->data)
{
qDebug() << "图片加载失败" << endl;
QMessageBox::information(this,"information","图片加载失败",QMessageBox::Ok,QMessageBox::Ok);
//qLabel->setText("打开图片失败");
return;
}
//下面代码是将Mat对象显示在QLabel上面
Img2RGB(*src,*mat); //修改图像API BGR->RGB
//imshow("show", *mat);
//rows行数量 cols列数量 uchar* data指向的数据
Mat2QPixmap(mat, qPixmap);
//qLabel->resize(qLabel->pixmap()->size());
qLabel->resize(700,550); //重置QLabel
QSize picSize(700,550);//要缩放的大小
QPixmap scalePixmap = qPixmap.scaled(picSize,Qt::KeepAspectRatio); //后面一个宏是按比例缩放
qLabel->setPixmap(scalePixmap);
qLabel->show();
});
//按钮2
connect(but2,&QPushButton::clicked,this,[=]()mutable{
if(!src->data)
{
qDebug() << "src为空" << endl;
QMessageBox::information(this,"information","没有打开图片",QMessageBox::Ok,QMessageBox::Ok);
return;
}
if(!mat->data)
{
qDebug() << "mat为空" << endl;
QMessageBox::information(this,"information","没有打开图片",QMessageBox::Ok,QMessageBox::Ok);
}
Img2Gray(*src,*mat); //转换为灰度图
Mat temp;
cvtColor(*mat,temp,CV_GRAY2RGB);
//rows行数量 cols列数量 uchar* data指向的数据
Mat2QPixmap(&temp, qPixmap);
//下面代码是将Mat对象显示在QLabel上面
//qLabel->resize(qLabel->pixmap()->size());
qLabel->resize(700,550); //重置QLabel
QSize picSize(700,550);//要缩放的大小
//另一种方式按比例缩放
//qLabel.setScaledContens(true);
QPixmap scalePixmap = qPixmap.scaled(picSize,Qt::KeepAspectRatio); //后面一个宏是按比例缩放
qLabel->setPixmap(scalePixmap);
qDebug() << "but2鼠标单击" << endl;
});
//按钮3
connect(but3,&QPushButton::clicked,this,[=]()mutable{
if(src->data == nullptr || mat->data == nullptr)
{
qDebug() << "src 和 mat 为空" << endl;
QMessageBox::information(this,"information","没有文件",QMessageBox::Ok,QMessageBox::Ok);
return;
}
//没有转换为灰度图单击按钮软件会奔溃
if(mat->channels() !=1)
{
qDebug() << "没有转换为灰度图" << endl;
QMessageBox::information(this,"information","没有转换灰度图",QMessageBox::Ok,QMessageBox::Ok);
return;
}
FancMain(*src, *mat, people);
//imshow("show", *src);
Mat temp;
Img2RGB(*src, temp);
//imshow("show1",temp);
Mat2QPixmap(&temp, qPixmap);
QSize picSize(700,550);//要缩放的大小
//另一种按比例缩放
//qLabel.setScaledContens(true);
QPixmap scalePixmap = qPixmap.scaled(picSize,Qt::KeepAspectRatio); //后面一个宏是按比例缩放
qLabel->setPixmap(scalePixmap);
//imshow("success", *src);
qDebug() << "but3鼠标单击" << endl;
});
}
Widget::~Widget()
{
}
//判断图片的通道,然后转换为灰度图
void Widget::Img2Gray(Mat image, Mat &gray)
{
if(image.channels() == 3)
{
cvtColor(image,gray,CV_BGR2GRAY);
}
else if(image.channels() == 4)
{
cvtColor(image,gray,CV_BGRA2GRAY);
}
else
{
gray = image;
}
}
//转换为RGB
void Widget::Img2RGB(Mat& image, Mat &rgb)
{
if(image.channels() == 3)
{
qDebug() << "图片通道为3" << endl;
cvtColor(image,rgb,CV_BGR2RGB);
}
else if(image.channels() == 4)
{
qDebug() << "图片通道为4" << endl;
cvtColor(image,rgb,CV_BGRA2RGB);
}
else
{
qDebug() << image.channels() << endl;
rgb = image;
}
}
//人脸检测
void Widget::FancMain(Mat &image, Mat &gray, QTextEdit *people) //src已经打开文原图 mat是储存rgb格式 按钮2后mat边为gray
{
CascadeClassifier faceDetetor;
faceDetetor.load("F:/QT/Demo/haarcascade_frontalface_alt2.xml");
if(faceDetetor.empty())
{
QMessageBox::information(this,"information","加载分类器失败",QMessageBox::Ok,QMessageBox::Ok);
qDebug() << "加载检测器失败!" << endl;
return;
}
//直方图均匀化(改善图像的对比度和亮度)
Mat equalizedImg;
equalizeHist(gray,equalizedImg);
int flags = CASCADE_SCALE_IMAGE; //检测多个人
Size minFeatureSize(30,30);
float searchScaleFactor = 1.1f; //默认1.1倍
int minNeighbors = 4;
//QVector faces;
vector<Rect> faces;
faceDetetor.detectMultiScale(equalizedImg,faces,searchScaleFactor,minNeighbors,flags,minFeatureSize);
qDebug() << "检测到人脸的个数:" << faces.size() << endl;
QString str;
str.setNum(faces.size());
qDebug() << str << endl;
people->setText(str);
//画矩形框
Mat face;
Point text_lb;
for(int i = 0; i < faces.size(); i++)
{
if(faces[i].height > 0 && faces[i].width >0 )
{
face = gray(faces[i]);
text_lb = Point(faces[i].x,faces[i].y);
//rectangle(equalizedImg, faces[i],Scalar(255,0,0),1,8,0);
//rectangle(gray,faces[i],Scalar(255,0,0),1,8,0);
//rectangle
//第一个参数:输入的图像,
//第二个参数:
//第三个参数:
//第四个参数:
rectangle(image, faces[i], Scalar(50, 50, 150), 2, 8, 0); //线太细了会导致在QLabel上面丢失线框
}
}
//imshow("lllll",gray);
}
//将cv::Mat转换QPixmap
void Widget::Mat2QPixmap(Mat *mat, QPixmap &qPixmap)
{
QImage qImage;
//rows行数量 cols列数量 uchar* data指向的数据
qImage = QImage((const uchar*)(mat->data),mat->cols,mat->rows,mat->cols*3,QImage::Format_RGB888); //转换成image对象
qPixmap = QPixmap();
qPixmap = QPixmap::fromImage(qImage);//QImage转换为QPixmap
}
widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include
#include "opencv2/opencv.hpp" //opnecv用到的头文件
#include "opencv2/imgproc/types_c.h" //解决CV_BGR2RGB找不到
#include "opencv2/objdetect.hpp" //级联分类器CascadeClassifier头文件
#include "opencv2/highgui.hpp"
#include "opencv2/core/core.hpp"
//#include "opencv2/imgproc.hpp"
#include
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
public:
//判断图片的通道,然后转换为灰度图
void Img2Gray(cv::Mat image, cv::Mat& gray);
void Img2RGB(cv::Mat& image, cv::Mat& rgb);
//人脸检测
void FancMain(cv::Mat& image,cv::Mat& gray,QTextEdit *people);
//将cv::Mat转换QPixmap
void Mat2QPixmap(cv::Mat* mat,QPixmap& qPixmap);
};
#endif // WIDGET_H