OpenCV常用图像拼接方法将分为四个部分与大家共享,这里是第二种方法,欢迎关注后续,此处子系统与素材链接位于文章末尾。
OpenCV常用图像拼接方法(二):基于模板匹配的图像拼接。基于模板的图像拼接特征和适用范围:图像有重合区域,且待分割图像之间无明显尺度变化和畸变。常用实例:两个相邻相机水平拍摄图像拼接。优点:简单,快速(相比于SIFT特征匹配拼接)。
这里没有找到更好的实例图片,所以仍使用上一篇文章中的图片,截取如下两部分ROI作为待拆分图像。
待拼接图①:
待拼接图②:
思路:在图①中截取部分公共区域ROI作为模板,利用模板在图②中匹配,得到最佳匹配位置后计算X和Y方向需要平移的距离,将图②对应的拼接到大图。如下,模板为青色区域:
部分代码和效果如下:
1 // Image_Stitch_With_Matchtemplate.cpp
2 // 环境VS2017 + OpenCV4.4.0
3 // 功能:基于模板匹配的图像拼接
4 // 特点:图像有重合区域,且待拼接图像之间无明显尺度变换和畸变
5
6 #include "pch.h"
7 #include <iostream>
8 #include <opencv2/opencv.hpp>
9
10 using namespace std;
11 using namespace cv;
12
13 int main()
14 {
15 Mat imgL = imread("A.jpg");
16 Mat imgR = imread("B.jpg");
17 double start = getTickCount();
18 Mat grayL, grayR;
19 cvtColor(imgL, grayL, COLOR_BGR2GRAY);
20 cvtColor(imgR, grayR, COLOR_BGR2GRAY);
21
22 Rect rectCut = Rect(372, 122, 128, 360);
23 Rect rectMatched = Rect(0, 0, imgR.cols / 2, imgR.rows);
24 Mat imgTemp = grayL(Rect(rectCut));
25 Mat imgMatched = grayR(Rect(rectMatched));
26
27 int width = imgMatched.cols - imgTemp.cols + 1;
28 int height = imgMatched.rows - imgTemp.rows + 1;
29 Mat matchResult(height, width, CV_32FC1);
30 matchTemplate(imgMatched, imgTemp, matchResult, TM_CCORR_NORMED);
31 normalize(matchResult, matchResult, 0, 1, NORM_MINMAX, -1); //归一化到0--1范围
32
33 double minValue, maxValue;
34 Point minLoc, maxLoc;
35 minMaxLoc(matchResult, &minValue, &maxValue, &minLoc, &maxLoc);
36
37 Mat dstImg(imgL.rows, imgR.cols + rectCut.x - maxLoc.x, CV_8UC3, Scalar::all(0));
38 Mat roiLeft = dstImg(Rect(0, 0, imgL.cols, imgL.rows));
39 imgL.copyTo(roiLeft);
40
41 Mat debugImg = imgR.clone();
42 rectangle(debugImg, Rect(maxLoc.x, maxLoc.y, imgTemp.cols, imgTemp.rows), Scalar(0, 255, 0), 2, 8);
43 imwrite("match.jpg", debugImg);
44
45 Mat roiMatched = imgR(Rect(maxLoc.x, maxLoc.y - rectCut.y, imgR.cols - maxLoc.x, imgR.rows - 1 - (maxLoc.y - rectCut.y)));
46 Mat roiRight = dstImg(Rect(rectCut.x, 0, roiMatched.cols, roiMatched.rows));
47
48 roiMatched.copyTo(roiRight);
49
50 double end = getTickCount();
51 double useTime = (end - start) / getTickFrequency();
52 cout << "use-time : " << useTime << "s" << endl;
53
54 imwrite("dst.jpg", dstImg);
55 cout << "Done!" << endl;
56 return 0;
57
58 }
匹配结果:
拼接结果:
本次耗时如下图:( 工业相机1200W图片拼接大约200ms):
分类:
OpenCV
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)