前言
本文将使用OpenCV C++ 制作电子相册查看器。类似于win10系统的“照片”功能。接下来就具体来看看是如何一步步的实现吧。
一、图片读取
我们想要一张张的查看文件夹下的图片,第一步就得读取将该文件夹下的所有图片。

如上图所示,为我创建的文件夹,该文件夹下有14张图片。接下来我们就编写代码读取该文件夹下的所有图片。将读取到的图片存储在images容器。
- //读取文件夹下所有图片
- string filename = "images";
- vector<string>imageList;
- glob(filename, imageList);
- vector<Mat>images;
- for (int i = 0; i < imageList.size(); i++)
- {
- Mat img = imread(imageList[i]);
- images.push_back(img);
- }
现在我们已经有了images容器,其实再使用一个for循环就能够一张张读取容器里的图片了。不过这样只能一张张往下读取,直到读取完最后一张图片程序结束。本案例的需求是使用键盘按键“->”向后读取,“<-”向前读取。
二、图片展示
我们需要一张白色的画布用来放置图片。为了将所有图片都居中在画布中显示,令画布中心为(cx,cy),当前图片宽width,高height。则该图片相对于画布起点为(x,y)。如下图所示。

- //将每一张照片放置画布中心
- int x = cx - (width / 2);
- int y = cy - (height / 2);
- //将照片抠图到画布上,此时照片位于画布中心位置
- images[index].copyTo(bg(Rect(x, y, width, height)));
在这里,使用一个判断语句,判断当前图片尺寸是否大于画布尺寸。如果当前图片尺寸大于画布尺寸,则将图片自适应剪切。否则的话,会造成内存溢出。
- //如果图片过大,则对其进行裁剪
- if (width > canvas.cols || height > canvas.rows)
- {
- //进行自适应剪切,每次只在原基础上剪切百分之八十
- while (true)
- {
- resize(images[index], images[index], Size(0, 0), 0.8, 0.8, INTER_LINEAR);
- if (images[index].cols < canvas.cols&&images[index].rows < canvas.rows)
- {
- break;
- }
- }
- width = images[index].cols;
- height = images[index].rows;
- }
三、键盘控制
根据上述代码我们已经可以将图片显示在画布中心了,接下来就需要使用键盘响应事件控制图片查看。
我们使用方向键“->”控制向下查看,“<-”控制向上查看。具体请看源码注释。
- if (key == 2424832)
- {
- //如果按动键盘‘←'键,则向前查看相片
- if (index > 0)//如果图片不是图库中第一张,则允许向前查看
- {
- cout << "←" << endl;
- index--;
- }
- }
- else if (key == 2555904)
- {
- //如果按动键盘‘→'键,则向后查看相片
- if (index < size-1)//如果图片不是图库中最后一张,则允许向后查看
- {
- cout << "→" << endl;
- index++;
- }
- }
- //如果按动键盘‘ESC'键,则退出程序
- else if (key == 27)
- {
- break;
- }
四、效果显示

如上图所示,至此我们已经完成了案例所想要的效果。请参考源码,注释也比较详细了。
五、源码
- #include<iostream>
- #include<opencv2/opencv.hpp>
- using namespace std;
- using namespace cv;
-
- int main()
- {
- ?? ?//读取文件夹下所有图片
- ?? ?string filename = "images";
- ?? ?vector<string>imageList;
- ?? ?glob(filename, imageList);
- ?? ?vector<Mat>images;
- ?? ?for (int i = 0; i < imageList.size(); i++)
- ?? ?{
- ?? ??? ?Mat img = imread(imageList[i]);
- ?? ??? ?images.push_back(img);
- ?? ?}
-
- ?? ?//创建画布,用于放置相片
- ?? ?Mat canvas = Mat(Size(1400, 900), CV_8UC3, Scalar::all(255));
- ?? ?//画布中心
- ?? ?int cx = canvas.cols / 2;
- ?? ?int cy = canvas.rows / 2;
- ?? ?
- ?? ?int size = images.size();//图库中相片数量
- ?? ?int index = 0; //当前图库中相片索引
- ?? ?
- ?? ?while (true)
- ?? ?{
- ?? ??? ?//waitKey无法正常捕捉方向键(上下左右),故使用waitKeyEx
- ?? ??? ?int key = waitKeyEx(0);
-
- ?? ??? ?if (key == 2424832)
- ?? ??? ?{
- ?? ??? ??? ?//如果按动键盘‘←'键,则向前查看相片
- ?? ??? ??? ?if (index > 0)//如果图片不是图库中第一张,则允许向前查看
- ?? ??? ??? ?{
- ?? ??? ??? ??? ?cout << "←" << endl;
- ?? ??? ??? ??? ?index--;
- ?? ??? ??? ?}
- ?? ??? ?}
- ?? ??? ?else if (key == 2555904)
- ?? ??? ?{
- ?? ??? ??? ?//如果按动键盘‘→'键,则向后查看相片
- ?? ??? ??? ?if (index < size-1)//如果图片不是图库中最后一张,则允许向后查看
- ?? ??? ??? ?{
- ?? ??? ??? ??? ?cout << "→" << endl;
- ?? ??? ??? ??? ?index++;
- ?? ??? ??? ?}
- ?? ??? ?}
- ?? ??? ?//如果按动键盘‘ESC'键,则退出程序
- ?? ??? ?else if (key == 27)
- ?? ??? ?{
- ?? ??? ??? ?break;
- ?? ??? ?}
-
- ?? ??? ?//将画布拷贝一份,每经一次循环,更新一次图片。
- ?? ??? ?Mat bg = canvas.clone();
-
- ?? ??? ?//计算每一张图片的宽高
- ?? ??? ?int width = images[index].cols;
- ?? ??? ?int height = images[index].rows;
-
- ?? ??? ?//如果图片过大,则对其进行裁剪
- ?? ??? ?if (width > canvas.cols || height > canvas.rows)
- ?? ??? ?{
- ?? ??? ??? ?//进行自适应剪切,每次只在原基础上剪切百分之八十
- ?? ??? ??? ?while (true)
- ?? ??? ??? ?{
- ?? ??? ??? ??? ?resize(images[index], images[index], Size(0, 0), 0.8, 0.8, INTER_LINEAR);
- ?? ??? ??? ??? ?if (images[index].cols < canvas.cols&&images[index].rows < canvas.rows)
- ?? ??? ??? ??? ?{
- ?? ??? ??? ??? ??? ?break;
- ?? ??? ??? ??? ?}
- ?? ??? ??? ?}?? ?
- ?? ??? ??? ?width = images[index].cols;
- ?? ??? ??? ?height = images[index].rows;
- ?? ??? ?}
-
- ?? ??? ?//将每一张照片放置画布中心
- ?? ??? ?int x = cx - (width / 2);
- ?? ??? ?int y = cy - (height / 2);
- ?? ??? ?//将照片抠图到画布上,此时照片位于画布中心位置
- ?? ??? ?images[index].copyTo(bg(Rect(x, y, width, height)));
-
- ?? ??? ?imshow("Demo", bg);
- ?? ?}
-
- ?? ?destroyAllWindows();
- ?? ?system("pause");
- ?? ?return 0;
- }
总结
本文使用OpenCV C++ 制作电子相册查看器,类似win10系统下的“照片”功能,关键步骤有以下几点。
1、图片在画布上居中显示
2、使用键盘响应事件控制相片上下读取
到此这篇关于基于C++ OpenCV制作电子相册查看器的文章就介绍到这了,更多相关C++ OpenCV电子相册查看器内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!