热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

图像处理——Qt5.12.0+opencv2.4.6的使用

本次项目主要是使用Qt平台编写图像处理程序,用到了opencv库。本文主要讲解怎么在Qt平台中添加opencv库,以及使用opencv库的注意事项&#x

本次项目主要是使用Qt平台编写图像处理程序,用到了opencv库。本文主要讲解怎么在Qt平台中添加opencv库,以及使用opencv库的注意事项,通过opencv库实现图像的直方图分析,形态学处理,线性滤波和非线性滤波,图像二值化,边缘提取以及轮廓分析,人脸检测,使用多线程批量处理图片加快处理速度等。

若想要编译好的opencv库,请查看咸鱼,链接:

https://market.m.taobao.com/app/idleFish-F2e/widle-taobao-rax/page-detail?wh_weex=true&wx_navbar_transparent=true&id=602946990172&ut_sk=1.AAhiIP37iQwDANlHHj81FWR6_21407387_1568553369621.Copy.detail.602946990172.1030106470&forceFlush=1

若想要源代码,请查看咸鱼,链接:
https://market.m.taobao.com/app/idleFish-F2e/widle-taobao-rax/page-detail?wh_weex=true&wx_navbar_transparent=true&id=603142423586&ut_sk=1.AAhiIP37iQwDANlHHj81FWR6_21407387_1568553369621.Copy.detail.603142423586.1030106470&forceFlush=1

这篇文章的示例代码见咸鱼:

目录

1.Qt工程中添加opencv库

2.使用opencv库实现人脸识别​

3.图像的直方图分析

4.图像的形态学处理--腐蚀和膨胀操作

5.图像的线性滤波和非线性滤波

6.图像的二值化,边缘提取以及轮廓分析

7.使用多线程批量处理图片,加快图片处理速度

8.使用opencv库的注意事项

第一:图片转换

第二:图片的拷贝

第三:在Qt窗口中显示处理后的图片

第四:打包成exe文件时,对于程序调用的dll文件以及需要外部载入文件的打包

第五:点击窗口上的图片,会弹出一个放大版的图片



1.Qt工程中添加opencv库

本项目所用平台为:win10系统,Qtcreater4.8.0,Qt5.12.0,vs2015,opencv2.4.6

 第一步:下载opencv并编译,将编译好的文件放在某个固定路径下

编译好的文件中,最重要的内容就是:

版本对应关系如下:

第二步:新建Qt工程,并在pro文件中添加对opencv库的引用

若你的opencv版本不是2.4.6,可以照着下图的代码进行修改。

第三步:opencv库的使用

第四步:将opencv库的dll文件放到系统调用目录

注意,很多时候运行程序失败都是这个原因。调用opencv库必须使用dll文件,因此必须让你的程序能够找到这个dll。

2.使用opencv库实现人脸识别

这里的人脸识别使用的是级联分类器haarcascades,在机器学习算法中,通过对多个弱分类器的叠加可以实现一个强分类器。使用级联分类器,识别速度快,识别准确率也较高,非常适合于物体识别。本文用到的级联分类器是由opencv官方训练好的一个用于人脸识别的级联分类器,可以分别识别人的眼睛和鼻子以及其他人脸部位,分类器由一个xml文件保存,使用时导入即可。

首先,将图片灰度化,再直方图均衡化,增强图片对比度;

然后,载入用到的级联分类器模型;

最后,使用载入的分类器进行人脸(或者其他部位)识别,识别到的所有人脸(或者其他部位),都会被一个正方形框住。这些正方形组成一个数组,正方形有位置和面积大小,通过人为设置判断标准,可以将人脸可靠的检测出来。

Mat faceimage&#61;img.clone();//深层拷贝Mat image_gray;cvtColor(faceimage, image_gray, CV_BGR2GRAY); //转为灰度图equalizeHist(image_gray, image_gray); //直发图均化&#xff0c;增强对比度方便处理CascadeClassifier eye_Classifier; //载入分类器CascadeClassifier face_cascade; //载入分类器//加载分类训练器&#xff0c;OpenCV官方文档的xml文档&#xff0c;可以直接调用QString aFile &#61; QDir::currentPath() &#43; "/haarcascade_eye.xml";QString path &#61; QDir::toNativeSeparators(aFile);string eyefile &#61; path.toStdString();if (!eye_Classifier.load(eyefile)) //把xml文档复制到了当前项目的路径下{qDebug() <<"导入haarcascade_eye.xml时出错 !" < faces, eyes;face_cascade.detectMultiScale(image_gray, faces, 1.2, 5, 0, Size(30, 30));if (faces.size()>0) {for (size_t i &#61; 0; ishowimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();


3.图像的直方图分析

一张彩色图像的直方图分析包括&#xff1a;R分量&#xff0c;G分量&#xff0c;B分量和灰色分量的直方图分析

第一&#xff1a;各个分量的直方图分析

将一副图像的各个分量通道进行分离&#xff0c;然后进行直方图分析

Mat histimg;vector rgb_channel;split(img, rgb_channel);//将一幅多通道的图像的各个通道分离。Mat R&#61;rgb_channel[2];histimg&#61;getHistograph(R);processedimg&#61;histimg;//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(histimg.data), histimg.cols, histimg.rows, histimg.cols*histimg.channels(),QImage::Format_Grayscale8);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

第二&#xff1a;灰度直方图分析

灰度直方图分析就是将图片转换为灰度图&#xff0c;然后进行直方图分析

Mat hsv;//定义灰度图像&#xff0c;转成灰度图cvtColor(img,hsv,COLOR_BGR2GRAY);//直方图图像Mat hist&#61;getHistograph(hsv);processedimg&#61;hist;//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(hist.data), hist.cols, hist.rows, hist.cols*hist.channels(),QImage::Format_Grayscale8);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

第三&#xff1a;直方图分析的普遍算法

//直方图提取算法
Mat getHistograph(const Mat grayImage)
{//定义求直方图的通道数目&#xff0c;从0开始索引int channels[]&#61;{0};//定义直方图的在每一维上的大小&#xff0c;例如灰度图直方图的横坐标是图像的灰度值&#xff0c;就一维&#xff0c;bin的个数//如果直方图图像横坐标bin个数为x&#xff0c;纵坐标bin个数为y&#xff0c;则channels[]&#61;{1,2}其直方图应该为三维的&#xff0c;Z轴是每个bin上统计的数目const int histSize[]&#61;{256};//每一维bin的变化范围float range[]&#61;{0,256};//所有bin的变化范围&#xff0c;个数跟channels应该跟channels一致const float* ranges[]&#61;{range};//定义直方图&#xff0c;这里求的是直方图数据Mat hist;//opencv中计算直方图的函数&#xff0c;hist大小为256*1&#xff0c;每行存储的统计的该行对应的灰度值的个数calcHist(&grayImage,1,channels,Mat(),hist,1,histSize,ranges,true,false);//cv中是cvCalcHist//找出直方图统计的个数的最大值&#xff0c;用来作为直方图纵坐标的高double maxValue&#61;0;//找矩阵中最大最小值及对应索引的函数minMaxLoc(hist,0,&maxValue,0,0);//最大值取整int rows&#61;cvRound(maxValue);//定义直方图图像&#xff0c;直方图纵坐标的高作为行数&#xff0c;列数为256(灰度值的个数)//因为是直方图的图像&#xff0c;所以以黑白两色为区分&#xff0c;白色为直方图的图像Mat histImage&#61;Mat::zeros(rows,256,CV_8UC1);//直方图图像表示for(int i&#61;0;i<256;i&#43;&#43;){//取每个bin的数目int temp&#61;(int)(hist.at(i,0));//如果bin数目为0&#xff0c;则说明图像上没有该灰度值&#xff0c;则整列为黑色//如果图像上有该灰度值&#xff0c;则将该列对应个数的像素设为白色if(temp){//由于图像坐标是以左上角为原点&#xff0c;所以要进行变换&#xff0c;使直方图图像以左下角为坐标原点histImage.col(i).rowRange(Range(rows-temp,rows))&#61;255;}}//由于直方图图像列高可能很高&#xff0c;因此进行图像对列要进行对应的缩减&#xff0c;使直方图图像更直观Mat resizeImage;resize(histImage,resizeImage,Size(256,256));return resizeImage;
}

4.图像的形态学处理--腐蚀和膨胀操作

腐蚀和膨胀操作关键点是&#xff1a;内核参数的选取&#xff0c;这个是人为确定的。

腐蚀操作如下&#xff1a;

//获取内核形状和尺寸int m_KernelValue&#61;1;Mat element &#61; getStructuringElement(MORPH_RECT, Size(m_KernelValue * 2 &#43; 1, m_KernelValue * 2 &#43; 1), Point(m_KernelValue, m_KernelValue));//腐蚀操作Mat m_dstImage;erode(img, m_dstImage, element);processedimg&#61;m_dstImage.clone();cvtColor(processedimg,processedimg,CV_RGB2BGR);//Mat的图片是BGR格式&#xff0c;需要先转换为RGB格式//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(m_dstImage.data), m_dstImage.cols, m_dstImage.rows, m_dstImage.cols*m_dstImage.channels(),QImage::Format_RGB888);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

膨胀操作如下:

//获取内核形状和尺寸int m_KernelValue&#61;1;Mat element &#61; getStructuringElement(MORPH_RECT, Size(m_KernelValue * 2 &#43; 1, m_KernelValue * 2 &#43; 1), Point(m_KernelValue, m_KernelValue));//膨胀操作Mat m_dstImage;dilate(img, m_dstImage, element);processedimg&#61;m_dstImage.clone();cvtColor(processedimg,processedimg,CV_RGB2BGR);//Mat的图片是BGR格式&#xff0c;需要先转换为RGB格式//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(m_dstImage.data), m_dstImage.cols, m_dstImage.rows,m_dstImage.cols*m_dstImage.channels(), QImage::Format_RGB888);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

5.图像的线性滤波和非线性滤波

这里介绍图像的线性滤波&#xff1a;方框滤波&#xff0c;均值滤波和高斯滤波。以及图像的非线性滤波&#xff1a;中值滤波和双边滤波

方框滤波&#xff1a;滤波操作非常简单&#xff0c;重要的是滤波函数内的参数人为选取

//进行滤波操作Mat out;boxFilter(img, out, -1, Size(3, 3));//显示processedimg&#61;out.clone();cvtColor(processedimg,processedimg,CV_RGB2BGR);//Mat的图片是BGR格式&#xff0c;需要先转换为RGB格式//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(out.data), out.cols, out.rows,out.cols*out.channels(), QImage::Format_RGB888);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

均值滤波&#xff1a;

//进行滤波操作Mat out;blur(img,out,Size(7,7));processedimg&#61;out.clone();cvtColor(processedimg,processedimg,CV_RGB2BGR);//Mat的图片是BGR格式&#xff0c;需要先转换为RGB格式//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(out.data), out.cols, out.rows, out.cols*out.channels(),QImage::Format_RGB888);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

高斯滤波&#xff1a;

//进行滤波操作Mat out;GaussianBlur(img,out,Size(3,3),0,0);processedimg&#61;out.clone();cvtColor(processedimg,processedimg,CV_RGB2BGR);//Mat的图片是BGR格式&#xff0c;需要先转换为RGB格式//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(out.data), out.cols, out.rows, out.cols*out.channels(),QImage::Format_RGB888);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

中值滤波&#xff1a;

//进行中值滤波操作Mat out;medianBlur (img, out, 7);//输入&#xff0c;输出&#xff0c;7通道。其中参数3&#xff1a;孔径的线性尺寸&#xff0c;必须大于1.、必须为奇数&#xff0c;越大&#xff0c;滤布越强。processedimg&#61;out.clone();cvtColor(processedimg,processedimg,CV_RGB2BGR);//Mat的图片是BGR格式&#xff0c;需要先转换为RGB格式//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(out.data), out.cols, out.rows,out.cols*out.channels(), QImage::Format_RGB888);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

双边滤波&#xff1a;

//进行中值滤波操作Mat out;//双边滤波操作bilateralFilter(img, out, 25, 25 * 2, 25 / 2);processedimg&#61;out.clone();cvtColor(processedimg,processedimg,CV_RGB2BGR);//Mat的图片是BGR格式&#xff0c;需要先转换为RGB格式//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(out.data), out.cols, out.rows,out.cols*out.channels(), QImage::Format_RGB888);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

6.图像的二值化&#xff0c;边缘提取以及轮廓分析

图像的二值化需要先将彩色图转换为灰度图&#xff0c;由于灰度范围是0-256&#xff0c;因此二值化处理时的值不能越过这个范围。

图像边缘提取算法有&#xff1a;sobel算子&#xff0c;Laplacian算子&#xff0c;Canny算子。

轮廓分析使用findContours函数&#xff0c;找到的轮廓是有面积值的&#xff0c;可以据此进行轮廓筛选。

图像的二值化&#xff1a;

Mat biImage;cvtColor(img, biImage, CV_BGR2GRAY);//彩色图转换为灰度图cv::threshold(biImage,biImage,threshold,255, CV_THRESH_BINARY);//二值化处理processedimg&#61;biImage;//方便放大显示二值化处理后的图片//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(biImage.data), biImage.cols, biImage.rows,biImage.cols*biImage.channels(),QImage::Format_Indexed8);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

sobel算子边缘提取&#xff1a;

Mat hsv,edgeImg;//定义灰度图像&#xff0c;转成灰度图cvtColor(img,hsv,COLOR_BGR2GRAY);//Sobel边缘检测Mat x_edgeImg, y_edgeImg;Mat abs_x_edgeImg, abs_y_edgeImg;/*****先对x方向进行边缘检测********///因为Sobel求出来的结果有正负&#xff0c;8位无符号表示不全&#xff0c;故用16位有符号表示Sobel(hsv,x_edgeImg, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);convertScaleAbs(x_edgeImg, abs_x_edgeImg);//将16位有符号转化为8位无符号/*****再对y方向进行边缘检测********/Sobel(hsv, y_edgeImg, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);convertScaleAbs(y_edgeImg, abs_y_edgeImg);addWeighted(abs_x_edgeImg, 0.5, abs_y_edgeImg, 0.5, 0, edgeImg);processedimg&#61;edgeImg;//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(edgeImg.data), edgeImg.cols, edgeImg.rows, edgeImg.cols*edgeImg.channels(),QImage::Format_Grayscale8);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

Laplacian算子边缘提取&#xff1a;

Mat hsv,edgeImg;//定义灰度图像&#xff0c;转成灰度图cvtColor(img,hsv,COLOR_BGR2GRAY);//Laplacian边缘检测Mat lapImg;Laplacian(hsv, lapImg, CV_16S, 5, 1, 0, BORDER_DEFAULT);convertScaleAbs(lapImg, edgeImg);processedimg&#61;edgeImg;//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(edgeImg.data), edgeImg.cols, edgeImg.rows, edgeImg.cols*edgeImg.channels(),QImage::Format_Grayscale8);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

Canny算子边缘提取&#xff1a;

Mat hsv,edgeImg;//定义灰度图像&#xff0c;转成灰度图cvtColor(img,hsv,COLOR_BGR2GRAY);//Canny边缘检测Canny(hsv, edgeImg, 30, 80);processedimg&#61;edgeImg;//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(edgeImg.data), edgeImg.cols, edgeImg.rows, edgeImg.cols*edgeImg.channels(),QImage::Format_Grayscale8);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

轮廓分析&#xff1a;

contoursize数组中contoursize[i]就是轮廓i的面积。

Mat hsv;//定义灰度图像&#xff0c;转成灰度图cvtColor(img,hsv,COLOR_BGR2GRAY);Mat contImg &#61; Mat ::zeros(hsv.size(),CV_8UC3);//定义三通道轮廓提取图像Mat binImg;cv::threshold(hsv, binImg, 127, 255, THRESH_OTSU);//大津法进行图像二值化vector> contours;vector hierarchy;//查找轮廓findContours(binImg, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);//绘制查找到的轮廓drawContours(contImg, contours, -1, Scalar(0,255,0));contoursize.clear();contoursize.resize(1);//重置轮廓面积变量的大小// qDebug()<contour->addItem(QString::number(i&#43;1));double temp&#61;contourArea(contours[i]);contoursize.push_back(temp);}ui->num->setText(QString::number(contours.size()));ui->size->setText(QString::number(contourArea(contours[0])));processedimg&#61;contImg;//在窗口控件中显示图片QImage Qtemp2 &#61; QImage((const unsigned char*)(contImg.data), contImg.cols, contImg.rows, contImg.cols*contImg.channels(),QImage::Format_RGB888);QPixmap pixmap2 &#61; QPixmap::fromImage(Qtemp2);int with &#61; ui->showimage->width();int height &#61; ui->showimage->height();QPixmap fitpixmap2 &#61; pixmap2.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 按比例缩放ui->showimage->setPixmap(fitpixmap2);ui->showimage->show();

7.使用多线程批量处理图片&#xff0c;加快图片处理速度

我们知道&#xff0c;将图片从硬盘中读取是一个费时的操作&#xff0c;远远高于图片处理的耗时。因此通过多线程的方式&#xff0c;我们就可以在处理图片的同时&#xff0c;导入后续图片到内存中。需要注意的是&#xff0c;需要采用线程锁的方式&#xff0c;避免多个线程处理同一张图片。

第一&#xff1a;获取图片所在文件夹中所有图片的名称以及总的图片数量值&#xff1b;

第二&#xff1a;对已经在处理中的图片编号进行计数&#xff0c;使用线程锁避免该计数值被多个线程同时改变。

第三&#xff0c;由于线程锁机制&#xff0c;每个线程都会顺序分配一张其可以处理的图片编号&#xff0c;只需对该图片进行处理。

第四&#xff0c;加入判断语句&#xff0c;当正在处理的图片编号达到或超过总的图片数量值时&#xff0c;结束当前线程。

void WorkThread::dataprocessing(void)
{while(1){//线程一进入先判断是否图像已经处理完毕&#xff0c;如果完毕记录从开始至该线程结束所用的时间if(currentimagenum>&#61;allImageNameList.count()){overtime&#61;codetime.elapsed()/1000.0;emit time_over();//发送批量处理图片花费的时间到主UI所在的线程进行显示//结束当前线程this->terminate();this->wait();break;}//给需要保护的变量currentimagenum加锁&#xff0c;防止多线程时对同一图片进行处理QMutex mutex;mutex.lock();int num&#61;currentimagenum;currentimagenum&#43;&#43;;mutex.unlock();//载入需要处理的图片QString filename&#61;imageprocessing_filename&#43;"/"&#43;(allImageNameList[num]);Mat img;std::string srcpath &#61; filename.toLocal8Bit().toStdString(); //解决中文路径问题img &#61; cv::imread(srcpath);//加载并图片&#xff0c;延时2后自动关闭窗口Mat biImage;// 转换为灰度图if (img.channels() &#61;&#61; 4) {cv::cvtColor(img, biImage, CV_BGRA2GRAY);} else if (img.channels() &#61;&#61; 3) {cv::cvtColor(img, biImage, CV_BGR2GRAY);} else if(img.channels() &#61;&#61; 2) {cv::cvtColor(img,biImage,CV_BGR5652GRAY);} else if(img.channels() &#61;&#61; 1) {// 单通道的图片直接就不需要处理} else { // 负数,说明图有问题 直接返回}//保存处理后的图片QImage Qtemp2 &#61; QImage((const unsigned char*)(biImage.data), biImage.cols, biImage.rows,biImage.cols*biImage.channels(),QImage::Format_Grayscale8);QString savefile&#61;imageprocessing_filename;savefile.append("/output/");QDir *photo &#61; new QDir;if(!photo->exists(savefile)){//创建output文件夹photo->mkdir(savefile);}savefile.append(QString::number(num)&#43;".jpg");QString path &#61; QDir::toNativeSeparators(savefile);//将路径转换为当前系统所定义的路径Qtemp2.save(path,"JPG", 100);savefile.clear();filename.clear();}
}

8.使用opencv库的注意事项

第一&#xff1a;图片格式转换

1.opencv库处理的图片格式是BGR格式的&#xff0c;当Qt窗口需要显示时要转换为RGB格式&#xff0c;否则会有运行问题。

2.彩色图片一般选用RGB888格式&#xff0c;灰色图片一般选用Indexed8格式

3.同理&#xff0c;当需要使用opencv库处理图片时&#xff0c;需要将原本是RGB格式的图片转换为BGR格式。

第二&#xff1a;图片的拷贝

图片的强制拷贝使用clone函数&#xff0c;避免对拷贝图片处理时影响原图片。

第三&#xff1a;在Qt窗口中显示处理后的图片

使用Qlabel控件作为图片显示的载体。

再将Mat格式的图片转换为QImage格式。

最后将QImage转换为QPixmap进行缩放显示。

注意&#xff1a;Mat格式的图片转换为QImage格式时&#xff0c;对于灰度图和彩色图是不同的。通过channels()函数进行区分。

第四&#xff1a;打包成exe文件时&#xff0c;对于程序调用的dll文件以及需要外部载入文件的打包

将dll文件直接放在打包目录里。

需要外部载入的文件&#xff0c;通过相对路径进行调用&#xff0c;打包时同样放在打包目录里。

这样这些文件都会包含在打包的exe文件中&#xff0c;不会造成缺少文件的情况。

第五&#xff1a;点击窗口上的图片&#xff0c;会弹出一个放大版的图片

只需要在Qlabel控件上覆盖一个按钮控件&#xff0c;按钮控件设为透明。则可以通过响应按钮点击事件弹出一个放大的图片。

 

 


推荐阅读
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 深入理解Java泛型:JDK 5的新特性
    本文详细介绍了Java泛型的概念及其在JDK 5中的应用,通过具体代码示例解释了泛型的引入、作用和优势。同时,探讨了泛型类、泛型方法和泛型接口的实现,并深入讲解了通配符的使用。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • 本文介绍如何在Java项目中使用Log4j库进行日志记录。我们将详细说明Log4j库的引入、配置及简单应用,帮助开发者快速上手。 ... [详细]
  • 深入探讨CPU虚拟化与KVM内存管理
    本文详细介绍了现代服务器架构中的CPU虚拟化技术,包括SMP、NUMA和MPP三种多处理器结构,并深入探讨了KVM的内存虚拟化机制。通过对比不同架构的特点和应用场景,帮助读者理解如何选择最适合的架构以优化性能。 ... [详细]
  • 在过去两周中,我们利用 ReportViewer 开发了与生产良率相关的报表,其中每个制程的直通率是所有测试项良率的乘积。由于 ReportViewer 没有内置的累乘函数,因此需要借助自定义代码来实现这一功能。本文将详细介绍实现步骤和相关代码。 ... [详细]
  • 本文总结了Java程序设计第一周的学习内容,涵盖语言基础、编译解释过程及基本数据类型等核心知识点。 ... [详细]
  • 作者:守望者1028链接:https:www.nowcoder.comdiscuss55353来源:牛客网面试高频题:校招过程中参考过牛客诸位大佬的面经,但是具体哪一块是参考谁的我 ... [详细]
  • PyCharm下载与安装指南
    本文详细介绍如何从官方渠道下载并安装PyCharm集成开发环境(IDE),涵盖Windows、macOS和Linux系统,同时提供详细的安装步骤及配置建议。 ... [详细]
author-avatar
戴乐季206
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有