OpenCV實現(xiàn)亂序碎片復(fù)原
題目
將4張打亂順序的碎片拼接復(fù)原并展示原圖
算法思路
將x張碎片的左右邊緣提取保存
左右邊緣兩兩對比,將相似度超過預(yù)設(shè)閾值的碎片執(zhí)行拼接操作,得到左右拼接好的碎片
提取左右拼接好的碎片的上下邊緣
上下邊緣兩兩對比,將相似度超過預(yù)設(shè)閾值的碎片執(zhí)行拼接操作,得到原圖
源碼展示
#include <opencv2/opencv.hpp> #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <iostream> #include <string> #include <cstdlib> #include <utility> #include <opencv2/imgproc/types_c.h> using namespace std; using namespace cv; /* * 問題: 將x張打亂順序的碎片復(fù)原,將復(fù)原好的圖片展示出來 * 思路: 1. 將x張碎片的左右邊緣提取保存 * 2. 左右邊緣兩兩對比,將相似度超過預(yù)設(shè)閾值的碎片執(zhí)行拼接操作,得到左右拼接好的碎片 * 3. 提取左右拼接好的碎片的上下邊緣 * 4. 上下邊緣兩兩對比,將相似度超過預(yù)設(shè)閾值的碎片執(zhí)行拼接操作,得到原圖 */ int n = 0; //左右拼接時需要的迭代器 int m = 0; //上下拼接時需要的迭代器 //讀取碎片 vector<Mat> fragments_Imread(string files_name); vector<Mat> fragments_LR_Imread(string files_name); //讀取左右拼接好的碎片 //保存每張碎片的左右邊緣 vector <vector<Mat>> edge_resection_LR(const vector <Mat>& fragments); //直方圖對比 bool compare_by_hist(const Mat& img1, const Mat& img2); //左右拼接 void picture_stitching_LR(const Mat& img1, const Mat& img2); //對每張碎片的左右邊緣相互對比拼接 void alignment_and_splicing_LR(const vector <Mat>& fragments, const vector<vector<Mat>>& resection_LR);//參數(shù):碎片;碎片的左右邊緣 //保存每張碎片的上下邊緣 vector <vector<Mat>> edge_resection_TB(const vector <Mat>& fragments_LR); //上下拼接 void picture_stitching_TB(const Mat& img1, const Mat& img2); //對左右拼接好的碎片進(jìn)行上下對比拼接 void alignment_and_splicing_TB(const vector <Mat>& fragments_LR, const vector<vector<Mat>>& resection_TB); int main() { vector<Mat> fragments = fragments_Imread("res/fragments/"); //讀取碎片 vector<vector<Mat> > resection_LR = edge_resection_LR(fragments); //保存每張碎片的左右邊緣 alignment_and_splicing_LR(fragments,resection_LR); //對每張碎片的左右邊緣相互對比拼接 vector<Mat> fragments_LR = fragments_LR_Imread("res/fragments_LR/"); //讀取左右拼接好的碎片 vector<vector<Mat>> resection_TB = edge_resection_TB(fragments_LR); //保存拼接好的左右碎片的上下邊緣 alignment_and_splicing_TB(fragments_LR, resection_TB); //對左右拼接好的碎片的上下邊緣相互對比拼接 Mat result = imread("res/result/0.jpg"); imshow("Restoration map",result); //展示結(jié)果 waitKey(0); return 0; } //讀取碎片 vector<Mat> fragments_Imread(string files_name){ vector<string> files; glob(std::move(files_name),files); vector<Mat> fragments; for(auto &file : files){ fragments.push_back(imread(file)); } return fragments; } vector<Mat> fragments_LR_Imread(string files_name){ vector<string> files; glob(std::move(files_name),files); vector<Mat> fragments_LR; for(auto &file : files){ fragments_LR.push_back(imread(file)); } return fragments_LR; } //保存每張碎片的左右邊緣 vector<vector<Mat> > edge_resection_LR(const vector <Mat>& fragments){ vector<vector<Mat> > resection_LR(fragments.size(), vector<Mat>(2)); for(int i = 0; i<fragments.size(); i++){ for(int j = 0; j<2; j++){ switch (j){ case 0: //第 i 張碎片的 左邊; 頂點:(0,0) 尺寸:(10 * 第i張碎片的高/行) resection_LR.at(i).at(j) = fragments.at(i)(Rect(0,0,10, fragments.at(i).rows)); break; case 1: //第 i 張碎片的 右邊; 頂點:(第 i 張碎片的寬/列-10,0) 尺寸:(10 * 第i張碎片的高/行) resection_LR.at(i).at(j) = fragments.at(i)(Rect(fragments.at(i).cols-10,0,10, fragments.at(i).rows)); default: break; } } } return resection_LR; } //直方圖對比 bool compare_by_hist(const Mat& img1, const Mat& img2){ Mat tmpImg,orgImg; resize(img1, tmpImg, Size(img1.cols, img1.rows)); resize(img2, orgImg, Size(img2.cols, img2.rows)); //HSV顏色特征模型(色調(diào)H,飽和度S,亮度V) cvtColor(tmpImg, tmpImg, COLOR_BGR2HSV); cvtColor(orgImg, orgImg, COLOR_BGR2HSV); //直方圖尺寸設(shè)置 //一個灰度值可以設(shè)定一個bins,256個灰度值就可以設(shè)定256個bins //對應(yīng)HSV格式,構(gòu)建二維直方圖 //每個維度的直方圖灰度值劃分為256塊進(jìn)行統(tǒng)計,也可以使用其他值 int hBins = 256, sBins = 256; int histSize[] = { hBins,sBins }; //H:0~180, S:0~255,V:0~255 //H色調(diào)取值范圍 float hRanges[] = { 0, 180 }; //S飽和度取值范圍 float sRanges[] = { 0,255 }; const float* ranges[] = { hRanges, sRanges }; int channels[] = { 0,1 }; //二維直方圖 MatND hist1, hist2; calcHist(&tmpImg, 1, channels, Mat(), hist1,2,histSize, ranges, true, false); normalize(hist1, hist1, 0, 1, NORM_MINMAX, -1, Mat()); calcHist(&orgImg, 1, channels, Mat(), hist2, 2, histSize, ranges, true, false); normalize(hist2, hist2, 0, 1, NORM_MINMAX, -1, Mat()); double similarityValue = compareHist(hist1, hist2, CV_COMP_CORREL); // cout << "相似度:" << similarityValue << endl; return similarityValue >= 0.95; } //左右拼接 void picture_stitching_LR(const Mat& img1, const Mat& img2){ Mat result; hconcat(img1,img2,result); imwrite("res/fragments_LR/"+to_string(n)+".jpg", result); n++; } //對每張碎片的左右邊緣相互對比拼接 void alignment_and_splicing_LR(const vector <Mat>& fragments, const vector<vector<Mat>>& resection_LR){ for(int i = 0; i<fragments.size()-1; i++){ //第 i 張碎片 for(int j = 0; j<2; j++){ //第 i 張碎片的第 j 條邊 for(int k = i; k<fragments.size()-1; k++){ //第 i 張碎片的第 j 條邊 與 第 i 張以后碎片的左右邊緣對比 for(int l = 0; l<2; l++){ if(compare_by_hist(resection_LR.at(i).at(j),resection_LR.at(k+1).at(l))){ if(j>l){ //當(dāng)j>l時被對比的邊緣應(yīng)該在對比右邊 picture_stitching_LR(fragments.at(i),fragments.at(k+1)); } else if(j<l){ //當(dāng)j<l時被對比的邊緣應(yīng)該在對比右邊 picture_stitching_LR(fragments.at(k+1),fragments.at(i)); } } } } } } } //上下拼接 void picture_stitching_TB(const Mat& img1, const Mat& img2){ Mat result; vconcat(img1,img2,result); imwrite("res/result/"+to_string(m)+".jpg", result); m++; } //保存左右拼接好的碎片的上下邊緣 vector <vector<Mat>> edge_resection_TB(const vector <Mat>& fragments_LR){ vector <vector<Mat>> resection_TB(fragments_LR.size(), vector<Mat>(2)); for(int i = 0; i<fragments_LR.size(); i++){ for(int j = 0; j<2; j++){ switch (j){ case 0: //第 i 張碎片的 上邊緣; 頂點:(0,0) 尺寸:(第i張碎片的寬/列 * 10) resection_TB.at(i).at(j) = fragments_LR.at(i)(Rect(0,0,fragments_LR.at(i).cols, 10)); break; case 1: //第 i 張碎片的 下邊緣; 頂點:(0,第 i 張碎片的高/行-10) 尺寸:(第i張碎片的寬/列 * 10) resection_TB.at(i).at(j) = fragments_LR.at(i)(Rect(0,fragments_LR.at(i).rows-10, fragments_LR.at(i).cols, 10)); default: break; } } } return resection_TB; } //對左右拼接好的碎片進(jìn)行上下對比拼接 void alignment_and_splicing_TB(const vector <Mat>& fragments_LR, const vector<vector<Mat>>& resection_TB){ for(int i = 0; i<fragments_LR.size()-1; i++){ //第 i 張碎片 for(int j = 0; j<2; j++){ //第 i 張碎片的第 j 條邊 for(int k = i; k<fragments_LR.size()-1; k++){ //第 i 張碎片的第 j 條邊 與 第 i 張以后碎片的左右邊緣對比 for(int l = 0; l<2; l++){ if(compare_by_hist(resection_TB.at(i).at(j),resection_TB.at(k+1).at(l))){ // picture_stitching_TB(fragments_LR.at(i),fragments_LR.at(k+1)); if(j>l){ //當(dāng)j>l時被對比的邊緣應(yīng)該在對比下邊 picture_stitching_TB(fragments_LR.at(i),fragments_LR.at(k+1)); } else if(j<l){ //當(dāng)j<l時被對比的邊緣應(yīng)該在對比上邊 picture_stitching_TB(fragments_LR.at(k+1),fragments_LR.at(i)); } } } } } } }
結(jié)果演示
碎片:
拼接結(jié)果:
到此這篇關(guān)于OpenCV實現(xiàn)亂序碎片復(fù)原的文章就介紹到這了,更多相關(guān)OpenCV碎片復(fù)原內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++順序容器(vector、deque、list)的使用詳解
本文主要介紹了C++順序容器(vector、deque、list)的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06c++連接mysql數(shù)據(jù)庫的兩種方法(ADO連接和mysql api連接)
現(xiàn)在正做一個接口,通過不同的連接字符串操作不同的數(shù)據(jù)庫。要用到mysql數(shù)據(jù)庫,C++連接mysql有2種方法:利用ADO連接、利用mysql自己的api函數(shù)進(jìn)行連接,下面看看如何用吧2013-12-12在Visual Studio Code中配置C++編譯環(huán)境的問題
關(guān)于Visual Studio Code對C++環(huán)境的配置方法應(yīng)該有好多種,我這里用到了其中的兩種,具體內(nèi)容詳情文中給大家詳細(xì)介紹,對Visual Studio Code配置C++編譯環(huán)境相關(guān)知識感興趣的朋友一起看看吧2021-07-07C++實現(xiàn)轉(zhuǎn)置矩陣的循環(huán)
大家好,本篇文章主要講的是C++實現(xiàn)轉(zhuǎn)置矩陣的循環(huán),感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2022-01-01