全景拼接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堆的几…...
CSS ~ 从入门到入坑。
CSS ~ 从入门到入坑。 文章目录CSS ~ 从入门到入坑。what。css 三种实现方式。选择器。id 选择器 > class 选择器 > 标签选择器。标签选择器。类选择器。id 选择器。层次选择器。后代选择器。子选择器。相邻兄弟选择器。通用选择器。结构伪类选择器。属性选择器。字体风格…...
成都哪家机构的Java培训比较好,求一个不坑的?
关于这个问题,相信你会得到很多条答案,以及很多家机构的自荐。既然如此,不如也了解一下老牌IT职业教育机构:有足够丰富的教学经验,丰富的教学产品资源以及成熟的就业保障体系,还有就是承担风险的能力。 很…...
《爆肝整理》保姆级系列教程python接口自动化(十二)--https请求(SSL)(详解)
简介 本来最新的requests库V2.13.0是支持https请求的,但是一般写脚本时候,我们会用抓包工具fiddler,这时候会 报:requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590) 小编…...
离线数据仓库
1 数据仓库建模 1.1 建模工具 PowerDesigner/SQLYog/EZDML… 1.2 ODS层 (1)保持数据原貌不做任何修改,起到备份数据的作用。 (2)数据采用压缩,减少磁盘存储空间(例如:压缩采用LZO&…...
【前端】Vue项目:旅游App-(23)detail:房东介绍、热门评论、预定须知组件
文章目录目标过程与代码房东介绍landlord热门评论HotComment预定须知Book效果总代码修改或添加的文件detail.vuedetail-book.vuedetail-hotComment.vuedetail-landlord.vue参考本项目博客总结:【前端】Vue项目:旅游App-博客总结 目标 根据detail页面获…...
JUC并发编程与源码分析
一、本课程前置知识及要求说明 二、线程基础知识复习 三、CompletableFuture 四、说说Java"锁"事 8锁案例原理解释: 五、LockSupport与线程中断 六、 Java内存模型之JMM 七、volatile与JMM 八、CAS 九、原子操作类之18罗汉增强 十、聊聊ThreadLocal 十一、Java对…...
Spark09: Spark之checkpoint
一、checkpoint概述 checkpoint,是Spark提供的一个比较高级的功能。有时候,我们的Spark任务,比较复杂,从初始化RDD开始,到最后整个任务完成,有比较多的步骤,比如超过10个transformation算子。而…...
《剑指offer》:数组部分
一、数组中重复的数字题目描述:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1…...
基于微信小程序图书馆座位预约管理系统
开发工具:IDEA、微信小程序服务器:Tomcat9.0, jdk1.8项目构建:maven数据库:mysql5.7前端技术:vue、uniapp服务端技术:springbootmybatis本系统分微信小程序和管理后台两部分,项目采用…...
剑指 Offer Day1——栈与队列(简单)
本专栏将记录《剑指 Offer》的刷题,传送门:https://leetcode.cn/study-plan/lcof/。 目录剑指 Offer 09. 用两个栈实现队列剑指 Offer 30. 包含min函数的栈剑指 Offer 09. 用两个栈实现队列 原题链接:09. 用两个栈实现队列 class CQueue { pu…...
佛山网站建设收费标准/小程序引流推广平台
北漂未及三月,最最心累的不仅仅从未接触过的工作(怎么就从C开发转到大数据开发了),还有让人一筹莫展、咬牙切齿的租房问题。 一筹莫展 我算是运气比较差的那一部分人了,对象在银行,本来在北京可以直接租个一…...
成都市网站公司/百度竞价排名展示方式
本来很久就已经注册了这博客,可到了今天才发现原来我错过了这么多,原来的很多的知识点都在这里可以学到,也是所谓的理解恨晚啊!其实也对我上一篇文章所说的定位有跳板吧,反而让我现在浪费了快一年的时间,今年身为应届生的我,第一次在石狮找工作,一是离学校很近,学校…...
网站建设链接演示/东莞搜索优化
ssh -p2016 apache10.10.18.130 /bin/sh /data/www/vhosts/WOStest3_ENV/update_env.sh 需要设置shell远程免密码登录 转载于:https://www.cnblogs.com/ai594ai/p/7306402.html...
wordpress iframe插件/品牌推广外包公司
人社部公告,正式将互联网营销师列入中国新十大职业,成为国家认证的新兴职业。 互联网营销师,简单讲,其实就是指直播带货主播,代表就是李佳琪。薇娅,散打哥,辛巴,罗永浩等网红大佬&…...
做公司网站写什么信息/我想做网络推广
oracle的架构大概分为3部分, 客户端:用户端 oracle instance:叫做实例,由内存结构(内存池或者叫SGA)和后台进程组成。Oracle Instance是Oracle RDBMS的核心之一,负责RDBMS的管理功能。内存结构有…...
做网站无需备案/做网站企业
本篇文章给大家带来的内容是关于如何清理浮动?清除浮动的4种方式,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。套路1:给浮动元素的父元素添加高度(扩展性不好)如果一个元素要浮动,那么它…...