图像拼接技术就是将数张有重叠部分的图像(可能是不同时间、不同视角或者不同传感器获得的)拼成一幅无缝的全景图或高分辨率图像的技术。
下面用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 实战五 图像拼接相关推荐

  1. [OpenCV实战]6 图像拼接和图像融合

    索引目录 1.问题描述 2.解决思路 3.程序算法 4.总结 参考 1.问题描述 将含有公共视野相同特征的两张图像拼接融合 2.解决思路 先使用sift算法对两张图像进行特征点提取和匹配,此时特征点过 ...

  2. OpenCV C++案例实战五《答题卡识别》

    OpenCV C++案例实战五<答题卡识别> 前言 一.图像矫正 1.源码 二.获取选项区域 1.扣出每题选项 2.源码 三.获取答案 1.思路 2.辅助函数 3.源码 4.效果 总结 前 ...

  3. Opencv实战 | 用摄像头自动化跟踪特定颜色物体

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:新机器视觉 1. 导语 在之前的某个教程里,我们探讨了如 ...

  4. 重磅升级,52个Python+OpenCV实战项目教你掌握图像处理

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 近期小白学视觉公众号推出了多篇Python+OpenCV实战项目的 ...

  5. OpenCV实战(1)——OpenCV与图像处理基础

    OpenCV实战(1)--OpenCV与图像处理基础 0. 前言 1. OpenCV 基础 1.1 安装 OpenCV 1.2 OpenCV 主要模块 1.3 使用 Qt 进行 OpenCV 开发 2 ...

  6. 再次升级,985博士整理的71个OpenCV实战项目教程开放下载!

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 近期小白学视觉公众号推出了多篇Python+OpenCV实战项目的 ...

  7. 基于OpenCV实战:3步实现图像降噪

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 在本文中,我们将展示如何通过三个简单的步骤来实现降噪.我们将使用机 ...

  8. 基于OpenCV实战:绘制图像轮廓(附代码)

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 山区和地形图中海拔高的区域划出的线称为地形轮廓,它们提供了地形的高 ...

  9. 基于OpenCV实战:车牌检测

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 拥有思维导图或流程将引导我们朝着探索和寻找实现目标的正确道路的方向 ...

最新文章

  1. Java 过滤特殊字符的 正则表达式
  2. BZOJ 4086: [Sdoi2015]travel(SDOI2015 round2 day1)(分类讨论+容斥原理)
  3. 封装 继承 多态_Java基础知识——封装、继承、多态
  4. python生成excel表格-Python生成excel表格并设置样式
  5. 杭电2032杨辉三角
  6. 仿windows造字程序的 ASP.NET图片组合生成控件
  7. 几个常用的宏:likely和unlikely __raw_writel
  8. 错误检测dP-bitstream-ei_flag runRestrictRef
  9. rserve php,使用Rserve远程执行R脚本
  10. 调试某游戏副本中的加亮提示信息思路
  11. 程序猿过年相亲:你总会遇到一个女孩,她不向你要钱,房子和车....
  12. Android深入探究笔记--手势识别
  13. 5-去掉a标签下划线,禁止a标签的跳转
  14. 链客区块链技术面试题目专题(三)
  15. node.js常见问题之:解决npm install出错(Cannot find module ‘internal/util/types‘)
  16. PAAS平台7#215;24小时可用性应用设计
  17. 《算法》第4版 导读
  18. Origin许可进行延期使用
  19. Visual Studio 插件番茄助手2个优秀的特性
  20. STM32系统定时器闪烁LED灯

热门文章

  1. kubernetes如何解决服务依赖呢?
  2. 闪存文件系统(Flash File System)
  3. 今天聊:程序媛是否需要职业规划?
  4. 分布式追踪不是银弹 | 正确使用分布式追踪和 APM 系统
  5. cpu功耗排行_2019.10.31性能和功耗CPU显卡天梯图
  6. iphone手机铃声制作(iTunes)
  7. tair用ldb做分布式存储
  8. BaoStock:使用python的baostock接口,查询除权除息信息
  9. IPCam网络摄像头
  10. Java新版本的控制台不在控制面板里面显示而是躲在这