全景拼接python旗舰版
前言
在这个项目中,您将构建一个管道,将几幅图像拼接成一个全景图。您还将捕获一组您自己的图像来报告最终的结果。
步骤1 特征检测与描述
本项目的第一步是对序列中的每幅图像分别进行特征检测。回想一下我们在这个类中介绍过的一些特征探测器:哈里斯角、Blob探测器、SIFT探测器等。与检测步骤相结合,就进行了特征描述。您的特性必须对某些转换是不变的。想想你将收集数据集的方式。你需要什么样的不变性?探索在OpenCV中可用的特性描述符实现: SIFT、SURF、ORB等

1.使用cv2.imread读取输入的图像。
2.将图像转换为灰度(例如,使用cv2.cvtColor)以进行特征提取。您也可以通过cv2.resize调整图像的大小(例如,在参考约塞米蒂序列中那样的480像素的高度),以使以下步骤运行得更快。
3.选择您的特征检测器。cv2是一个很好的开始。SIFT_creve(或cv2.xfeatures2d。SIFT_Creve在旧的OpenCV版本中)。
4.使用检测和计算方法提取关键点和关键点特征。
5.图1使用cv2.drawKeypoints可视化了检测到的关键点:
def flt_show(image, title='sift detects'):plt.figure(figsize=(10,10)) # Canvas 10x magnificationplt.title(title,fontsize=20) # titleplt.axis('off') # Hidden axisplt.imshow(cv2.cvtColor(image,cv2.COLOR_BGR2RGB)) # print imageplt.show() # Display canvas# 1. Read the input images using cv2.imread.
def feature_detection_and_description(image_path):image = cv2.imread(image_path)# RGB to Grayimage = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)# Create detectorsift_detecter = sift = cv2.SIFT_create()# Detection picturekp,des = sift.detectAndCompute(image,None) # Keypoints and descriptors# Plot key pointsimg2 = cv2.drawKeypoints(image,kp,None,(255,0,0),4)# showflt_show(img2)# Release resourcescv2.waitKey(0)cv2.destroyAllWindows()feature_detection_and_description('yosemite1.jpg')步骤2 特征匹配和图像对齐
一旦计算出了关键点和特征,代码就需要在连续的图像对之间建立良好的匹配。为此,您需要选择一个距离函数和一个匹配算法。

1.选择一个匹配算法和一个距离函数。强力匹配(cv2。你可以做这个工作,因为你以后会摆脱糟糕的比赛!如果您使用二进制特性,如简短或ORB,看看汉明距离函数(cv2。NORM_HAMMING),否则,只需使用欧几里得距离(cv2。norm_l2 ).
2.使用匹配()方法从一对图像中计算匹配,并提供它们的特征作为输入。选择一对有良好重叠的图像。实际上,按照预定义的顺序(例如从左到右)捕捉图像进行全景拼接是很方便的,这样相邻的图像总是有很好的重叠。
3.使用原始的关键点位置和匹配,以两个m×2数组点1和点2的形式构造对应,这样点1[i]和点2[i]分别在第一和第二幅图像中存储匹配的位置。如果您正在使用建议的OpenCV功能,请查看关键点和DMatch类的接口,以了解如何操作返回对象。
4.现在,从对应关系中估计图像之间的同源性变换。匹配项将会有很多离群值,所以你需要选择一个对离群值很健壮的估计器,比如RANSAC。cv2.findHomography对这一步很有用!
5.最后,用模糊的同源性扭曲其中一幅图像: cv2.warpPerspective。
6.图2显示了在所选对图像之间检测到的1249个匹配中的前10个匹配(基于响应分数)。该图是使用cv2.drawMatches创建的。让我们来看看图3和图4。为什么前者的一致性如此成功?为什么在后一个数字中会有问题?
def detectAndDescribe(image):# convert the image to grayscalegray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# detect and extract features from the imagedescriptor = cv2.SIFT_create()(kps, features) = descriptor.detectAndCompute(image, None)# convert the keypoints from KeyPoint objects to NumPy# arrays
# kps = np.float32([kp.pt for kp in kps])# return a tuple of keypoints and featuresreturn (kps, features)def matchKeypoints(kpsA, kpsB, featuresA, featuresB, ratio, reprojThresh):# compute the raw matches and initialize the list of actual# matches
# matcher = cv2.DescriptorMatcher_create("BruteForce")
# rawMatches = matcher.knnMatch(featuresA, featuresB, 2)
# matches = []
# # loop over the raw matches
# for m in rawMatches:
# # ensure the distance is within a certain ratio of each
# # other (i.e. Lowe's ratio test)
# if len(m) == 2 and m[0].distance < m[1].distance * ratio:
# matches.append((m[0].trainIdx, m[0].queryIdx))bf = cv2.BFMatcher(cv2.NORM_L2,crossCheck=True)matches = bf.match(featuresA,featuresB)goods = sorted(matches,key = lambda x:x.distance)# computing a homography requires at least 4 matchesif len(matches) > 4:# construct the two sets of points
# ptsA = np.float32([kpsA[i] for (_, i) in matches])
# ptsB = np.float32([kpsB[i] for (i, _) in matches])ptsA = np.float32([ kpsA[m.queryIdx].pt for m in goods ]).reshape(-1,1,2)ptsB = np.float32([ kpsB[m.trainIdx].pt for m in goods ]).reshape(-1,1,2)# compute the homography between the two sets of points(H, status) = cv2.findHomography(ptsA, ptsB, cv2.RANSAC,reprojThresh)# return the matches along with the homograpy matrix# and status of each matched pointreturn (matches, H, status)# otherwise, no homograpy could be computedreturn Nonedef drawMatches(imageA, imageB, kpsA, kpsB, matches, status):img1 = imageAimg2 = imageBif len(matches) > 10:src_pts = np.float32([ kpsA[m.queryIdx].pt for m in matches ]).reshape(-1,1,2)dst_pts = np.float32([ kpsB[m.trainIdx].pt for m in matches ]).reshape(-1,1,2)M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)matchesMask = mask.ravel().tolist()h,w,_ = img1.shapepts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)draw_params = dict(matchColor = (0,255,0), # draw matches in green colorsinglePointColor = None,matchesMask = matchesMask, # draw only inliersflags = 2)img_matchers = cv2.drawMatches(imageA,kpsA,imageB,kpsB,matches,None,**draw_params)# return the visualizationreturn img_matchersdef feature_matching_and_image_alignment(imageL, imageR, ratio=0.75, reprojThresh=4.0, showMatches=False):imageA, imageB = imageR, imageL# local invariant descriptors from them(kpsA, featuresA) = detectAndDescribe(imageA)(kpsB, featuresB) = detectAndDescribe(imageB)# match features between the two imagesM = matchKeypoints(kpsA, kpsB,featuresA, featuresB, ratio, reprojThresh)# if the match is None, then there aren't enough matched# keypoints to create a panoramaif M is None:return None# otherwise, apply a perspective warp to stitch the images# together(matches, H, status) = Mresult = cv2.warpPerspective(imageA, H,(imageA.shape[1] + imageB.shape[1], imageA.shape[0]))result[0:imageB.shape[0], 0:imageB.shape[1]] = imageB# check to see if the keypoint matches should be visualizedif showMatches:vis = drawMatches(imageA, imageB, kpsA, kpsB, matches,status)# return a tuple of the stitched image and the# visualizationreturn (result, vis)# return the stitched imagereturn resultresult, vis = feature_matching_and_image_alignment(cv2.imread('yosemite1.jpg'), cv2.imread('yosemite2.jpg'), showMatches=True)
flt_show(vis)
flt_show(result)
步骤3 图像背景去除
现在您已经将原始图像1和图像2扭曲到图像1的平面上,您需要将它们组合起来以产生无缝的结果。如果你简单地添加图像强度,重叠的区域看起来会很不错,但其他区域看起来会很暗,如图3所示。另一个简单的解决方案是将一幅图像复制粘贴到另一幅图像之上。这还将在边界上创建工件,如图5所示。减少伪影强度的一个解决方案是使用自适应权值来混合图像。靠近每幅图像边界的像素不如位于中心的像素可靠。那么如何将这些像素与与这些像素到相应图像边界的距离成比例的权重进行混合呢?我们提供了get_tinghe_变换函数,它取一个扭曲的RGB图像H×W×3,并产生一个单通道距离函数H×W×1。您可以使用这个函数来计算结果为img1 *权重1+img2*权重2。不要忘记将生成的图像规格化到0…255的范围。尝试使用np.最大值(denom,1.0)以避免除以零。将您的图像转换回无符号的8位整数与img.astype(“uint8”)
def get_distance_transform(img_rgb):'''Get distance to the closest background pixel for an RGB imageInput:img_rgb : np.array , HxWx3 RGB imageOutput:dist : np.array , HxWx1 distance imageeach pixel ’s intensity is proportional toits distance to the closest background pixelscaled to [0..255] for plotti'''# Threshold the image : any value above 0 maps into 255thresh = cv2.threshold(img_rgb , 0 , 255 , cv2 . THRESH_BINARY )[1]# Collapse the color dimensionthresh = thresh.any(axis =2)# Pad to make sure the border is treated as backgroundthresh = np.pad(thresh, 1, mode='maximum')# Get distance transformdist = distance_transform_edt(thresh) [1: -1 , 1: -1]# HxW -> HxWx1dist = dist[: , : , None ]return dist / dist . max () * 255.0def getMaskResult(result, show=False):mask = get_distance_transform(result)locs = np.where(mask>0)xmin = np.min(locs[1])xmax = np.max(locs[1])ymin = np.min(locs[0])ymax = np.max(locs[0])result_mask = result[ymin:ymax, xmin:xmax]if show:flt_show(result, 'before')flt_show(result_mask, 'after')return result_mask
result_mask = getMaskResult(result, True)
步骤4 缝合多张图像
拼接n个图像的一个简单方法是从左到右对序列进行排序,并逐步应用成对拼接:如果拼接每一对相邻图像,将得到n个−1的全景图。您可以一次又一次地对这些图像应用相同的拼接过程,直到您只留下一个宽的全景图。您只需要在它上面添加一个for循环。
imageList = [cv2.imread('yosemite1.jpg'), cv2.imread('yosemite2.jpg'), cv2.imread('yosemite3.jpg'),cv2.imread('yosemite4.jpg')]temp_image = feature_matching_and_image_alignment(imageList[0], imageList[1])
temp_image = getMaskResult(temp_image)
flt_show(temp_image1, title='Step 1')
for i in range(2, 4):temp_image = feature_matching_and_image_alignment(temp_image, imageList[i])temp_image = getMaskResult(temp_image)flt_show(temp_image, title='Step {}'.format(i))
步骤5 创建您自己的全景图,并讨论设置和结果。
请注意,这一步将主要根据您提供的讨论进行分级(例如,只捕获一些图像并在不编写的情况下生成结果不会给您很多分数)。为了获得一个好的全景,在捕捉自己的图像时有几件事需要考虑。
imageList = [cv2.imread('1.png'), cv2.imread('2.png'), cv2.imread('3.png'),cv2.imread('4.png'), cv2.imread('5.png')]temp_image = feature_matching_and_image_alignment(imageList[0], imageList[1])
temp_image = getMaskResult(temp_image)
flt_show(temp_image, title='Step 1')
for i in range(2, 5):temp_image = feature_matching_and_image_alignment(temp_image, imageList[i])temp_image = getMaskResult(temp_image)flt_show(temp_image, title='Step {}'.format(i))

# # # #发表评论
- 1。这已经在步骤4中完成了。
- 2。数据集捕捉了沿河的建筑风景,具有良好的视野和易于区分的特征。
- 3。相邻的图片有很好的重叠。
- 4. 摄像机角度的变化容易引起同态现象。如果天气晴朗,最好待在室外,视野开阔,位置好,光线也明亮。只要两幅图像之间的特征明显,摄像机是否自由移动并不重要。
当三张以上的图片拼接在一起时,由于黑色背景的原因,图像与其他图像的拼接会有很多困难。背景剔除可以解决这个问题。
感谢观看!由于是作业的缘故,文中可能有极少部分会出现语义不通顺的情况,但对本文的目的没有什么影响。
相关文章:
全景拼接python旗舰版
前言在这个项目中,您将构建一个管道,将几幅图像拼接成一个全景图。您还将捕获一组您自己的图像来报告最终的结果。步骤1 特征检测与描述本项目的第一步是对序列中的每幅图像分别进行特征检测。回想一下我们在这个类中介绍过的一些特征探测器:…...
(C语言)常见的字符串与内存操作函数
问:1. Solve the problems:我想用三种方法求字符串的长度怎么办?2. strlen处理的字符串中有什么时需要注意:什么只记为什么?当什么不起什么作用时,什么不计算在内,编译器会把什么,什…...
Linux基础笔记总结
♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的绽放࿰…...
R语言学习笔记
1.R语言介绍 2.R语言安装 官网:https://www.r-project.org/ CARN → 选择China中任意镜像站点 → Download R for Windows → base(二进制版本R基础软件)→ Download R-4.2.2 for Windows (76 megabytes, 64 bit) 3.Rstudio安装 https://po…...
【软件测试】企业测试面试题9道,从自我介绍到项目考察+回答......
目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 1、自我介绍 您好&a…...
《Spring源码深度分析》第8章 数据库连接JDBC
目录标题前言一、数据库连接方式1.JDBC连接数据库2.Spring Jdbc连接数据库(JdbcTemplate)二、JdbcTemplate源码分析1.update/save功能的实现源码分析入口(关键)基础方法execute1.获取数据库连接池2.应用用户设定的输入参数3. 调用回调函数处理4. 资源释放Update中的回调函数2.q…...
ModuleNotFoundError的解决方案【已解决】
问题描述 有包却提示ModuleNotFoundError 在正常情况下,你使用pip或者conda检查是否有相应包的时候,显示的是有的。但是一旦运行程序就会报这个ModuleNotFoundError错误。 问题可能是程序运行环境不对。 解决方案 (1)进入正确…...
Vue驼峰与短横线分割命名中有哪些坑
目录 0.前言 驼峰和短横线分割命名注意事项 组件注册命名 父子组件数据传递时命名 父子组件函数传递 0.前言 Vue驼峰命名法指的是将变量以驼峰形式命名,例如 userName、userId 等,而短横线分隔符法则指的是用短横线分隔变量名,例如 user…...
从文件中加载数据以及异常处理
上期学习了数据的存储,这次学习数据的加载 你可以使用把openpyxl.load_workbook() 来打开一个已经存在的工作簿 >>> from openpyxl import load_workbook >>> wb load_workbook(filename empty_book.xlsx) >>> sheet_ranges wb[ran…...
【JavaSE】方法的使用
方法的使用BIT-5-方法的使用绪论1. 方法概念及使用1.1什么是方法1.2 方法定义1.3 实参和形参的关系(重要)1.4 没有返回值的方法2. 方法重载2.1 为什么需要方法重载2.2 方法重载概念3. 递归3.1 生活中的故事3.2 递归的概念3.2 递归执行过程分析3.3 递归练…...
ModelScope 垂类检测系列模型介绍
文章目录ModelScope介绍垂类模型介绍调用方式1 Demo Service2 Notebook3 本地使用* 二次开发总结ModelScope介绍 ModelScope 是阿里达摩院推出的 中文版模型即服务(MaaS, Model as a Service)共享平台。该平台在2022年的云栖大会上发布,之前…...
Linux | Linux卸载和安装MySQL(Ubuntu版)
最近又来到了Linux学习了,原因是要接触云服务器相关知识, 所以博主整理了一些关于Linux的知识, 欢迎各位朋友点赞收藏,天天开心丫,快乐写代码! Linux系列文章请戳 Linux教程专栏 目录 一、卸载MySQL 1…...
【C1】数据类型,常量变量,输入输出,运算符,if/switch/循环,/数组,指针,/结构体,文件操作,/编译预处理,gdb,makefile,线程
文章目录1.数据类型:单双引号,char(1B),int/float(32位系统,大小一样4B,但存储方式不同),double(8B),long double…...
【深度学习】pytorch的基础操作
import torch import numpy as np # 1.1 根据已有的数据创建张量 def test01(): # 1.1 创建标量 data torch.tensor(10) print(data) # 1.2 使用numpy数组来创建张量 data np.random.randn(2,3) data torch.tensor(data) print(data) # 1.3使用list…...
MWORKS--同元软控MWORKS介绍、安装与使用
MWORKS--同元软控MWORKS介绍、安装与使用1 同元软控介绍1.1 同元软控简介1.2 同元软控发展历史2 MWORKS介绍2.1 MWORKS简介2.2 MWORKS产品描述3 装备数字化3.1 发展3.2 内涵3.3 系统模型发展成为产品的一部分3.4 MWORKS系统模型数据管理3.4 MWORKS为装备数字化提供的套件4 下载…...
Python 解决dilb和face_recognition第三方包安装失败
目录 dilb和face_recognition第三方包安装失败 亲测有效的解决方法:whl安装方式 dilb和face_recognition第三方包安装失败 场景复现:因为需要用到dlibface_recognition,基于OpenCV做一些人脸识别的项目,在Pycharm中进行pip清华…...
Mac系统Mysql的8.0.22版本安装笔记和密码重置修改密码等问题方法
忘记密码官网教程地址:https://dev.mysql.com/doc/refman/5.7/en/resetting-permissions.html 5.7数据库安装指南参考:https://jingyan.baidu.com/article/fa4125ac0e3c2928ac709204.html 初次安装8.0.22遇到许多坑,密码修改失败;…...
驱动 | Linux | NVMe 不完全总结
本文主要参考这里 1’ 2 的解析和 linux 源码 3。 此处推荐一个可以便捷查看 linux 源码的网站 bootlin 4。 更新:2022 / 02 / 11 驱动 | Linux | NVMe 不完全总结NVMe 的前世今生从系统角度看 NVMe 驱动NVMe CommandPCI 总线从架构角度看 NVMe 驱动NVMe 驱动的文件…...
一个测试人员,在现阶段的环境下如何在测试行业发展和自我价值。
前言周末和几个测试圈子里的大佬饭局上聊了一些职场和测试职业发展相关的话题,我将聊天的内容做了整理和阐述。。朋友圈有测试同学对这篇文章提了比较深刻的建议,下面是他的评价和建议:评价:据说是大佬饭桌总结,有两点…...
pwn手记录题2
fastbin_reverse_into_tcache(2.34) 本题所使用的libc版本为2.34;(最新版 libc2.34版本已经没有了所谓的hook函数,甚至exit_hook(实际为某个函数指针)也已经不能够使用;能够利用的手法已经很少了; 高版本glibc堆的几…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
