今天又回到我前2天提到的问题上,我要解决的问题是自动帮助我处理图片,然后归类到文件夹。如下2篇是准备工作,今天开始动手在QT上实现功能。
一,功能说明
- 图片检测是否有人脸,我一般喜欢拍景物照片。所以做一个功能:带人脸和不带人脸的分类
- 我拍的比较烂的照片一般都是曝光问题,在大太阳下手机拍照也看不清。所以做一个功能:灰度直方图均衡化处理后保存。
- 一开始做一个文件,打开文件夹。然后处理这个文件夹中的图片。
关于理论和基础知识我前2天已经准备好了,如下:
图像直方图均衡化算法理解—Apple的学习笔记
opencv图像灰度直方图显示--Apple的学习笔记
主界面.png
二,解决的技术问题
- 照片像素不一,检测人脸的框到达要设置多大,会导致误检测人脸?
解决方法:照片先resize下。 - 通道分割和合并的opencv函数有吗?
解决方法:有的split和merge函数。另外研究了下Mat的=号赋值属于浅copy,可以理解为以指针方式共享内存。mat.clone才是深度copy - QT的QVector无法传入opencv,QString也报错?
解决方法:QString.toStdString()就变成标准的字符串了。QVector我索性不用了,直接使用std::vector。 - 直方图均衡化处理后,某些细节反而没了?
解决方法:毕竟有得有失。我应该添加曝光检测,若曝光度好的就不再继续处理。这个将来再加,我更有动力继续学习算法了。完美,完美,再完美。学以致用,乐趣无穷。
三,GIF效果演示
GIF 2019-12-29 16-17-50.gif四,小二上代码咯
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->actionOpen_folder, &QAction::triggered, this, &MainWindow::open);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::open()
{
ImagePath = QFileDialog::getExistingDirectory(NULL,"caption",".");
qDebug() << ImagePath ;
QDir dir(ImagePath);
QStringList ImageList;
ImageList << "*.bmp" << "*.jpg" << "*.png";//向字符串列表添加图片类型
dir.setNameFilters(ImageList);//获得文件夹下图片的名字
//获得图片名
for (int i=0;i < dir.count();i++)
{
ImageNames.append(dir[i]);
qDebug() << ImageNames[i];//输出图片名
}
}
void MainWindow::on_checkBox_clicked(bool checked)
{
bl_hist = checked;
}
void MainWindow::on_pushButton_clicked()
{
if (bl_hist)
{
ui->pushButton->setEnabled(false);
cv::Mat image_yuv,imageY, imageU, imageV,dstImg;
//定义一个Mat向量容器保存拆分后的数据
std::vector<cv::Mat> imgchannels;
qDebug()<<ImageNames.size();
for(int i=0;i<ImageNames.size();i++)
{
Img_Name = ImagePath.toStdString()+"/"+ImageNames[i].toStdString();
srcImg = cv::imread(Img_Name, cv::IMREAD_COLOR);
cvtColor(srcImg, image_yuv,cv::COLOR_BGR2YUV);
//通道的拆分
cv::split(image_yuv, imgchannels);
//提取单独通道的数据
imageY = imgchannels.at(0);
imageU = imgchannels.at(1);
imageV = imgchannels.at(2);
equalizeHist(imageY, imageY);
//对拆分的通道数据合并
cv::merge(imgchannels,dstImg);
// YUV转RGB
cv::cvtColor(dstImg, srcImg, cv::COLOR_YUV2BGR);
ImageSavePath = "D://qtpro//output//nonFace//";
//人脸检测
facecheck();
//保存图片到分类文件夹
saveFile(i);
}
ui->pushButton->setEnabled(true);
}
}
void MainWindow::saveFile(int i)
{
qDebug()<<"go";
Img_Name = ImageSavePath.toStdString()+ImageNames[i].toStdString();
cv::imwrite(Img_Name,srcImg);
}
void MainWindow::facecheck()
{
//检测人脸
cv::CascadeClassifier cascade;
if (!cascade.load("D://opencv341//VScodebuild2019//install//etc//haarcascades//haarcascade_frontalface_alt.xml"))
{
printf("Cascade.load error\r\n");
}
std::vector<cv::Rect> faces(0);
cv::Mat dstsc;
//cv::resize(srcImg, dstsc, cv::Size(480,640));
if(srcImg.size[0]>1500 || srcImg.size[1]>700)
{
cv::resize(srcImg, dstsc, cv::Size(), 0.4, 0.4);//我长宽都变为原来的0.2倍
cvtColor(dstsc, dstsc, CV_BGR2GRAY);//转化成灰度图来加快人脸识别的速度
}
else
{
cvtColor(srcImg, dstsc, CV_BGR2GRAY);//转化成灰度图来加快人脸识别的速度
}
cascade.detectMultiScale(dstsc, faces, 1.1, 2, 0,cv::Size(30, 30));
if (faces.size() > 0)
{
qDebug()<<"go2";
ImageSavePath = "D://qtpro//output//Face//";
}
else
{
qDebug()<<"go3";
ImageSavePath = "D://qtpro//output//nonFace//";
}
}
网友评论