-
2018-11-04 10:05:05
由于最近在学习超分辨率算法,但是大多数开源程序输入图片太大就显示显存不够,因此就把手机拍摄的图片先分割成一系列小的图片,超分辨率之后再拼接在一块
OpenCV的程序如下:比较简单,对5x5即25张图片进行拼接:
#include <iostream>
#include <core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<opencv2/stitching.hpp>using namespace std;
using namespace cv;
int main()
{
int i = 0,j=0;
Mat combine;
Mat row[5][5], column[5];
Mat com_row[5][5], con_column[5];row[0][0] = imread("C:\\test\\pic_div\\1-1.jpg");
row[0][1] = imread("C:\\test\\pic_div\\1-2.jpg");
row[0][2] = imread("C:\\test\\pic_div\\1-3.jpg");
row[0][3] = imread("C:\\test\\pic_div\\1-4.jpg");
row[0][4] = imread("C:\\test\\pic_div\\1-5.jpg");row[1][0] = imread("C:\\test\\pic_div\\2-1.jpg");
row[1][1] = imread("C:\\test\\pic_div\\2-2.jpg");
row[1][2] = imread("C:\\test\\pic_div\\2-3.jpg");
row[1][3] = imread("C:\\test\\pic_div\\2-4.jpg");
row[1][4] = imread("C:\\test\\pic_div\\2-5.jpg");row[2][0] = imread("C:\\test\\pic_div\\3-1.jpg");
row[2][1] = imread("C:\\test\\pic_div\\3-2.jpg");
row[2][2] = imread("C:\\test\\pic_div\\3-3.jpg");
row[2][3] = imread("C:\\test\\pic_div\\3-4.jpg");
row[2][4] = imread("C:\\test\\pic_div\\3-5.jpg");row[3][0] = imread("C:\\test\\pic_div\\4-1.jpg");
row[3][1] = imread("C:\\test\\pic_div\\4-2.jpg");
row[3][2] = imread("C:\\test\\pic_div\\4-3.jpg");
row[3][3] = imread("C:\\test\\pic_div\\4-4.jpg");
row[3][4] = imread("C:\\test\\pic_div\\4-5.jpg");row[4][0] = imread("C:\\test\\pic_div\\5-1.jpg");
row[4][1] = imread("C:\\test\\pic_div\\5-2.jpg");
row[4][2] = imread("C:\\test\\pic_div\\5-3.jpg");
row[4][3] = imread("C:\\test\\pic_div\\5-4.jpg");
row[4][4] = imread("C:\\test\\pic_div\\5-5.jpg");//cv::resize(a, a, cv::Size(1984, 1488), 0, 0, CV_INTER_LINEAR);
//cv::resize(b, b, cv::Size(1984, 1488), 0, 0, CV_INTER_LINEAR);
//cv::resize(c, c, cv::Size(1984, 1488), 0, 0, CV_INTER_LINEAR);
//cv::resize(d, d, cv::Size(1984, 1488), 0, 0, CV_INTER_LINEAR);
//水平拼接
com_row[0][0] = row[0][0];
com_row[1][0] = row[1][0];
com_row[2][0] = row[2][0];
com_row[3][0] = row[3][0];
com_row[4][0] = row[4][0];
for (i = 0; i < 5; i = i + 1)
{
for (j = 0; j < 4; j = j + 1)
{
hconcat(com_row[i][j], row[i][j+1], com_row[i][j+1]);
}
column[i] = com_row[i][4]; //产生的每一行的拼接图片
}
//垂直拼接
con_column[0] = column[0];
for (i = 0; i < 4; i = i + 1)
{
vconcat(con_column[i], column[i + 1], con_column[i + 1]);
}
combine = con_column[4];
namedWindow("Combine", CV_WINDOW_AUTOSIZE);
imshow("Combine", combine);
imwrite("Combine.png", combine);
cv::waitKey(1);system("pause");
return 0;
}拼接 之前的图片:
拼接之后:
更多相关内容 -
opencv实现多张图像拼接
2020-08-26 10:31:50主要为大家详细介绍了opencv实现多张图像拼接功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
Panorama:使用opencv和python3进行多幅图像全景拼接
2021-05-07 04:26:45该存储库包含多个图像拼接的实现。 高分辨率图像处理缓慢。 图像必须按从左到右的顺序提供,反之亦然。 演示->>> 要求 python3.7.1 的opencv3.4.2 或使用opencv-contrib-python,因为某些非免费功能不可用 pip ... -
python opencv 图像拼接的实现方法
2020-09-19 05:13:11高级图像拼接也叫作基于特征匹配的图像拼接,拼接时消去两幅图像相同的部分,实现拼接合成全景图。这篇文章主要介绍了python opencv 图像拼接,需要的朋友可以参考下 -
Opencv 实战五 图像拼接
2022-05-13 13:55:24下面用opencv实现一下多张图像进行拼接 如下图所示,三张不同角度的图像最终拼接成一张全视角的图像 from imutils import paths import numpy as np import argparse import imutils import cv2 # 构造参数解析...图像拼接技术就是将数张有重叠部分的图像(可能是不同时间、不同视角或者不同传感器获得的)拼成一幅无缝的全景图或高分辨率图像的技术。
下面用opencv实现一下多张图像进行拼接
如下图所示,三张不同角度的图像最终拼接成一张全视角的图像
from imutils import paths import numpy as np import argparse import imutils import cv2 # 构造参数解析器并解析参数 ap = argparse.ArgumentParser() ap.add_argument("-i", "--images",default='images', type=str, required=True, help="path to input directory of images to stitch") ap.add_argument("-o", "--output", default='output.png',type=str, required=True, help="path to the output image") ap.add_argument("-c", "--crop", type=int, default=0, help="whether to crop out largest rectangular region") args = vars(ap.parse_args()) # vars函数是实现返回对象object的属性和属性值的字典对象 print(args) # {'images': 'images/scottsdale', 'output': 'output.png', 'crop': 1} # 匹配输入图像的路径并初始化我们的图像列表 # rectangular_region = 2 print("[INFO] loading images...") # 获取到每张待拼接图像并排序,如['第一张图片路径', 第二张图片路径',第三张图片路径'] imagePaths = sorted(list(paths.list_images(args["images"]))) # print(imagePaths) # imagePaths = ['IMG_1786-2.jpg', # 'IMG_1787-2.jpg', # 'IMG_1788-2.jpg'] images = [] # 遍历图像路径,加载每个路径,然后将它们添加到我们的路径中图像到stich列表 for imagePath in imagePaths: image = cv2.imread(imagePath) images.append(image) # 初始化OpenCV的图像sticher对象,然后执行图像拼接 print("[INFO] stitching images...") stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create() (status, stitched) = stitcher.stitch(images) # print(status, stitched) # 如果状态为“0”,则OpenCV成功执行图像拼接 if status == 0: # 检查我们是否应该从拼接图像中裁剪出最大的矩形区域 if args["crop"] > 0: # 在拼接图像周围创建一个10像素的黑色边框 print("[INFO] cropping...") stitched = cv2.copyMakeBorder(stitched, 10, 10, 10, 10, cv2.BORDER_CONSTANT, (0, 0, 0)) # cv2.imshow('123',stitched) # 将拼接图像转换为灰度 gray = cv2.cvtColor(stitched, cv2.COLOR_BGR2GRAY) # cv2.imshow('456', gray) # 对灰度图像进行阈值二值化, # 这样所有大于零的像素都设置为255(前景),而其他所有像素都保持为0(背景) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)[1] # cv2.imshow('789', thresh) # 在阈值图像中找到所有外部轮廓,然后找到 “最大 ”轮廓,它将是拼接图像的轮廓 # cv2.RETR_EXTERNAL:只找外轮廓。cv2.CHAIN_APPROX_SIMPLE:输出少量轮廓点 # 输出参数1:图像 # 输出参数2:轮廓列表 # 输出参数3:层级 cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # print(cnts) #cnts包括三个数组: # print(len(cnts)) cnts = imutils.grab_contours(cnts) ################################ # imutils.grab_contours 的源码 : # # if the length the contours tuple returned by cv2.findContours # # is '2' then we are using either OpenCV v2.4, v4-beta, or # # v4-official # if len(cnts) == 2: # cnts = cnts[0] # # if the length of the contours tuple is '3' then we are using # # either OpenCV v3, v4-pre, or v4-alpha # elif len(cnts) == 3: # cnts = cnts[1] # # otherwise OpenCV has changed their cv2.findContours return # # signature yet again and I have no idea WTH is going on # else: # raise Exception(("Contours tuple must have length 2 or 3, " # "otherwise OpenCV changed their cv2.findContours return " # "signature yet again. Refer to OpenCV's documentation " # "in that case")) # # return the actual contours array # return cnts ################################## # 抓取具有最大区域的轮廓(即拼接图像本身的轮廓),cv2.contourArea是求轮廓面积 c = max(cnts, key=cv2.contourArea) # print(c) # print(c.shape) # 为掩码分配内存,该掩码将包含拼接图像区域的矩形边界框 mask = np.zeros(thresh.shape, dtype="uint8") # 计算出最大轮廓的边界框,使用边界矩形信息.使用 cv2.boundingRect(img) 函数,用一个最小的矩形, # 把找到的形状包起来,img是一个二值图,也就是它的参数;返回四个值,分别是 x,y,w,h; # 其中 x,y 是矩阵左上点的坐标,w,h 是矩阵的宽和高 (x, y, w, h) = cv2.boundingRect(c) # 使用cv2.rectangle给图像加框,我们在mask上绘制一个纯白色矩形。 # 参数1:图像 # 参数2:左上角坐标 # 参数3:右下角坐标 # 参数4:框的颜色 # 参数5:框的粗细 cv2.rectangle(mask, (x, y), (x + w, y + h), 255, -1) # 创建掩码的两个副本 # 第一个mask,将逐渐缩小,直到它可以放入全景内部。 minRect = mask.copy() # 第二个mask,将用于确定是否需要继续减小minRect的大小。 sub = mask.copy() cv2.imshow('111',sub) # 保持循环,直到sub中没有更多的前景像素 # 对二值化图像执行countNonZero。可得到非零像素点数(即外边框的像素点) print(cv2.countNonZero(sub)) while cv2.countNonZero(sub) > 0: # 执行侵蚀形态学操作以减小minRect的大小。 minRect = cv2.erode(minRect, None) cv2.imshow('333',minRect) # 从minRect中减去thresh ,一旦minRect中没有更多的前景像素,我们就可以从循环中断开 sub = cv2.subtract(minRect, thresh) # 在最小矩形掩码中找到轮廓,然后提取边界框(x,y) - 坐标 cnts = cv2.findContours(minRect.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cv2.imshow('444',cnts[0]) cnts = imutils.grab_contours(cnts) c = max(cnts, key=cv2.contourArea) (x, y, w, h) = cv2.boundingRect(c) # 使用边界框坐标来提取我们的最终拼接图像 stitched = stitched[y:y + h, x:x + w] # 将输出拼接图像写入磁盘 cv2.imwrite("result.jpg", stitched) # 将输出拼接图像显示到我们的屏幕 cv2.imshow("Stitched", stitched) cv2.waitKey(0) # 否则,拼接失败,可能是由于检测不到足够的关键点 else: print("[INFO] image stitching failed ({})".format(status))
#执行 python main.py --images images/ --output output.png --crop 1
结果如下所示
有一说一opencv真的牛掰 -
OpenCV 实现多张图像拼接
2021-06-27 00:53:07点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达 本文转自:opencv学堂拼接算法OpenCV中从2.4.x版本之后多出来一个新的模型 图像拼接,该...点击上方“小白学视觉”,选择加"星标"或“置顶”
重磅干货,第一时间送达
本文转自:opencv学堂
拼接算法
OpenCV中从2.4.x版本之后多出来一个新的模型 图像拼接,该模块通过简单的高级API设置,可以获得比较好的图像拼接效果,OpenCV官方提供了一个高度集成的API函数 Stitcher,只要两行代码就可以得到一个很好的拼接图像。
Ptr<Stitcher> stitcher = Stitcher::create(mode); Stitcher::Status status = stitcher->stitch(imgs, pano);
其中第一行代码是创建拼接Stitcher的指针,第二行代码是调用拼接算法,
imgs表示的输入参数,是一系列Mat对象的vector。
pano表示的输出结果,是拼接之后的Mat对象
官方的例子得到效果是非常的好,输入的images如下:
拼接结果如下:
但是很多人按照官方的例子开始拼接自己的图像,就是各种掉坑,各种拼接都不出结果,想跟跟上面一样简单的调用两句代码完成几乎是个梦,其实这个API里面有很多参数设置,这个在官方的演示当中都没有详细交代,stitching拼接算法 流程图示如下:
可见图像拼接是一个很复杂的算法,是由一系列的基础算法构成,这些基础算法如果你不是很了解,其实很难实现自己的图像拼接,这其中影响拼接算法stitch工作最常见几个算法子模块为:
特征发现与描述子
常见的特征可以选择SIFT、SURF、AKAZE、ORB等特征算子进行匹配相机参数
不同的相机参数与设置会导致不同的结果融合方式(blender)
不同的融合方式,也会导致不同结果各种阈值设置,特别是config threshold,如果无法特征匹配,记得把这个阈值调小点
其它参数可以如何设置可以参考OpenCV的官方文档,总之无法拼接就去调参数,一般最后都会拼接成功,此外该算法速度比较慢,但是支持GPU执行,所以想要实时的可以尝试如何GPU下执行,我这里没有尝试 ,谁尝试过的可以留言分享,我负责置顶。
代码演示
另外在拼接的时候可以设置不同warper,这样会对拼接之后的图像生成不同效果,常见的效果包括
鱼眼相机
环视(平面曲翘)
默认
图示分别如下:
演示代码如下:
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main(int argc, char** argv) { vector<string> files; glob("D:/images/zsxq/1", files); vector<Mat> images; for (int i = 0; i < files.size(); i++) { printf("image file : %s \n", files[i].c_str()); images.push_back(imread(files[i])); } // 设置拼接模式与参数 Mat result1, result2, result3; Stitcher::Mode mode = Stitcher::PANORAMA; Ptr<Stitcher> stitcher = Stitcher::create(mode); // 拼接方式-多通道融合 auto blender = detail::Blender::createDefault(detail::Blender::MULTI_BAND); stitcher->setBlender(blender); // 拼接 Stitcher::Status status = stitcher->stitch(images, result1); // 平面曲翘拼接 auto plane_warper = makePtr<cv::PlaneWarper>(); stitcher->setWarper(plane_warper); status = stitcher->stitch(images, result2); // 鱼眼拼接 auto fisheye_warper = makePtr<cv::FisheyeWarper>(); stitcher->setWarper(fisheye_warper); status = stitcher->stitch(images, result3); // 检查返回 if (status != Stitcher::OK) { cout << "Can't stitch images, error code = " << int(status) << endl; return EXIT_FAILURE; } imwrite("D:/result1.png", result1); imwrite("D:/result2.png", result2); imwrite("D:/result3.png", result3); waitKey(0); return 0; }
注意:一起运行速度比较慢!是真的比较慢!
下载1:OpenCV-Contrib扩展模块中文版教程
在「小白学视觉」公众号后台回复:扩展模块中文教程,即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。
下载2:Python视觉实战项目52讲
在「小白学视觉」公众号后台回复:Python视觉实战项目,即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。
下载3:OpenCV实战项目20讲
在「小白学视觉」公众号后台回复:OpenCV实战项目20讲,即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。
交流群
欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~
-
opencv实现指定目录下多幅图像读取与拼接
2017-09-13 17:38:26读取指定目录下按照一定命名规格命名的图片,可循环读取多幅图片,并进行图像拼接。按照类似原理,可实现按照一定命名规格将图片存储到指定目录下。 -
python opencv进行图像拼接
2020-12-20 09:31:453、如果找到了足够多的匹配点,就能将两幅图拼接起来,拼接前,可能需要将第二幅图透视旋转一下,利用找到的关键点,将第二幅图透视旋转到一个与第一幅图相同的可以拼接的角度; 4、进行拼接; 5、进行拼接后的一些... -
OpenCV图像处理--常用图像拼接方法
2021-10-15 14:57:10OpenCV常用图像拼接方法(一) :直接拼接OpenCV常用图像拼接方法(一) :直接拼接
vconcat()—垂直方向拼接,要求待拼接图像有相同的宽度; hconcat()—水平方向拼接,要求待拼接图像有相同的高度。
使用vconcat()和hconcat()拼接则要求待拼接图像有相同的宽度或高度
Mat img = imread("girl.jpg"); vector<Mat>vImgs; Mat result; vImgs.push_back(img); vImgs.push_back(img); vconcat(vImgs, result); //垂直方向拼接 //hconcat(vImgs, result); //水平方向拼接 imshow("result",result); cout << "Hello World!" << endl; waitKey(0);
其他拼接函数vector<Mat> images; images.push_back(imread("stitch1.jpg")); images.push_back(imread("stitch2.jpg")); // 设置拼接模式与参数 Mat result1, result2, result3; Stitcher::Mode mode = Stitcher::PANORAMA; Ptr<Stitcher> stitcher = Stitcher::create(mode); // 拼接方式-多通道融合 auto blender = detail::Blender::createDefault(detail::Blender::MULTI_BAND); stitcher->setBlender(blender); // 拼接 Stitcher::Status status = stitcher->stitch(images, result1); // 平面曲翘拼接 auto plane_warper = makePtr<cv::PlaneWarper>(); stitcher->setWarper(plane_warper); status = stitcher->stitch(images, result2); // 鱼眼拼接 auto fisheye_warper = makePtr<cv::FisheyeWarper>(); stitcher->setWarper(fisheye_warper); status = stitcher->stitch(images, result3); // 检查返回 if (status != Stitcher::OK) { cout << "Can't stitch images, error code = " << int(status) << endl; return EXIT_FAILURE; } imshow("result1.png", result1); imshow("result2.png", result2); imshow("result3.png", result3); waitKey(0);
图示:
OpenCV常用图像拼接方法(二) :基于模板匹配拼接
- 适用范围:图像有重合区域,且待拼接图像之间无明显尺度变化和畸变。
- 优点:简单、快速(相比于SIFT特征匹配拼接)。
- 常用实例:两个相邻相机水平拍摄图像拼接。
截取如下两部分ROI作为待拼接图像。
待拼接图①:
待拼接图②:思路:在图①中截取部分公共区域ROI作为模板,利用模板在图②中匹配,得到最佳匹配位置后计算X和Y方向需要平移的像素距离,将图②对应的拼接到大图中。如下,模板为青色区域:
部分代码和效果如下:Mat imgL = imread("A.jpg"); Mat imgR = imread("B.jpg"); double start = getTickCount(); Mat grayL, grayR; cvtColor(imgL, grayL, COLOR_BGR2GRAY); cvtColor(imgR, grayR, COLOR_BGR2GRAY); Rect rectCut = Rect(372, 122, 128, 360); Rect rectMatched = Rect(0, 0, imgR.cols / 2, imgR.rows); Mat imgTemp = grayL(Rect(rectCut)); Mat imgMatched = grayR(Rect(rectMatched)); int width = imgMatched.cols - imgTemp.cols + 1; int height = imgMatched.rows - imgTemp.rows + 1; Mat matchResult(height, width, CV_32FC1); matchTemplate(imgMatched, imgTemp, matchResult, TM_CCORR_NORMED); normalize(matchResult, matchResult, 0, 1, NORM_MINMAX, -1); //归一化到0--1范围 double minValue, maxValue; Point minLoc, maxLoc; minMaxLoc(matchResult, &minValue, &maxValue, &minLoc, &maxLoc); Mat dstImg(imgL.rows, imgR.cols + rectCut.x - maxLoc.x, CV_8UC3, Scalar::all(0)); Mat roiLeft = dstImg(Rect(0, 0, imgL.cols, imgL.rows)); imgL.copyTo(roiLeft); Mat debugImg = imgR.clone(); rectangle(debugImg, Rect(maxLoc.x, maxLoc.y, imgTemp.cols, imgTemp.rows), Scalar(0, 255, 0), 2, 8); imwrite("match.jpg", debugImg); Mat roiMatched = imgR(Rect(maxLoc.x, maxLoc.y - rectCut.y, imgR.cols - maxLoc.x, imgR.rows - 1 - (maxLoc.y - rectCut.y))); Mat roiRight = dstImg(Rect(rectCut.x, 0, roiMatched.cols, roiMatched.rows)); roiMatched.copyTo(roiRight); double end = getTickCount(); double useTime = (end - start) / getTickFrequency(); cout << "use-time : " << useTime << "s" << endl; imwrite("dst.jpg", dstImg); cout << "Done!" << endl;
匹配结果:
拼接结果:
OpenCV常用图像拼接方法(三) :SIFT特征匹配拼接方法
特点和适用范围:图像有足够重合相同特征区域,且待拼接图像之间无明显尺度变换和畸变。
优点:适应部分倾斜变化情况。缺点:需要有足够的相同特征区域进行匹配,速度较慢,拼接较大图片容易崩溃。
如下是待拼接的两张图片:
特征匹配图:
拼接结果图:
拼接缝处理后(拼接处过渡更自然):
/********************直接图像拼接函数*************************/ bool ImageOverlap0(Mat &img1, Mat &img2) { Mat g1(img1, Rect(0, 0, img1.cols, img1.rows)); // init roi Mat g2(img2, Rect(0, 0, img2.cols, img2.rows)); cvtColor(g1, g1, COLOR_BGR2GRAY); cvtColor(g2, g2, COLOR_BGR2GRAY); vector<cv::KeyPoint> keypoints_roi, keypoints_img; /* keypoints found using SIFT */ Mat descriptor_roi, descriptor_img; /* Descriptors for SIFT */ FlannBasedMatcher matcher; /* FLANN based matcher to match keypoints */ vector<cv::DMatch> matches, good_matches; cv::Ptr<cv::SIFT> sift = cv::SIFT::create(); int i, dist = 80; sift->detectAndCompute(g1, cv::Mat(), keypoints_roi, descriptor_roi); /* get keypoints of ROI image */ sift->detectAndCompute(g2, cv::Mat(), keypoints_img, descriptor_img); /* get keypoints of the image */ matcher.match(descriptor_roi, descriptor_img, matches); //实现描述符之间的匹配 double max_dist = 0; double min_dist = 5000; //-- Quick calculation of max and min distances between keypoints for (int i = 0; i < descriptor_roi.rows; i++) { double dist = matches[i].distance; if (dist < min_dist) min_dist = dist; if (dist > max_dist) max_dist = dist; } // 特征点筛选 for (i = 0; i < descriptor_roi.rows; i++) { if (matches[i].distance < 3 * min_dist) { good_matches.push_back(matches[i]); } } printf("%ld no. of matched keypoints in right image\n", good_matches.size()); /* Draw matched keypoints */ Mat img_matches; //绘制匹配 drawMatches(img1, keypoints_roi, img2, keypoints_img, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); imshow("matches", img_matches); vector<Point2f> keypoints1, keypoints2; for (i = 0; i < good_matches.size(); i++) { keypoints1.push_back(keypoints_img[good_matches[i].trainIdx].pt); keypoints2.push_back(keypoints_roi[good_matches[i].queryIdx].pt); } //计算单应矩阵(仿射变换矩阵) Mat H = findHomography(keypoints1, keypoints2, RANSAC); Mat H2 = findHomography(keypoints2, keypoints1, RANSAC); Mat stitchedImage; //定义仿射变换后的图像(也是拼接结果图像) Mat stitchedImage2; //定义仿射变换后的图像(也是拼接结果图像) int mRows = img2.rows; if (img1.rows > img2.rows) { mRows = img1.rows; } int count = 0; for (int i = 0; i < keypoints2.size(); i++) { if (keypoints2[i].x >= img2.cols / 2) count++; } //判断匹配点位置来决定图片是左还是右 if (count / float(keypoints2.size()) >= 0.5) //待拼接img2图像在右边 { cout << "img1 should be left" << endl; vector<Point2f>corners(4); vector<Point2f>corners2(4); corners[0] = Point(0, 0); corners[1] = Point(0, img2.rows); corners[2] = Point(img2.cols, img2.rows); corners[3] = Point(img2.cols, 0); stitchedImage = Mat::zeros(img2.cols + img1.cols, mRows, CV_8UC3); warpPerspective(img2, stitchedImage, H, Size(img2.cols + img1.cols, mRows)); perspectiveTransform(corners, corners2, H); /* circle(stitchedImage, corners2[0], 5, Scalar(0, 255, 0), 2, 8); circle(stitchedImage, corners2[1], 5, Scalar(0, 255, 255), 2, 8); circle(stitchedImage, corners2[2], 5, Scalar(0, 255, 0), 2, 8); circle(stitchedImage, corners2[3], 5, Scalar(0, 255, 0), 2, 8); */ cout << corners2[0].x << ", " << corners2[0].y << endl; cout << corners2[1].x << ", " << corners2[1].y << endl; imshow("temp", stitchedImage); //imwrite("temp.jpg", stitchedImage); Mat half(stitchedImage, Rect(0, 0, img1.cols, img1.rows)); img1.copyTo(half); imshow("result", stitchedImage); } else //待拼接图像img2在左边 { cout << "img2 should be left" << endl; stitchedImage = Mat::zeros(img2.cols + img1.cols, mRows, CV_8UC3); warpPerspective(img1, stitchedImage, H2, Size(img1.cols + img2.cols, mRows)); imshow("temp", stitchedImage); //计算仿射变换后的四个端点 vector<Point2f>corners(4); vector<Point2f>corners2(4); corners[0] = Point(0, 0); corners[1] = Point(0, img1.rows); corners[2] = Point(img1.cols, img1.rows); corners[3] = Point(img1.cols, 0); perspectiveTransform(corners, corners2, H2); //仿射变换对应端点 /* circle(stitchedImage, corners2[0], 5, Scalar(0, 255, 0), 2, 8); circle(stitchedImage, corners2[1], 5, Scalar(0, 255, 255), 2, 8); circle(stitchedImage, corners2[2], 5, Scalar(0, 255, 0), 2, 8); circle(stitchedImage, corners2[3], 5, Scalar(0, 255, 0), 2, 8); */ cout << corners2[0].x << ", " << corners2[0].y << endl; cout << corners2[1].x << ", " << corners2[1].y << endl; Mat half(stitchedImage, Rect(0, 0, img2.cols, img2.rows)); img2.copyTo(half); imshow("result", stitchedImage); } imwrite("result.bmp", stitchedImage); return true; }
OpenCV常用图像拼接方法(四) :SURF特征匹配拼接方法
参考链接:
https://www.cnblogs.com/skyfsm/p/7411961.html
https://www.cnblogs.com/skyfsm/p/7401523.html -
opencv实现多张图像全景拼接
2020-12-15 16:06:07对多张图片进行基于SIFT的特征检测算法,如果符合最小拼接要求大的关键点`matchKeypoints`数量,使用`OpenCV-Python`自带的`stitching`方法进行全景拼接,但是对于拼接后的黑边裁剪效果不好,可以修改优化。... -
Opencv实战——图像拼接
2022-06-01 15:44:32图像拼接(Image Stitching)是一种利用实景图像组成全景空间的技术,它将多幅图像拼接成一幅大尺度图像或360度全景图,接可以看做是场景重建的一种特殊情况,其中图像仅通过平面单应性进行关联。图像拼接在运动... -
图像拼接(七):OpenCV单应变换模型拼接多幅图像
2017-03-06 10:50:05求取每相邻两幅图像的单应矩阵拼接多幅图像,需要计算每相邻两幅图像的单应矩阵,上篇已经封装了求取单应矩阵的类,可以拿来用。 现有4幅图像:img1img1,img2img2,img3img3,img4img4。依次从右向左排列,拼接... -
图像拼接(十三):OpenCV拼接多幅图像(以中间图像为参考)
2017-03-25 16:48:59在图像拼接(十三):OpenCV单应变换模型拼接多幅图像 这篇博客中实现了用单应变换模型拼接多幅图像,图像拼接使用的OpenCV库函数warpPerspective()。因为这个函数只有在右侧图像变换到左侧图像时才能完整显示,所以... -
Python + OpenCV一步一步地实现图像拼接(原理与代码)
2022-07-18 14:31:27由于已经计算出单应矩阵,可以使用该矩阵将第一张图像转换到第二张图像的平面上。对于在同一平面上的两张图像,一个很直观的思路是,迭代两幅图像,发现匹配的区域则覆盖,否则置为0。......... -
c++ Opencv基础--图像直接拼接
2022-07-05 09:17:14C++ Opencv图像基础处理,图像的直接拼接 -
利用C++中的opencv进行图像拼接
2022-05-25 16:37:36这篇文章依旧是记录采用C++复现...OpenCV常用图像拼接方法(二):基于模板匹配拼接_Color Space的博客-CSDN博客_图像拼接素材 图像拼接的程序的目的是将imgL(1)与imgR(2)拼接起来,方法是通过截取imgL中的一小. -
python+opencv图像拼接-python opencv 图像拼接的实现方法
2020-11-11 14:14:24初级的图像拼接为将两幅图像简单的粘贴在一起,仅仅是图像几何空间的转移与合成,与图像内容无关。高级图像拼接也叫作基于特征匹配的图像拼接,拼接时消去两幅图像相同的部分,实现拼接合成全景图。具有相同尺寸的图... -
OpenCV C++案例实战十二《图像全景拼接》
2022-01-02 10:59:09OpenCV C++案例实战十二《图像全景拼接》前言一、OpenCV Stitcher1.功能源码2.效果二、图像全景拼接1.特征检测2.计算单应性矩阵3.透视变换4.图像拼接5.功能源码6.效果三、源码总结 前言 本文将使用OpenCV C++ 进行... -
利用OpenCV实现图像的全景拼接
2022-03-02 14:54:29利用OpenCV实现图像的全景拼接 案例:实现图像的全景拼接: 代码如下所示: import cv2 import numpy as np class Stitcher(): # 拼接函数 def stitch(self, images, ratio=0.75, reprojThresh=4.0, ... -
python opencv 图像拼接
2018-08-21 10:24:24高级图像拼接也叫作基于特征匹配的图像拼接,拼接时消去两幅图像相同的部分,实现拼接合成全景图。 具有相同尺寸的图A和图B含有相同的部分与不同的部分,如图所示: 用基于特征的图像拼接实现后: 设图像... -
多方向多图像自动拼接源码-python-openCV
2021-12-10 08:53:46基于python编程下opencv库实现多张多方向图片的自动识别拼接,可应用于大幅纸质地图扫描成多个文件后自动拼接恢复电子版原图。 -
5.OpenCV图像拼接
2022-07-15 19:15:13图像拼接(Image Stitching)是一种利用实景图像组成全景空间的技术,它将多幅图像拼接成一幅大尺度图像或360°全景图,可视作场景重建的一种特殊情况,其中图像仅通过平面单应性进行关联。图像拼接在运动检测和跟踪... -
如何使用OpenCV实现多张图像拼接
2019-09-03 10:52:10先来看看OpenCV官方的例子得到效果是非常的好,输入...低级别函数封装在detail命名空间中,展示了OpenCV算法实现的很多步骤和细节,使熟悉如下拼接流水线的用户,方便自己定制。 这涉及到以下算法流程: 命令行调... -
计算机视觉教程7-2: 基于OpenCV的多图像拼接、配准与美化
2021-10-29 09:58:08图像拼接、配准与美化,从涉及的多个知识点出发,结合代码实践加深理解 -
【opencv-python 使用stitcher.stitch进行全景的拼接】将多张图片拼接成全景,采用了stitcher.stitch
2022-05-13 09:24:54【opencv-python 使用stitcher.stitch进行全景的拼接】将多张图片拼接成全景,采用了stitcher.stitch -
使用python-opencv进行图像拼接
2019-02-01 22:12:27如果找到了足够多的匹配点,就能将两幅图拼接起来,拼接前,可能需要将第二幅图透视旋转一下,利用找到的关键点,将第二幅图透视旋转到一个与第一幅图相同的可以拼接的角度; 进行拼接; 进行拼接后的一些处理,让... -
基于OpenCV,如何将多张图片(没有排序的情况下)排序并拼接成全景图像?
2019-10-06 18:51:57网络上大都是在已排序的情况下进行全景拼接。...以方便后续的全景图像拼接。 源图像 x 10 ,顺序为(4 -8-6-3-5-2-10-9-1-7) 如何排序得到(1-2-3-4-5-6-7-8-9-10) 全景图像(1-2-3-4-5-6-7-8-9-10) -
使用OpenCV和Python进行图像拼接
2020-11-21 01:24:21么是图像拼接呢?简单来说,对于输入应该有一组图像,输出是合成图像。同时,必须保留图像之间的逻辑流。首先让我们了解图像拼接的概念。基本上,如果你想捕捉一个大的...获取多幅图像并将其转换成全景图的整个过... -
VC++基于Opencv开发的图像拼接和图像融合软件
2019-03-06 20:07:24VS2012开发的,融合多钟图像拼接和融合方法并进行对比,可以对两幅或四幅图像进行拼接,有助于各种方法的对比和学习,原图片存放于data文件夹即可 -
利用OpenCV实现图像拼接的代码
2016-07-30 10:30:08图像拼接操作对序列图像一般要求重叠区域不少于10%,对序列图像进行特征点检测,可利用OpenCV中提供的角点检测方法来对序列图像进行特征点提取。特征点筛选采用RANSAC提取有效样本特征点,OpenCV提供了函数Find........