在某些情况下,我们需要将两张图像合并为一张,这时候我们会选择类似 PhotoShow
等画图软件进行拼接。不过我想偷个懒,自动拼接。
所以查找了一些资料之后,开发了 Web版本的图像拼接
接口。
开始之前
用到的 web 端使用的是kProxyCpp ,图像处理用的是 OpenCV
,技术实现参考了:OpenCV探索之路(二十四)图像拼接和图像融合技术(这篇文章有更详细的介绍,有兴趣的可以看看)。
源码已经上传至 Github
,仓库为:kProxyCpp
代码实现
http端实现
使用的是kProxyCpp,比较简单点:
1 2 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
格式字符串,然后一起传入到后台即可:
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
| <!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>
|
最终效果