OpenCV C++案例实战十九《制作电子相册查看器》

OpenCV C++案例实战十九《制作电子相册查看器》


前言

本文将使用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、使用键盘响应事件控制相片上下读取

            • 0
              点赞
            • 0
              收藏
              觉得还不错? 一键收藏
            • 0
              评论
            评论
            添加红包

            请填写红包祝福语或标题

            红包个数最小为10个

            红包金额最低5元

            当前余额3.43前往充值 >
            需支付:10.00
            成就一亿技术人!
            领取后你会自动成为博主和红包主的粉丝 规则
            hope_wisdom
            发出的红包
            实付
            使用余额支付
            点击重新获取
            扫码支付
            钱包余额 0

            抵扣说明:

            1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
            2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

            余额充值