基于C++ OpenCV制作电子相册查看器

 更新时间:2022年01月17日 08:28:58   作者:Zero___Chen  
这篇文章主要介绍了如何使用OpenCV C++ 制作电子相册查看器。类似于win10系统的“照片”功能。感兴趣的小伙伴可以跟随小编一起学习一下

前言

本文将使用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电子相册查看器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 实例讲解在C++的函数中变量参数及默认参数的使用

    实例讲解在C++的函数中变量参数及默认参数的使用

    这篇文章主要介绍了在C++的函数中变量参数及默认参数的使用,是C++函数入门学习中的基础知识,需要的朋友可以参考下
    2016-01-01
  • C/C++经典实例之模拟计算器示例代码

    C/C++经典实例之模拟计算器示例代码

    最近在看到的一个需求,本以为比较简单,但花了不少时间,所以下面这篇文章主要给大家介绍了关于C/C++经典实例之模拟计算器的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-10-10
  • 如何应用C++的函数对象

    如何应用C++的函数对象

    C++函数对象是C语言程序的主要组成部分,一个函数可以调用其他函数。在设计良好的程序中,每个函数都有特定的目的。本文将介绍C++函数对象的应用,有需要的可以参考学习。
    2016-08-08
  • Qt实现简易计时器的示例代码

    Qt实现简易计时器的示例代码

    计时器实现四个功能:开始计时、停止计时、暂停计时以及打点。当点击暂停时,开始按钮和停止按钮无法点击。当点击停止时,开始按钮和暂停按钮无法点击,此时停止按钮变为清零。本文将用Qt实现这样的一个计时器,需要的可以参考一下
    2022-06-06
  • 在Visual Studio中配置C++最新版netCDF库的方法

    在Visual Studio中配置C++最新版netCDF库的方法

    本文介绍在Windows电脑的Visual Studio软件中,配置C++ 语言最新版netCDF库的方法,文中通过图文结合的形式介绍的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2024-03-03
  • OpenCV实现马赛克功能

    OpenCV实现马赛克功能

    这篇文章主要为大家详细介绍了OpenCV实现马赛克功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • 详解C++字符串常用操作函数(查找、插入、截取、删除等)

    详解C++字符串常用操作函数(查找、插入、截取、删除等)

    这篇文章主要介绍了C++字符串常用操作函数(查找、插入、截取、删除等),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • IOS 开发UITextView回收或关闭键盘

    IOS 开发UITextView回收或关闭键盘

    这篇文章主要介绍了IOS 开发UITextView回收或关闭键盘的相关资料,需要的朋友可以参考下
    2017-06-06
  • opencv实现定时录像功能

    opencv实现定时录像功能

    这篇文章主要为大家详细介绍了opencv实现定时录像功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • C++数据结构之哈希算法详解

    C++数据结构之哈希算法详解

    这篇文章主要为大家详细介绍了C++数据结构中哈希算法的相关资料,文中的示例代码讲解详细,具有一定的借鉴价值,希望对大家有所帮助
    2022-12-12

最新评论