服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - OpenCV实现乱序碎片复原

OpenCV实现乱序碎片复原

2022-07-28 10:56Zane Zeng C/C++

这篇文章主要介绍了通过OpenCV 直方图相似度对比,实现将4张打乱顺序的碎片拼接复原并展示原图。文中的示例代码讲解详细,需要的朋友可以学习一下

题目

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

算法思路

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

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

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

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

源码展示

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#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张打乱顺序的碎片复原,将复原好的图片展示出来
 * 思路: 1. 将x张碎片的左右边缘提取保存
 *       2. 左右边缘两两对比,将相似度超过预设阈值的碎片执行拼接操作,得到左右拼接好的碎片
 *       3. 提取左右拼接好的碎片的上下边缘
 *       4. 上下边缘两两对比,将相似度超过预设阈值的碎片执行拼接操作,得到原图
*/
 
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实现乱序碎片复原

OpenCV实现乱序碎片复原

OpenCV实现乱序碎片复原

拼接结果:

OpenCV实现乱序碎片复原

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

原文链接:https://blog.csdn.net/Winter_is/article/details/122106732

延伸 · 阅读

精彩推荐
  • C/C++C语言实现的循环单链表功能示例

    C语言实现的循环单链表功能示例

    这篇文章主要介绍了C语言实现的循环单链表功能,结合实例形式分析了基于C语言实现的循环单链表定义、创建、添加、删除、打印、排序等相关操作技巧...

    Tom文星9472021-06-24
  • C/C++C语言实现通讯管理系统设计

    C语言实现通讯管理系统设计

    这篇文章主要为大家详细介绍了C语言实现通讯管理系统设计,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    想飞的孤独少年4332021-06-17
  • C/C++详解C语言中的错误报告errno与其相关应用方法

    详解C语言中的错误报告errno与其相关应用方法

    这篇文章主要介绍了C语言中的错误报告errno与其相关应用方法,包括errno和strerror以及perror的介绍,需要的朋友可以参考下 ...

    selFire11542021-03-07
  • C/C++C语言实现数学表达式运算

    C语言实现数学表达式运算

    这篇文章主要为大家详细介绍了c语言实现数学表达式运算,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    _牛仔很忙10002022-03-05
  • C/C++浅谈C++对象的内存分布和虚函数表

    浅谈C++对象的内存分布和虚函数表

    下面小编就为大家带来一篇浅谈C++对象的内存分布和虚函数表。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    C++教程网11722021-04-24
  • C/C++php调用c++的方法

    php调用c++的方法

    这篇文章主要介绍了php调用c++的方法,需要的朋友可以参考下...

    C++教程网12492021-01-14
  • C/C++哦!这该死的 C 语言

    哦!这该死的 C 语言

    C 语言是一门抽象的、面向过程的语言,C 语言广泛应用于底层开发,C 语言在计算机体系中占据着不可替代的作用,可以说 C 语言是编程的基础,也就是说...

    今日头条3232020-11-09
  • C/C++C语言编程之预处理过程与define及条件编译

    C语言编程之预处理过程与define及条件编译

    这篇文章主要为大家介绍了C语言编程之预处理过程与define及条件编译,文中通过图文及示例代码方式作了详细的解释,有需要的朋友可以借鉴参考下...

    Booksort12092022-01-07