从开源项目聊鱼眼相机的“360全景拼接”

目录

概述

从360全景的背景讲起

跨过参数标定聊透视变化

拼接图片后处理

参考文献


概述

        写这篇文章的原因完全源于开源项目(GitHub参阅参考文献1)。该项目涵盖了环视系统的较为全貌的制作过程,包含完整的标定、投影、拼接和实时运行流程。该篇文章主要是梳理全景拼接技术中的一些实现细节,并在些地方记录了自己的思考。鉴于该开源项目,后续将计划:(1)基于自动驾驶车辆环视相机标定参数(内外参), 完成360全景拼接demo;(2)这篇文章要跳过的参数标定环节,后面要单独拿出篇幅详析。

从360全景的背景讲起

        百度百科:“360度全景倒车影像,是一套通过车载显示屏幕观看汽车四周360度全景融合,超宽视角,无缝拼接的适时图像信息(鸟瞰图像),了解车辆周边视线盲区,帮助汽车驾驶员更为直观、更为安全地停泊车辆的泊车辅助系统,又叫全景泊车影像系统或全景停车影像系统(有别于市面上把汽车四周画面在显示屏幕上进行分割显示的“全景”系统)。”

源自网络,如侵联删

        说的通俗些,360全景影像给人视觉上呈现的就是鸟瞰图,即从天空望车顶或者地面的俯视图,但俯视效果的实现是通过多个视角的照片拼接而成的。如下图所示,我们观察自己的车就能发现在车的前后左右四个方向上都有一个鱼眼相机,一般左右方向的鱼眼相机因为视野的问题布置在后视镜下方的比较多。

源自网络,如侵联删

        把四个鱼眼相机通过一定的方法拼接到一张图上,再把车辆照片贴到图片中央,就能近似形成完成的全景图像。下图所示的就是开源项目中所使用的的四路鱼眼相机的前、后、左、右方向的照片。

跨过参数标定聊透视变化

        写这篇文章的重点是要梳理如何从鱼眼图片透视变换为全景图片,相机的内外参标定跳过。要完成从单目鱼眼图到鸟瞰图的变化,最重要的一步骤就是完成如下从左图到右图的投影变换,也叫做透视变换。

        从左侧到右侧的变化是通过如下表达式实现的。我这里插一句,有同学将透视矩阵叫做外参,我认为这种说法是牵强的。为了说明这个问题,我们就先在世界坐标系下讨论,其他坐标系一样的道理。

源自网络,如侵联删
  1. 请参上式,基于将像素坐标反投回世界坐标系,需要内外参。所以即便透视后就是世界坐标,透视矩阵能只叫外参吗?
  2. 其次透视转换后得到的坐标定义为世界坐标是否合适?因为每个视角的透视变换是分离的,并不在同一坐标下。
  3. 还有像素坐标到世界坐标得到的是归一化平面下的世界坐标,非严格意义的世界坐标,那透视转换后得到的坐标定义为世界坐标是否准确?

        以上三个问题抛砖引玉,愿与大家探讨。我也计划分别针对“相机内参”和“实车全景拼接”再写两篇文章专门从数据上来验证这个事情。

引用自: Perspective Transformation | TheAILearner
引用自: Perspective Transformation | TheAILearner

        上面的公式解释了透视变换矩阵及其元素物理意义,感兴趣可直接到原文地址拜读。下面对于透视变换的图例描述的也挺形象的

引用自: Perspective Transformation | TheAILearner

        作者针对四路鱼眼图都进行了同样的透视变换。但在实施投影之前还有个重要的工作,就是图像去畸变,并在去畸变的过程中做一些视野范围的校正。

源自网络,如侵联删

        关于CV库去畸变方法中的矫正矩阵:参考上式,如果你推导过内参矩阵对应元素位置数值的话,应该很清楚在对应非零元素位置乘系数的作用就是:完成像素坐标在各轴线的放缩及平移。而在图像大小已定义的情况下,这个变化的作用无异于“裁剪”的效果。这样一来,就完成了去畸变的工作。

def update_undistort_maps(self):new_matrix = self.camera_matrix.copy()# 校正内参new_matrix[0, 0] *= self.scale_xy[0]new_matrix[1, 1] *= self.scale_xy[1]new_matrix[0, 2] += self.shift_xy[0]new_matrix[1, 2] += self.shift_xy[1]width, height = self.resolutionself.undistort_maps = cv2.fisheye.initUndistortRectifyMap(self.camera_matrix,self.dist_coeffs,np.eye(3),new_matrix,(width, height),cv2.CV_16SC2)return selfdef undistort(self, image):print("undistort_maps: ", self.undistort_maps)result = cv2.remap(image, *self.undistort_maps, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)return result

        进一步的我们开始处理透视变换:透视变换需要提供输入图片及其变换矩阵。变换矩阵的变换可参考源码,基本的道理就是假设真实世界中的标定布的尺寸缩放出几个点的对应坐标数值,将其作为dst、原鱼眼图片对应位置的坐标作为src,通过getPerspectiveTransform方法获取,此处不赘述,后续会写相关文章。 

def project(self, image):result = cv2.warpPerspective(image, self.project_matrix, self.project_shape)return result

        下一步要将各个视角的透视图拼起来:这里需要梳理清楚的主要是各个图的相对位置和方向的关系。由于各个视角的透视变换图都是单独处理的,相当于是摄像头的朝向,所以对于后方摄像头需要做中心变换贴在鸟瞰图的上方,左侧摄像头视图需要左旋放在左侧,右侧如法。

def flip(self, image):if self.camera_name == "front":return image.copy()elif self.camera_name == "back":return image.copy()[::-1, ::-1, :]elif self.camera_name == "left":return cv2.transpose(image)[::-1]else:return np.flip(cv2.transpose(image), 1)

拼接图片后处理

        最后阶段的鸟瞰图的拼接与平滑,不作为文章的重点赘述,但主要涉及到了几种策略:

birdview = BirdView()
Gmat, Mmat = birdview.get_weights_and_masks(projected)
birdview.update_frames(projected)
birdview.make_luminance_balance().stitch_all_parts()
birdview.make_white_balance()
birdview.copy_car_image()
  • 重叠区域中的像素值的加权平均处理
  • 为拼接图像的亮度一致性调整各区域的亮度
  • 通过色彩平衡改善摄像头不同通道的强度不同的问题

参考文献

[1]  https://github.com/neozhaoliang/surround-view-system-introduction

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/189566.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习数据预处理——Word2Vec的使用

引言: Word2Vec 是一种强大的词向量表示方法,通常通过训练神经网络来学习词汇中的词语嵌入。它可以捕捉词语之间的语义关系,对于许多自然语言处理任务,包括情感分析,都表现出色。 代码: 重点代码&#…

科技改变农业:合成数据农业中的应用

介绍 农业在我们的生活中起着至关重要的作用,它为我们提供了生存的食物。如今,它遇到了各种困难,例如气候变化的影响、缺乏工人以及全球流行病造成的中断。这些困难影响了耕作用水和土地的供应,而这些水和土地正变得越来越稀缺。…

PROFINET和UDP、MODBUS-RTU通信速度对比实验

这篇博客我们介绍PROFINET 和MODBUS-RTU通信实验时的数据刷新速度,以及这种速度不同对控制系统带来的挑战都有哪些,在介绍这篇对比实验之前大家可以参考下面的文章链接: S7-1200PLC和SMART PLC的PN智能从站通信 S7-200 SMART 和 S7-1200PLC进行PROFINET IO通信-CSDN博客文…

Adobe Photoshop 2020给证件照换底

1.导入图片 2.用魔法棒点击图片 3.点选择,反选 4.选择,选择并遮住 5.用画笔修饰证件照边缘 6. 7.更换要换的底的颜色 8.新建图层 9.使用快捷键altdelete键填充颜色。 10.移动图层,完成换底。

计算机中丢失msvcr120.dll文件怎么修复?找不到msvcr120.dll五种完美修复方案

今天我想和大家分享的是关于“msvcr120.dll丢失的问题的5个解决方法”。在我们日常的工作生活中,或许大家都曾遇到过这样的问题,那么,了解它的解决方法是非常必要的。 首先,让我们来了解一下msvcr120.dll是什么文件。简单来说&am…

基于springboot实现桥牌计分管理系统项目【项目源码】

基于springboot实现桥牌计分管理系统演示 JAVA简介 JavaScript是一种网络脚本语言,广泛运用于web应用开发,可以用来添加网页的格式动态效果,该语言不用进行预编译就直接运行,可以直接嵌入HTML语言中,写成js语言&#…

单链表按位序与指定结点 删除

按位序删除(带头结点) #define NULL 0 #include<stdlib.h>typedef struct LNode {int data;struct LNode* next; }LNode, * LinkList;//按位序删除&#xff08;带头结点&#xff09; bool ListInsert(LinkList& L, int i, int& e) {if (i < 1)return false;L…

js运算,笔试踩坑知识点

文章目录 前端面试系列运算符记住口诀先计算 后 赋值赋值从右向左 和 - -计算从左向右括号里的加减优先于括号外的乘除交换俩数的值答案 前端面试系列 js运算 笔试踩坑知识点 前端js面试题 &#xff08;三&#xff09; 前端js面试题&#xff08;二&#xff09; 前端js面试题 (…

基于SpringBoot的SSMP整合案例(开启日志与分页查询条件查询功能实现)

开启事务 导入Mybatis-Plus框架后&#xff0c;我们可以使用Mybatis-Plus自带的事务&#xff0c;只需要在配置文件中配置即可 使用配置方式开启日志&#xff0c;设置日志输出方式为标准输出mybatis-plus:global-config:db-config:table-prefix: tb_id-type: autoconfiguration:…

【原创课设】java+swing+mysql选课管理系统设计与实现

摘要&#xff1a; 随着学校规模的扩大和课程设置的多样化&#xff0c;传统的手工选课管理方式已经无法满足现代教育的需求。因此&#xff0c;开发一款高效、便捷的选课管理系统变得尤为重要。该系统可以提高选课工作的效率&#xff0c;减少人为错误&#xff0c;同时也能为学生…

工业摄像机参数计算

在工业相机选型的时候有点懵&#xff0c;有一些参数都不知道咋计算的。有些概念也没有区分清楚。‘’ 靶面尺寸 CMOS 或者是 CCD 使用几分之几英寸来标注的时候&#xff0c;这个几分之几英寸计算的是什么尺寸&#xff1f; 一开始我以为这个计算的就是靶面的实际对角线的尺寸…

nfs配置

1.NFS介绍 NFS就是Network File System的缩写&#xff0c;它最大的功能就是可以通过网络&#xff0c;让不同的机器、不同的操 作系统可以共享彼此的文件。 NFS服务器可以让PC将网络中的NFS服务器共享的目录挂载到本地端的文 件系统中&#xff0c;而在本地端的系统中来看&#…

【STM32】TIM2的PWM:脉冲宽度调制--标准库

注意点&#xff1a; TIM_Period---->指要进行比较的值Compare TIM_Prescaler----> 指要进行分频的值【分频值/原始时钟值】 PWM是一种周期固定&#xff0c;脉宽可调整的输出波形。 https://www.cnblogs.com/brianblog/p/7117896.html 0.通用寄存器输出 1.捕获/比较通道…

Docker从零开始学习,及常用命令大全(附带代码讲解)

Docker从零开始&#xff0c;及常用命令大全&#xff08;附带代码讲解&#xff09; docker是一种开源的应用容器引擎&#xff0c;可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化。…

Qt QtCreator调试Qt源码配置

目录 前言1、编译debug版Qt2、QtCreator配置3、调试测试4、总结 前言 本篇主要介绍了在麒麟V10系统下&#xff0c;如何编译debug版qt&#xff0c;并通过配置QtCreator实现调试Qt源码的目的。通过调试源码&#xff0c;我们可以对Qt框架的运行机制进一步深入了解&#xff0c;同时…

使用Redis实现热搜功能

Redis热搜 原理数据类型redis操作简单实现 实操封装方法执行方法最后使用springboot的定时任务对热搜榜单进行维护 原理 使用redis实现热搜的原理就是维护一个zset集合&#xff0c;然后使用score作为当前搜索词的搜索量&#xff0c;score越高的搜索词就说明该搜索词热度越高。…

设计模式之十一:代理模式

代理可以控制和管理访问。 RMI提供了客户辅助对象和服务辅助对象&#xff0c;为客户辅助对象创建和服务对象相同的方法。RMI的好处在于你不必亲自写任何网络或I/O代码。客户程序调用远程方法就和运行在客户自己本地JVM对对象进行正常方法调用一样。 步骤一&#xff1a;制作远程…

机器学习——朴素贝叶斯

目录 一、贝叶斯方法 背景知识 贝叶斯公式 二、朴素贝叶斯原理 判别模型和生成模型 1&#xff0e;朴素贝叶斯法是典型的生成学习方法 2&#xff0e;朴素贝叶斯法的基本假设是条件独立性 3&#xff0e;朴素贝叶斯法利用贝叶斯定理与学到的联合概率模型进行分类预测 用于文…

Redis为什么要使用SDS作为基本数据结构

Redis为什么要使用SDS作为基本数据结构 Redis SDS与C语言中字符串的对比二进制安全兼容部分C字符串函数 Redis SDS与C语言中字符串的对比 SDS中保存了字符串的长度属性&#xff0c;我们在获取字符串长度是的时间复杂度为O(1)&#xff0c;而C中字符串则需要对字符串进行遍历时间…

Lambertian模型(完美漫反射)

这里使用相乘的方式组合光照色和纹理色。根据这个模型,面朝光源的区域光照强度高,纹理色也相应增强。面背光源的区域光照弱,纹理色也被抑制。这样通过光照和纹理的结合,可以合成出具有照明效果的面部颜色,而不仅仅是固定的纹理本身的颜色。相乘方式可以近似实现不同光照方向下面…