项目结项:数字相册
时间:10-02
整理:3721RD
点击:
综述
本次试用的项目实现了读取home分区下所有图片并按一定顺序将图片显示,切换图片间实现了左右切换、淡入淡出和百叶窗,通过2个按钮选择切换到上一张还是下一张,还对当前图像进行处理,实现增强对比度、亮度改变以及腐蚀膨胀,效果如下所示:
410c试用效果.rar(6.11 MB, 下载次数: 8)
2016-10-13 18:56 上传
点击文件名下载附件http://v.youku.com/v_show/id_XMTc3NjM0MzU4MA==.html
源码地址:https://github.com/agdhun/DigitalPhotoFrame
第一部分:路径读取与图片显示
我们通过QT与OpenCV结合,OpenCV实现图片切换和处理效果,而QT则负责读取文件路径和显示图片、控制程序启动与退出功能,如下图所示:
对于路径读取,将目录转QDir类的一个实例,再定义QStringList的实例,通过迭代器把图片路径保存起来,实现代码如下:
- QDir dir(path);
- if(!dir.exists())
- {
- return;
- }
- QStringList filters;
- filters<<QString("*.jpeg")<<QString("*.jpg")<<QString("*.png")<<QString("*.tiff")<<QString("*.gif")<<QString("*.bmp");
- QDirIterator dir_iterator(path,
- filters,
- QDir::Files | QDir::NoSymLinks,
- QDirIterator::Subdirectories);
- while(dir_iterator.hasNext())
- {
- dir_iterator.next();
- QFileInfo file_info = dir_iterator.fileInfo();
- QString file_path = file_info.absoluteFilePath();
- string_list.append(file_path);
- qDebug() << file_path;
- }
qDebug函数是打印输出信息,有如ARM的串口,Linux的Terminal等;
获得路径后我们就要把第一幅图片显示在QT的label上,我们需要先利用opencv的读取图片函数来将图片的信息读取保存到Mat结构中,虽然OpenCV也提供对图片显示的支持,但OpenCV对于界面也仅仅提供Window、Slider等基本功能,操作并不是很方便,而QT则是为显示而生,把OpenCV的图片数据显示到QT上,首先需要考虑OpenCV的数据格式与QT并不一样,OpenCV是以BGR排列,而QT是用GRB排列,需要用到OpenCV的图像数据转换函数,其原型如下:
CV_EXPORTS_W void cvtColor( InputArray src, OutputArray dst, int code, int dstCn=0 );
其需要提供至少三个参数,分别是:
Src:原图片数据;
Dst:目标图片数据;
Code:转换形式;
对于code,OpenCv提供了135种转换,常用于QT显示也就是CV_BGR2GRB;
得到转换后的数据后,我们就需要将图片显示在QT程序上,使用QImage进行数据转换,再将其显示到QT的label控件上,其中需要注意的是,对于图像数据要考虑到其通道数,否则会出现图片扭曲现象,使用如下代码便可消除:
- if(disp.channels() == 3)
- {
- cvtColor(disp, rgb, CV_BGR2RGB);
- img = QImage((const unsigned char*)(rgb.data), rgb.cols, rgb.rows, rgb.cols*rgb.channels(), QImage::Format_RGB888);
- }else
- {
- rgb = disp;
- img = QImage((const unsigned char*)(rgb.data), rgb.cols, rgb.rows, rgb.cols*rgb.channels(), QImage::Format_Indexed8);
- }
接着通过label控件的setPixmap方法将图片显示。
第二部分:QT控件使用
在QTcreator里可以使用设计师来设计ui文件,最后用c文件导入就可以,优点是简化了代码编写,所见即所得,当然也有缺点,多Ui间不能很好处理,与代码交互性并不是很好,控件方位修改不太灵活。
设计师提供了多种按钮,有单选按钮RadioButton、普通按钮PushButton等,如下所示:
此例中,我们只需要用到Push Button和Radio Button,Push Button,即按下就会有信号,即clicked()信号,当然需要有相应的槽来接收,其实也可以不用槽信号接收,直接对此按钮进行信号重载,使用右键,Go to slot…,即可在相应的C文件产生私有的槽,此槽有缺点就是仅仅只用于该信号,这样就无需要在填充connect代码:
其他类似,我们还需要用到滑动条slider,同理可以用如上方法填充槽,好处是不用记住相应控件的系统槽函数,它们给你提供,缺点也有,当信号不是系统提供的,需要自己添加;
对于slider,使用如上方法,signal需要选择valueChanged(int),而不能使用sliderMoved(int)或sliderPressed()或sliderReleased(),因为它们只能响应slider滑动或是点击的其中一种行为,并不能很好处理只要滑块移动就处理,当然也可以通过属性栏控制不能滑动或是单击,这样只需要处理其中一种情况,其他的用户操作无法实现滑块滑动。Label控件使用很简单,拖入即可,控制好范围即可。
第三部分:图片切换效果
此处我们使用OpenCV处理图片,从读取图片后,我们需要对图片进行裁剪,方可让图片在label上大小完美的显示,我们使用cv::resize函数,原型如下:
- CV_EXPORTS_W void resize( InputArray src, OutputArray dst,
- Size dsize, double fx=0, double fy=0,
- int interpolation=INTER_LINEAR );
提供输入图像的矩阵和输出图像矩阵变量,再提供输出矩阵大小就可以了,无特效处理很简单,一旦出现转换到下一页,我们直接让程序控制label显示第二幅图片,由于速度极快,相对于肉眼,就像连续过去;对于从左到右,我们需要让图片依次平移,当前图片像左平移,新图像从0列开始依次向左展开,并稍加延时,让肉眼能感知这种变化,也即成了效果:
同理,淡入淡出也是类似实现,我们使用cv::addWeighted函数,其原型如下:
- CV_EXPORTS_W void addWeighted(InputArray src1, double alpha, InputArray src2,
- double beta, double gamma, OutputArray dst, int dtype=-1);
也就是实现dst = alpha*src1 + beta*src2 + gamma这个公式,此处不详细探讨;
最后一个效果,百叶窗,大致思路是,将一副整图分割成n份,每一份都单独实现从左到右的效果。
第四部分:图片处理效果
对于图片处理效果,我实现了对比度调整、亮度调整、腐蚀膨胀调整,使用四个滑动条控制其中相应数据改变的触发,对比度调整使用之前的addWeighted函数,对比度也就是对每个像素同时放大或缩小N倍,而亮度则是加上在-255到+255范围的数值,腐蚀膨胀则是用erode和dilate函数。