基于C++ OpenCV制作電子相冊(cè)查看器
前言
本文將使用OpenCV C++ 制作電子相冊(cè)查看器。類似于win10系統(tǒng)的“照片”功能。接下來(lái)就具體來(lái)看看是如何一步步的實(shí)現(xiàn)吧。
一、圖片讀取
我們想要一張張的查看文件夾下的圖片,第一步就得讀取將該文件夾下的所有圖片。
如上圖所示,為我創(chuàng)建的文件夾,該文件夾下有14張圖片。接下來(lái)我們就編寫代碼讀取該文件夾下的所有圖片。將讀取到的圖片存儲(chǔ)在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); }
現(xiàn)在我們已經(jīng)有了images容器,其實(shí)再使用一個(gè)for循環(huán)就能夠一張張讀取容器里的圖片了。不過(guò)這樣只能一張張往下讀取,直到讀取完最后一張圖片程序結(jié)束。本案例的需求是使用鍵盤按鍵“->”向后讀取,“<-”向前讀取。
二、圖片展示
我們需要一張白色的畫布用來(lái)放置圖片。為了將所有圖片都居中在畫布中顯示,令畫布中心為(cx,cy),當(dāng)前圖片寬width,高h(yuǎn)eight。則該圖片相對(duì)于畫布起點(diǎn)為(x,y)。如下圖所示。
//將每一張照片放置畫布中心 int x = cx - (width / 2); int y = cy - (height / 2); //將照片摳圖到畫布上,此時(shí)照片位于畫布中心位置 images[index].copyTo(bg(Rect(x, y, width, height)));
在這里,使用一個(gè)判斷語(yǔ)句,判斷當(dāng)前圖片尺寸是否大于畫布尺寸。如果當(dāng)前圖片尺寸大于畫布尺寸,則將圖片自適應(yīng)剪切。否則的話,會(huì)造成內(nèi)存溢出。
//如果圖片過(guò)大,則對(duì)其進(jìn)行裁剪 if (width > canvas.cols || height > canvas.rows) { //進(jìn)行自適應(yīng)剪切,每次只在原基礎(chǔ)上剪切百分之八十 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; }
三、鍵盤控制
根據(jù)上述代碼我們已經(jīng)可以將圖片顯示在畫布中心了,接下來(lái)就需要使用鍵盤響應(yīng)事件控制圖片查看。
我們使用方向鍵“->”控制向下查看,“<-”控制向上查看。具體請(qǐng)看源碼注釋。
if (key == 2424832) { //如果按動(dòng)鍵盤‘←'鍵,則向前查看相片 if (index > 0)//如果圖片不是圖庫(kù)中第一張,則允許向前查看 { cout << "←" << endl; index--; } } else if (key == 2555904) { //如果按動(dòng)鍵盤‘→'鍵,則向后查看相片 if (index < size-1)//如果圖片不是圖庫(kù)中最后一張,則允許向后查看 { cout << "→" << endl; index++; } } //如果按動(dòng)鍵盤‘ESC'鍵,則退出程序 else if (key == 27) { break; }
四、效果顯示
如上圖所示,至此我們已經(jīng)完成了案例所想要的效果。請(qǐng)參考源碼,注釋也比較詳細(xì)了。
五、源碼
#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); ?? ?} ?? ?//創(chuàng)建畫布,用于放置相片 ?? ?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();//圖庫(kù)中相片數(shù)量 ?? ?int index = 0; //當(dāng)前圖庫(kù)中相片索引 ?? ? ?? ?while (true) ?? ?{ ?? ??? ?//waitKey無(wú)法正常捕捉方向鍵(上下左右),故使用waitKeyEx ?? ??? ?int key = waitKeyEx(0); ?? ??? ?if (key == 2424832) ?? ??? ?{ ?? ??? ??? ?//如果按動(dòng)鍵盤‘←'鍵,則向前查看相片 ?? ??? ??? ?if (index > 0)//如果圖片不是圖庫(kù)中第一張,則允許向前查看 ?? ??? ??? ?{ ?? ??? ??? ??? ?cout << "←" << endl; ?? ??? ??? ??? ?index--; ?? ??? ??? ?} ?? ??? ?} ?? ??? ?else if (key == 2555904) ?? ??? ?{ ?? ??? ??? ?//如果按動(dòng)鍵盤‘→'鍵,則向后查看相片 ?? ??? ??? ?if (index < size-1)//如果圖片不是圖庫(kù)中最后一張,則允許向后查看 ?? ??? ??? ?{ ?? ??? ??? ??? ?cout << "→" << endl; ?? ??? ??? ??? ?index++; ?? ??? ??? ?} ?? ??? ?} ?? ??? ?//如果按動(dòng)鍵盤‘ESC'鍵,則退出程序 ?? ??? ?else if (key == 27) ?? ??? ?{ ?? ??? ??? ?break; ?? ??? ?} ?? ??? ?//將畫布拷貝一份,每經(jīng)一次循環(huán),更新一次圖片。 ?? ??? ?Mat bg = canvas.clone(); ?? ??? ?//計(jì)算每一張圖片的寬高 ?? ??? ?int width = images[index].cols; ?? ??? ?int height = images[index].rows; ?? ??? ?//如果圖片過(guò)大,則對(duì)其進(jìn)行裁剪 ?? ??? ?if (width > canvas.cols || height > canvas.rows) ?? ??? ?{ ?? ??? ??? ?//進(jìn)行自適應(yīng)剪切,每次只在原基礎(chǔ)上剪切百分之八十 ?? ??? ??? ?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); ?? ??? ?//將照片摳圖到畫布上,此時(shí)照片位于畫布中心位置 ?? ??? ?images[index].copyTo(bg(Rect(x, y, width, height))); ?? ??? ?imshow("Demo", bg); ?? ?} ?? ?destroyAllWindows(); ?? ?system("pause"); ?? ?return 0; }
總結(jié)
本文使用OpenCV C++ 制作電子相冊(cè)查看器,類似win10系統(tǒng)下的“照片”功能,關(guān)鍵步驟有以下幾點(diǎn)。
1、圖片在畫布上居中顯示
2、使用鍵盤響應(yīng)事件控制相片上下讀取
到此這篇關(guān)于基于C++ OpenCV制作電子相冊(cè)查看器的文章就介紹到這了,更多相關(guān)C++ OpenCV電子相冊(cè)查看器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android中使用GridView和ImageViewSwitcher實(shí)現(xiàn)電子相冊(cè)簡(jiǎn)單功能實(shí)例
- 基于spring+hibernate+JQuery開發(fā)之電子相冊(cè)(附源碼下載)
- C++ OpenCV實(shí)現(xiàn)圖像去水印功能
- C++?OpenCV實(shí)現(xiàn)二維碼檢測(cè)功能
- C++ OpenCV生成蒙太奇圖像的示例詳解
- C++ OpenCV實(shí)戰(zhàn)之制作九宮格圖像
- C++ OpenCV實(shí)戰(zhàn)之圖像透視矯正
- C++ OpenCV實(shí)現(xiàn)圖像修復(fù)功能
相關(guān)文章
C語(yǔ)言自定義實(shí)現(xiàn)strlen函數(shù)的3種方法總結(jié)
這篇文章帶大家了解C語(yǔ)言中自定義實(shí)現(xiàn)strlen函數(shù)的3種方法,計(jì)數(shù)器,遞歸以及指針,這三種方法通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08單鏈表實(shí)現(xiàn)反轉(zhuǎn)的3種方法示例代碼
單鏈表的反轉(zhuǎn)是常見的面試題目,下面這篇文章主要給大家介紹了關(guān)于單鏈表實(shí)現(xiàn)反轉(zhuǎn)的3種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02C語(yǔ)言算法積累加tag的循環(huán)隊(duì)列
這篇文章主要為大家介紹了C語(yǔ)言算法積累加tag的循環(huán)隊(duì)列的解題思路,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06C++實(shí)現(xiàn)LeetCode(134.加油站問(wèn)題)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(134.加油站問(wèn)題),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07