文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

OpenCV实现乱序碎片复原

2024-04-02 19:55

关注

题目

将4张打乱顺序的碎片拼接复原并展示原图

算法思路

将x张碎片的左右边缘提取保存

左右边缘两两对比,将相似度超过预设阈值的碎片执行拼接操作,得到左右拼接好的碎片

提取左右拼接好的碎片的上下边缘

上下边缘两两对比,将相似度超过预设阈值的碎片执行拼接操作,得到原图

源码展示


#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;



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);//参数:碎片;碎片的左右边缘

//保存每张碎片的上下边缘
vector <vector<Mat>> edge_resection_TB(const vector <Mat>& fragments_LR);

//上下拼接
void picture_stitching_TB(const Mat& img1, const Mat& img2);

//对左右拼接好的碎片进行上下对比拼接
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);                                           //展示结果

    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颜色特征模型(色调H,饱和度S,亮度V)
    cvtColor(tmpImg, tmpImg, COLOR_BGR2HSV);
    cvtColor(orgImg, orgImg, COLOR_BGR2HSV);
    //直方图尺寸设置
    //一个灰度值可以设定一个bins,256个灰度值就可以设定256个bins
    //对应HSV格式,构建二维直方图
    //每个维度的直方图灰度值划分为256块进行统计,也可以使用其他值
    int hBins = 256, sBins = 256;
    int histSize[] = { hBins,sBins };
    //H:0~180, S:0~255,V:0~255
    //H色调取值范围
    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){            //当j>l时被对比的边缘应该在对比右边
                            picture_stitching_LR(fragments.at(i),fragments.at(k+1));
                        } else if(j<l){     //当j<l时被对比的边缘应该在对比右边
                            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;
}

//对左右拼接好的碎片进行上下对比拼接
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){            //当j>l时被对比的边缘应该在对比下边
                            picture_stitching_TB(fragments_LR.at(i),fragments_LR.at(k+1));
                        } else if(j<l){     //当j<l时被对比的边缘应该在对比上边
                            picture_stitching_TB(fragments_LR.at(k+1),fragments_LR.at(i));
                        }
                    }
                }
            }
        }
    }
}

结果演示

碎片:

拼接结果:

到此这篇关于OpenCV实现乱序碎片复原的文章就介绍到这了,更多相关OpenCV碎片复原内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯