热门标签 | 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 网站开发的相关资源和步骤,包括常用网站、开发环境和框架选择。 ... [详细]
  • 阿里巴巴终面技术挑战:如何利用 UDP 实现 TCP 功能?
    在阿里巴巴的技术面试中,技术总监曾提出一道关于如何利用 UDP 实现 TCP 功能的问题。当时回答得不够理想,因此事后进行了详细总结。通过与总监的进一步交流,了解到这是一道常见的阿里面试题。面试官的主要目的是考察应聘者对 UDP 和 TCP 在原理上的差异的理解,以及如何通过 UDP 实现类似 TCP 的可靠传输机制。 ... [详细]
  • 在 Linux 环境下,多线程编程是实现高效并发处理的重要技术。本文通过具体的实战案例,详细分析了多线程编程的关键技术和常见问题。文章首先介绍了多线程的基本概念和创建方法,然后通过实例代码展示了如何使用 pthreads 库进行线程同步和通信。此外,还探讨了多线程程序中的性能优化技巧和调试方法,为开发者提供了宝贵的实践经验。 ... [详细]
  • 本文详细介绍了如何在PHP中记录和管理行为日志,包括ThinkPHP框架中的日志记录方法、日志的用途、实现原理以及相关配置。 ... [详细]
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • 三角测量计算三维坐标的代码_双目三维重建——层次化重建思考
    双目三维重建——层次化重建思考FesianXu2020.7.22atANTFINANCIALintern前言本文是笔者阅读[1]第10章内容的笔记,本文从宏观的角度阐 ... [详细]
  • 安装 IIS 5.1 并注册 .NET 2.0 后,访问页面时出现 500 错误。本文提供详细的步骤和解决方案,帮助您解决该问题。 ... [详细]
  • Ihavetwomethodsofgeneratingmdistinctrandomnumbersintherange[0..n-1]我有两种方法在范围[0.n-1]中生 ... [详细]
  • 对于众多创业公司而言,选择小程序或小视频的发展方向至关重要。本文将深入分析小程序和小视频的特点、优势及局限,帮助创业者做出更明智的选择。 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 重要知识点有:函数参数默许值、盈余参数、扩大运算符、new.target属性、块级函数、箭头函数以及尾挪用优化《深切明白ES6》笔记目次函数的默许参数在ES5中,我们给函数传参数, ... [详细]
  • 在嵌入式Linux系统中,性能低下通常由CPU、内存和I/O三个关键因素引起。为了有效提升系统性能,首先需要识别并定位性能瓶颈。通过综合分析这些瓶颈,可以采取针对性的优化措施,如调整内核参数、优化算法和改进数据结构等,从而显著提高系统的整体性能。 ... [详细]
  • 本文总结了JavaScript的核心知识点和实用技巧,涵盖了变量声明、DOM操作、事件处理等重要方面。例如,通过`event.srcElement`获取触发事件的元素,并使用`alert`显示其HTML结构;利用`innerText`和`innerHTML`属性分别设置和获取文本内容及HTML内容。此外,还介绍了如何在表单中动态生成和操作``元素,以便更好地处理用户输入。这些技巧对于提升前端开发效率和代码质量具有重要意义。 ... [详细]
  • 在C#中开发多线程应用程序变得高效且简便,与之前使用VB时的复杂性和局限性形成鲜明对比。C#不仅提供了丰富的多线程编程模型,还简化了线程管理、同步和通信等关键任务,使得开发者能够更加轻松地构建高性能的应用程序。此外,C#的异步编程特性进一步增强了多线程应用的开发效率和可维护性。 ... [详细]
  • 在Spring与Ibatis集成的环境中,通过Spring AOP配置事务管理至服务层。当在一个服务方法中引入自定义多线程时,发现事务管理功能失效。若不使用多线程,事务管理则能正常工作。本文深入分析了这一现象背后的潜在风险,并探讨了可能的解决方案,以确保事务一致性和线程安全。 ... [详细]
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社区 版权所有