在某些情况下,我们需要将两张图像合并为一张,这时候我们会选择类似 PhotoShow 等画图软件进行拼接。不过我想偷个懒,自动拼接。
所以查找了一些资料之后,开发了 Web版本的图像拼接 接口。
开始之前
用到的 web 端使用的是kProxyCpp ,图像处理用的是 OpenCV,技术实现参考了:OpenCV探索之路(二十四)图像拼接和图像融合技术(这篇文章有更详细的介绍,有兴趣的可以看看)。
源码已经上传至 Github ,仓库为:kProxyCpp
代码实现
http端实现
使用的是kProxyCpp,比较简单点:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | kHttpd::Init();
 
 kHttpd kProxy("网站目录", "线程池数量");
 
 kProxy.set_cb("POST", "/MergePhoto",[](void *kClient, const std::vector<unsigned char> &data, const std::string &url_path,const std::string &method, int type, void *arg) -> int {
 
 if (type == -1) {
 
 …………
 } else {
 return -1;
 }
 });
 
 kProxy.listen(20, port, ip.c_str());
 
 | 
这样我们就绑定了路径 POST /MergePhoto ,然后结合我们的业务进行操作。
图片拼接
原理就是
- 对每幅图进行特征点提取
- 对对特征点进行匹配
- 进行图像配准
- 把图像拷贝到另一幅图像的特定位置
- 对重叠边界进行特殊处理
参考的原文(OpenCV探索之路(二十四)图像拼接和图像融合技术)有更加详细的介绍,我这边就不重复了,代码也比较多,请查看参考原文或者例子源码。
前端代码
前端代码比较简单点,读取文件 Base64 格式字符串,然后一起传入到后台即可:
| 12
 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
 
 | <!DOCTYPE html><html lang="zh">
 <head>
 <meta charset="UTF-8">
 <title>OpenCV合并图片</title>
 <script>
 let data = {};
 
 function onChange(type) {
 let file = this.files[0];
 let reader = new FileReader();
 reader.onload = function (event) {
 
 data[type] = (event.target.result);
 let img = document.querySelector(`#${type}_img`);
 img.src = data[type];
 };
 reader.readAsDataURL(file)
 }
 
 function MergePhoto() {
 let httpRequest = new XMLHttpRequest();
 httpRequest.open('POST', '/MergePhoto', true);
 httpRequest.setRequestHeader("Content-type", "application/json");
 httpRequest.send(JSON.stringify(data));
 
 
 
 httpRequest.onreadystatechange = function () {
 if (httpRequest.readyState === 4 && httpRequest.status === 200) {
 let json = httpRequest.responseText;
 try {
 json = JSON.parse(json);
 }catch (e) {
 
 }
 if(json.code===0) {
 document.querySelector("#MergePhoto").src = json.photo;
 }else{
 alert(json.message);
 }
 }
 };
 }
 </script>
 <style>
 img {
 max-height: calc(100% - 1.5em);
 max-width: 100%;
 }
 
 img[src=""] {
 opacity: 0;
 }
 </style>
 </head>
 <body>
 <div style="position: fixed;left: 0;right: 0;top:0;bottom: 50%;">
 <div style="padding:0.5em;box-sizing: border-box;border:1px solid #CCCCCC;position: absolute;left: 0;right:  50%;top:0;bottom:0;">
 <label>左边图片:<input type="file" onchange="onChange.call(this,'left')"></label><br/>
 <img id="left_img" src="" alt="左边图片"/>
 </div>
 <div style="padding:0.5em;box-sizing: border-box;border:1px solid #CCCCCC;position: absolute;left:  50%;right: 0;top:0;bottom: 0;">
 <label>右边图片:<input type="file" onchange="onChange.call(this,'right')"></label><br/>
 <img id="right_img" src="" alt="右边图片"/>
 </div>
 </div>
 <div style="padding:0.5em;box-sizing: border-box;border:1px solid #CCCCCC;position: fixed;left: 0;right: 0;top: 50%;bottom: 0;">
 <button onclick="MergePhoto()">合并</button>
 <br/>
 <img id="MergePhoto" src="" alt="合并之后图片">
 
 </div>
 </body>
 </html>
 
 | 
最终效果
