基於C++ OpenCV制作電子相冊查看器

前言

本文將使用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電子相冊查看器內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: