目录:

  1. 函数介绍
  2. 图像拼接算法实现
  3. 图像拼接算法改进

Image Stitching with OpenCV and Python - PyImageSearch​www.pyimagesearch.com

本文参考上面这个链接,实现多张图像的拼接,构建一张全景图。

根据多个图像创建全景图的步骤为:

  1. 检测两张图像的关键点特征(DoG、Harris等)
  2. 计算不变特征描述符(SIFT、SURF或ORB等)
  3. 根据关键点特征和描述符,对两张图像进行匹配,得到若干匹配点对,并移除错误匹配;
  4. 使用Ransac算法和匹配的特征来估计单应矩阵(homography matrix);
  5. 通过单应矩阵来对图像进行仿射变换;
  6. 两图像拼接,重叠部分融合;
  7. 裁剪以获得美观的最终图像。

原理比较复杂,本文先不讲解,OpenCV中已经实现了全景图拼接的算法,它们是 cv2.createStitcher (OpenCV 3.x) 和 cv2.Stitcher_create(OpenCV 4) 。

该算法对以下条件具有较好的鲁棒性:

  • 输入图像的顺序
  • 图像的方向
  • 光照变化
  • 图像噪声

一、函数介绍

OpenCV 3.x 的 cv2.createStitcher 函数原型为:

createStitcher(...)createStitcher([, try_use_gpu]) -> retval

这个函数有一个参数 try_use_gpu,它可以用来提升图像拼接整个过程的速度。

OpenCV 4 的 cv2.Stitcher_create 函数原型为:

Stitcher_create(...)Stitcher_create([, mode]) -> retval.   @brief Creates a Stitcher configured in one of the stitching. modes..   .   @param mode Scenario for stitcher operation. This is usually.    determined by source of images to stitch and their transformation.. Default parameters will be chosen for operation in given scenario..   @return Stitcher class instance.

要执行实际的图像拼接,我们需要调用 .stitch 方法:

OpenCV 3.x:
stitch(...) method of cv2.Stitcher instancestitch(images[, pano]) -> retval, panoOpenCV 4.x:
stitch(...) method of cv2.Stitcher instancestitch(images, masks[, pano]) -> retval, pano.   @brief These functions try to stitch the given images..   .   @param images Input images..   @param masks Masks for each input image specifying where to. look for keypoints (optional)..   @param pano Final pano..   @return Status code.

该方法接收一个图像列表,然后尝试将它们拼接成全景图像,并进行返回。

变量 status=0表示图像拼接是否成功。

二、图像拼接算法实现

先把三张图片读取出来存放到列表里:

img_dir = 'pictures/stitching'
names = os.listdir(img_dir)images = []
for name in names:img_path = os.path.join(img_dir, name)image = cv2.imread(img_path)images.append(image)

图片顺序没有影响,我试了一下,不同的图片顺序,输出全景图都相同。

然后构造图像拼接对象stitcher, 要注意的是,OpenCV 3 和 4 的构造器是不同的。

import imutils
stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create()

再把图像列表传入.stitch函数,该函数会返回状态和拼接好的全景图(如果没有错误):

status, stitched = stitcher.stitch(images)

完整代码如下:

import os
import cv2
import imutilsimg_dir = 'pictures/stitching'
names = os.listdir(img_dir)images = []
for name in names:img_path = os.path.join(img_dir, name)image = cv2.imread(img_path)images.append(image)stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create()
status, stitched = stitcher.stitch(images)if status==0:cv2.imwrite('pictures/stitch.jpg', stitched)

OpenCV真的很强大,这短短几行,就实现了拼接全景图。

全景图如下:

呃,全景图是实现了,但是周围出现了一些黑色区域。

这是因为构建全景时会做透视变换,透视变换时会产生这些黑色区域。

所以需要做进一步处理,裁剪出全景图的最大内部矩形区域,也就是只保留下图中红色虚线边框内的全景区域。

三、图像拼接算法改进

获取图像列表并得到初步全景图,这两步还是相同的:

img_dir = 'pictures/stitching'
names = os.listdir(img_dir)images = []
for name in names:img_path = os.path.join(img_dir, name)image = cv2.imread(img_path)images.append(image)stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create()
status, stitched = stitcher.stitch(images)

在全景图四周各添加10像素宽的黑色边框,以确保能够找到全景图的完整轮廓:

stitched = cv2.copyMakeBorder(stitched, 10, 10, 10, 10, cv2.BORDER_CONSTANT, (0, 0, 0))

再将全景图转换为灰度图,并将不为0的像素全置为255,作为前景,其他像素灰度值为0,作为背景。

gray = cv2.cvtColor(stitched, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)

现在有了全景图的二值图,再应用轮廓检测,找到最大轮廓的边界框,

注:和轮廓相关的详细讲解可以查看 这篇文章。

cnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt = max(cnts, key=cv2.contourArea)  # 获取最大轮廓mask = np.zeros(thresh.shape, dtype="uint8")
x, y, w, h = cv2.boundingRect(cnt)
# 绘制最大外接矩形框(内部填充)
cv2.rectangle(mask, (x, y), (x + w, y + h), 255, -1)

这个白色矩形框是整个全景图可以容纳下的最小矩形区域。

接下来就是最难,也是最巧妙的部分了,先创建mask的两个副本:

  • minRect,这个mask的白色区域会慢慢缩小,直到它刚好可以完全放入全景图内部。
  • sub,这个mask用于确定minRect是否需要继续减小,以得到满足要求的矩形区域。
minRect = mask.copy()
sub = mask.copy()# 开始while循环,直到sub中不再有前景像素
while cv2.countNonZero(sub) > 0:minRect = cv2.erode(minRect, None)sub = cv2.subtract(minRect, thresh)

不断地对minRect进行腐蚀操作,然后用minRect减去之前得到的阈值图像,得到sub

再判断sub中是否存在非零像素,如果不存在,则此时的minRect就是我们最终想要的全景图内部最大矩形区域。

subminRect在while循环中的变化情况如下动图所示:

因为OpenCV中灰度图像素值范围0-255,如果两个数相减得到负数的话,会直接将其置为0;如果两个数相加,结果超过了255的话,则直接置为255。

比如下面这个图,左图中白色矩形可以完全包含在全景图中,但不是全景图的最大内接矩形,用它减去右边的阈值图,

因为黑色像素减白色像素,会得到黑色像素,所以其结果图为全黑的图。

所以上面那个while循环最终得到的minRect就是减去阈值图得到全黑图的面积最大的矩形区域。

好了,我们已经得到全景图的内置最大矩形框了,接下来就是找到这个矩形框的轮廓,并获取其坐标:

cnts, hierarchy = cv2.findContours(minRect.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt = max(cnts, key=cv2.contourArea)
# 计算最大轮廓的边界框
(x, y, w, h) = cv2.boundingRect(cnt)# 使用边界框坐标提取最终的全景图
stitched = stitched[y:y + h, x:x + w]

得到最终结果图如下:

完整代码如下:

import os
import cv2
import imutils
import numpy as npimg_dir = '/images'
names = os.listdir(img_dir)images = []
for name in names:img_path = os.path.join(img_dir, name)image = cv2.imread(img_path)images.append(image)stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create()
status, stitched = stitcher.stitch(images)# 四周填充黑色像素,再得到阈值图
stitched = cv2.copyMakeBorder(stitched, 10, 10, 10, 10, cv2.BORDER_CONSTANT, (0, 0, 0))
gray = cv2.cvtColor(stitched, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)cnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt = max(cnts, key=cv2.contourArea)mask = np.zeros(thresh.shape, dtype="uint8")
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(mask, (x, y), (x + w, y + h), 255, -1)minRect = mask.copy()
sub = mask.copy()# 开始while循环,直到sub中不再有前景像素
while cv2.countNonZero(sub) > 0:minRect = cv2.erode(minRect, None)sub = cv2.subtract(minRect, thresh)cnts, hierarchy = cv2.findContours(minRect.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt = max(cnts, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(cnt)# 使用边界框坐标提取最终的全景图
stitched = stitched[y:y + h, x:x + w]cv2.imwrite('final.jpg', stitched)


如果觉得有用,就点个赞吧(ง •̀_•́)ง。

getprocaddress得到为0_拼接图像得到全景图相关推荐

  1. 【Opencv】Python+openCV实现全景图拼接(左右两张图片拼接成一张全景图)

    Python+openCV实现全景图拼接(左右两张图片拼接成一张全景图) 全景图拼接 思路 具体步骤 代码与结果 代码 效果测试1 效果测试2 全景图拼接 思路 这个就是简单对左右两张图进行拼接,希望 ...

  2. java 墨卡托 经纬度_JAVA代码根据经纬度范围计算WGS84与谷歌全球墨卡托包含的切片数目与拼接图像像素尺寸...

    根据项目需求编写的代码. 适用场景:在网络地图上,比如天地图与谷歌地图,用户用鼠标在地图上拉一个矩形框,希望下载该矩形框内某一层级的瓦片数据,并将所有瓦片拼接成一个完整的,包含地理坐标的tif图像. ...

  3. 【计算机视觉】OpenCV 4高级编程与项目实战(Python版)【7】:拼接图像

    我们已经知道,图像是通过数组描述的,那么拼接图像其实就是拼接数组.NumPy提供了2个拼接数组的函数,分别是hstack函数和vstack函数,这两个拼接函数可以将两个数组水平和垂直拼接在一起,也就相 ...

  4. 【python拼图】遍历文件夹后,自动拼接图像成正方形图,或者指定行数显示

    功能说明 def image_combines(img_dir,fw=1,fh=1,cols=1,flag_sort=True,IMAGES_FORMAT = ['.jpg', '.JPG', 'PN ...

  5. Python遥感图像处理应用篇(二十三):Python+GDAL 批量拼接图像

    遥感影像拼接分多种不同的情况,比如比较常用的是两幅影像拼接或者多个图像合并为一个图像. GDAL中实现影像拼接的方式也有多种,比如常用可以通过numpy读取影像数组,并计算各个图像的numpy数组范围 ...

  6. python把hdf转为tif_python_MODIS HDF数据转为tif并拼接图像

    首先是转换格式,原始hdf数据是这样 # -*- coding:utf-8 -*- import os import arcpy from arcpy import env sourceDir=u'E ...

  7. python_MODIS HDF数据转为tif并拼接图像

    首先是转换格式,原始hdf数据是这样 # -*- coding:utf-8 -*- import os import arcpy from arcpy import envsourceDir=u'E: ...

  8. getprocaddress得到为0_基于ZU+系列MPSoC芯片的USB3.0/2.0接口硬件设计

    本文主要介绍Zynq UltraScale + MPSoC系列芯片的USB3.0/2.0接口硬件设计. ZU+系列MPSoC要实现USB3.0/2.0的全部功能,需要同时使用MIO和GTR.因为GTR ...

  9. 利用opencv拼接图像视频摄像头进行录像

    将图像拼接成视频格式 今天想将5000张图片转换成视频格式,操作如下: import os import cv2 import numpy as nppath = '/home/violet/Pych ...

最新文章

  1. VirtualBox下安装rhel5.5 linux系统
  2. 10.STM32中用I2C接口发送数据到EEPROM寄存器在从此寄存器读数据
  3. 107. Leetcode 123. 买卖股票的最佳时机 III (动态规划-股票交易)
  4. python字符串截取_Python容器类型公共方法汇总
  5. Java基础篇(03):流程控制语句,和算法应用
  6. GitLab Docker 前端开发工具链
  7. oracle vm virtualbox安装xp,如何在VirtualBox虚拟机中安装XP系统?
  8. c语言表白情书作品,程序员一句话表白情书
  9. 一曲罢已,愁若梨花,乱红释怀,浮躁尽然。。。。。。
  10. 冲奶粉有感 ----与代码的关系
  11. Android App Dark Theme(暗黑模式)适配指南,android实战mysql
  12. Wordpress最强大的主题-2019最新The7.7主题
  13. 点云视窗类CloudViewer
  14. Qt+sqlite 《扫雷》游戏排名功能
  15. 论坛入口forum.php
  16. python中axes什么意思_matplotlib中的axes.flat是做什么的?/p precodefor i, ax in enumerate(axes.flat): /code...
  17. 七个常用shell运维脚本
  18. 在Windows上使用Google Chrome安装Helvetica Neue字体被认为是有害的
  19. 计算机语言a什么码,a的ascll码是什么意思
  20. 关于高斯定理在泊松重构上的应用

热门文章

  1. 微信公众帐号开发教程第6篇-消息及消息处理工具的封装
  2. [收藏]C#实现超酷的图像效果(附源码)
  3. Webpack按需加载秒开应用
  4. Teambition CEO齐俊元:大象起舞,现代组织的企业协作
  5. 菜鸟的DUBBO进击之路(一):SOA构架
  6. java并发编程与线程安全
  7. 10套华丽的 Windows 8 Metro 风格图标【2000+免费图标】
  8. 【Android游戏开发十八】解放手指,利用传感器开发游戏!
  9. asp.net获取客户端信息
  10. 【QM-05】Material Specification(物料说明)