鱼眼相机模型与去畸变实现
1.坐标系说明
鱼眼相机模型涉及到世界坐标系、相机坐标系、图像坐标系、像素坐标系之间的转换关系。对于分析鱼眼相机模型,假定世界坐标系下的坐标点,经过外参矩阵的变换转到相机坐标系
,相机坐标再经过内参转换到像素坐标,具体如下

进一步进行变换得到如下

坐标(i, j)位置对应的就是无畸变图中的像素坐标。
那么在已知像素坐标时,根据上述表达式就能得到归一化的相机坐标 .实际计算时,可以用内参矩阵求逆也可以直接变换得到。
xw = K_matrix_inv.dot(np.array([i, j, 1], dtype=float))x_d = xw[0]y_d = xw[1]x = float(i)y = float(j)x1 = (x - cx) / fx # 求出ud ==> x1y1 = (y - cy) / fy # 求出vd ==> y1# x == x1, y == y1
2.opencv实现
分析opencv鱼眼矫正最重要的函数是fisheye::initUndistortRectifyMap(),它能得到map1矩阵。对应opencv-python,
map1, map2 = cv2.initUndistortRectifyMap(camera_matrix, dist_coeffs, None, new_camera_matrix, (w, h), cv2.CV_32FC1)
map1是一个2通道矩阵,它在(i, j)处的二维向量元素(u, v) = (map1(i, j)[0], map1(i, j)[1])的意义如下:
将畸变图像中(u, v) = (map1(i, j)[0], map1(i, j)[1])的元素,复制到(i, j)处,就得到了无畸变图像。
opencv官方给出的实现过程如下:

3.去畸变理论分析
鱼眼相机的入射与反射示意图如下图所示。对于相机坐标系下有一点 ,如果按照针孔相机模型投影,则不存在畸变,像点为
,发生畸变后的像点坐标为
。
在图中,.

在上图中不妨假设 ,最终可以求得
和
的比值(与
无关),从而可求得去畸变后的
点坐标
以及入射角
. 这里的
实际就是对应于
的齐次坐标。
实际的鱼眼镜头因为各种原因并不会精确的符合投影模型,为了方便鱼眼相机的标定,一般取关于
泰勒展开式的前5项来近似鱼眼镜头的实际投影函数。具体来说,该近似结果最早由
Juho Kannala 和 Sami S. Brandt在《A Generic Camera Model and Calibration Method for Conventional, Wide-Angle, and Fish-Eye Lenses》论文中提出了一种一般的鱼眼模型,也是opencv和一般通常使用的模型,用入射角 的奇数次泰勒展开式来进行鱼眼模型的通用表示:
通常设置,使得相应的变化在后续的含
高次项目中体现,由此得到
结合发生畸变后对应的归一化相机坐标,可以求出
.
注意,这里的,根据示意图可知,无论采用通用模型还是等距投影模型,都严格存在如下
对于 ,则有:
实际计算过程,都是已知无畸变的像素坐标(i,j) 推导得到畸变后的像素坐标(u,v),再借助remap函数完成像素插值。当需要通过已知的畸变像素坐标反向投影得到无畸变点的像素时,也就是已知,采用上述关系得到
,此时已知
, 需要求出对应的
。所以畸变矫正的本质问题是求解关于
的一元高次方程
常见求解一元高次方程的方法有二分法、不动点迭代、牛顿迭代法。这里采用牛顿迭代法求解。
令 ,
循环迭代直到(具体精度根据需要自行设置,比如设置阈值1e-6),或达到迭代次数上限。求得
之后,未畸变像点
的坐标满足
详见下文4.3代码。
4.代码实现
4.1 调用opencv
def undistort_imgs_fisheye(camera_matrix, dist_coeffs,img):# 注意:OpenCV 没有直接提供逆畸变的函数,但我们可以使用 cv2.initUndistortRectifyMap 和 cv2.remap 来模拟w = int(img.shape[1])h = int(img.shape[0])border_width = int(w/4)border_height = int(h/4)img_bordered = cv2.copyMakeBorder(img, border_height, border_height, border_width, border_width, cv2.BORDER_ISOLATED)h_new, w_new = img_bordered.shape[:2]new_camera_matrix1, roi = cv2.getOptimalNewCameraMatrix(camera_matrix, dist_coeffs[:4], (w_new, h_new), 0.5, (w, h))# 计算去畸变和逆畸变的映射map1, map2 = cv2.fisheye.initUndistortRectifyMap(camera_matrix, dist_coeffs[:4], np.eye(3), new_camera_matrix1, (w_new, h_new), cv2.CV_16SC2)#根据CV_16SC2, map1此时是一个2通道的矩阵,每个点(i, j)都是一个2维向量, u = map1(i, j)[0], v= map1(i, j)[1],畸变图中坐标为(u, v)的像素点,在无畸变图中应该处于(i, j)位置。undistort_img = cv2.remap(img_bordered, map1, map2, cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)return undistort_img
4.2 表达式实现
def undistort_imgs_fisheye_equid(params_matrix, distort, img):fx = params_matrix[0][0]fy = params_matrix[1][1]cx = params_matrix[0][2]cy = params_matrix[1][2]distortion_params = distortkk = distortion_paramswidth = int(img.shape[1] * 1)height = int(img.shape[0] * 1)print("w is: {}, h is: {}".format(width,height))mapx = np.zeros((width, height), dtype=np.float32)mapy = np.zeros((width, height), dtype=np.float32)for i in tqdm(range(0, width), desc="calculate_maps"):for j in range(0, height):x = float(i) #x是去畸变后的像素坐标y = float(j) #y是去畸变后的像素坐标a = (x - cx) / fx # x ==> ab = (y - cy) / fy # y ==> br = np.sqrt(a**2 + b**2)theta = np.arctan2(r,1)rd = (1.0 *theta + kk[0] * theta**3 + kk[1] * theta**5 + kk[2] * theta**7 + kk[3] * theta**9)scale = rd/r if r!=0 else 1.0x2 = fx * a * scale + cx # width // 2y2 = fy *b * scale + cy # height // 2mapx[i, j] = x2mapy[i, j] = y2distorted_image = cv2.remap(img,mapx.T,mapy.T,interpolation=cv2.INTER_LINEAR,borderMode=cv2.BORDER_CONSTANT,)return distorted_image, params_matrix
4.3 反向投影
def diff(k2, k3, k4, k5, theta):theta_2 = theta * thetatheta_4 = theta_2 * theta_2theta_6 = theta_4 * theta_2theta_8 = theta_6 * theta_2rd_diff = 1 + 3 * k2 * theta_2 + 5 * k3 * theta_4 + 7 * k4 * theta_6 + 9 * k5 * theta_8return rd_diffdef distort_theta(k2, k3, k4, k5, theta):theta_2 = theta * thetatheta_3 = theta * theta_2theta_5 = theta_3 * theta_2theta_7 = theta_5 * theta_2theta_9 = theta_7 * theta_2theta_d = theta + k2 * theta_3 + k3 * theta_5 + k4 * theta_7 + k5 * theta_9return theta_ddef newton_itor_theta(k2, k3, k4, k5, r_d):theta = r_dmax_iter = 500for i in range(max_iter):diff_t0 = diff(k2, k3, k4, k5, theta)f_t0 = distort_theta(k2, k3, k4, k5, theta) - r_dtheta = theta - f_t0 / diff_t0if abs(f_t0) < 1e-6:breakreturn thetadef distort_imgs_fisheye_new(params_matrix, distort, img):undistorted_image = np.zeros((img.shape))fx = params_matrix[0][0]fy = params_matrix[1][1]cx = params_matrix[0][2]cy = params_matrix[1][2]K_matrix_inv = np.linalg.inv(params_matrix)width = int(img.shape[1] * 1)height = int(img.shape[0] * 1)mapx = np.zeros((width, height), dtype=np.float32)mapy = np.zeros((width, height), dtype=np.float32)for i in tqdm(range(0, width), desc="calculate_maps"):for j in range(0, height):xw = K_matrix_inv.dot(np.array([i, j, 1], dtype=float))x_d = xw[0]y_d = xw[1]x = float(i)y = float(j)x1 = (x - cx) / fx # 求出ud ==> x1y1 = (y - cy) / fy # 求出vd ==> y1phi = np.arctan2(y_d, x_d)r_d = np.sqrt(x_d ** 2 + y_d ** 2)theta = newton_itor_theta(distort[0],distort[1],distort[2],distort[3],r_d)r = np.tan(theta)# r_d = np.tan(theta_d)a = x_d * r/r_db = y_d * r/r_du = a*fx + cxv = b*fy + cymapx[i, j] = umapy[i, j] = vreturn mapx, mapy
相关文章:
鱼眼相机模型与去畸变实现
1.坐标系说明 鱼眼相机模型涉及到世界坐标系、相机坐标系、图像坐标系、像素坐标系之间的转换关系。对于分析鱼眼相机模型,假定世界坐标系下的坐标点,经过外参矩阵的变换转到相机坐标系,相机坐标再经过内参转换到像素坐标,具体如下 进一步进…...
【Unity功能集】TextureShop纹理工坊(七)魔棒工具
项目源码:在终章发布 索引 魔棒工具PS魔棒工具魔棒工具功能点提炼TextureShop魔棒工具根据色差选取非连续区域中间镂空边框的流动虚线取消选区魔棒工具 魔棒工具,也既是通过颜色色差,在图像上选出自定义选区的工具(了解PS魔棒工具)。 PS魔棒工具 我们先来看看PS中的魔棒…...
ASP.NET Core Web API Hangfire
ASP.NET Core Web API Hangfire 前言一、安装二、相关代码1.代码片段2.代码片段3.运行效果 三、测试代码1.即发即弃作业2.延迟作业3.重复作业4.延续作业5.页面调度作业 前言 👨💻👨🌾📝记录学习成果,以…...
E-commerce .net+React(一)——项目初始化
文章目录 项目地址一、创建.Net环境1.1环境配置1.1.1 使用vscode创建webapi1.1.2 Clean architecture结构创建1.1.3 将创建好结构的项目添加到git里1.1.4 EF Core配置1. 在infrastructure里安装EF所需环境2. 创建Product数据模型3. 创建EF Core的DbContext 数据库上下文4. 创建…...
算法每日双题精讲 —— 滑动窗口(水果成篮,找到字符串中所有字母异位词)
🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟 别再犹豫了!快来订阅我们的算法每日双题精讲专栏,一起踏上算法学习的精彩之旅吧!💪…...
C++ 设计模式:享元模式(Flyweight Pattern)
链接:C 设计模式 链接:C 设计模式 - 单例模式 享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享尽可能多的相同对象来减少内存使用和提高性能。享元模式适用于大量细粒度对象的场景,这些对象之…...
Docker+Portainer 离线安装
1. Docker安装 步骤一:官网下载 docker 安装包 步骤二:解压安装包; tar -zxvf docker-24.0.6.tgz 步骤三:将解压之后的docker文件移到 /usr/bin目录下; cp docker/* /usr/bin/ 步骤四:将docker注册成系统服务; vim /etc/sy…...
Linux第100步_Linux之设置LCD作为终端控制台和LCD背光调节
KMS是Kemmel Mode Setting的缩写,内核显示模式设置。它主要负责显示的控制,包括屏幕分辨率、屏幕刷新率和颜色深度等等。 CRTC是指显示控制器,在DRM里有多个显存,通过操作CRTC来控制要显示那个显存。 KMS包含了FB框架。DRM驱动默…...
Chapter09 国际化i18n 和 数据校验:Validation
文章目录 1 Java国际化2 Spring6国际化3 使用Spring6国际化4 数据校验:Validation实验一:通过Validator接口实现实验二:Bean Validation注解实现实验三:基于方法实现校验实验四:实现自定义校验 1 Java国际化 示例&…...
活动预告 | Microsoft 安全在线技术公开课:通过扩展检测和响应抵御威胁
课程介绍 通过 Microsoft Learn 免费参加 Microsoft 安全在线技术公开课,掌握创造新机遇所需的技能,加快对 Microsoft Cloud 技术的了解。参加我们举办的“通过扩展检测和响应抵御威胁”技术公开课活动,了解如何更好地在 Microsoft 365 Defen…...
Unresolved plugin: ‘org.apache.maven.plugins:maven-site-plugin:3.12.1‘
问题 使用idea 社区办加载项目提示下面问题: Unresolved plugin: org.apache.maven.plugins:maven-site-plugin:3.12.1 问题解决 maven插件地址: https://maven.apache.org/plugins/maven-dependency-plugin/plugins.html Maven 中央仓库地址&#…...
5个开源RAG框架对比
还在为RAG应用开发头疼吗?别急,今天给大家推荐五款完全开源免费的RAG框架,覆盖自动优化、多模态处理、本地部署、生产环境支持等多种场景,助你轻松搞定RAG开发!👇 1. AutoRAG:自动优化ÿ…...
活动预告 | Microsoft Power Platform 在线技术公开课:实现业务流程自动化
课程介绍 参加“Microsoft Power Platform 在线技术公开课:实现业务流程自动化”活动,了解如何更高效地开展业务。参加我们举办的本次免费培训活动,了解如何借助 Microsoft AI Builder 和 Power Automate 优化工作流。结合使用这些工具可以帮…...
【分布式文件存储系统Minio】2024.12保姆级教程
文章目录 1.介绍1.分布式文件系统2.基本概念 2.环境搭建1.访问网址2.账号密码都是minioadmin3.创建一个桶4.**Docker安装miniomc突破7天限制**1.拉取镜像2.运行容器3.进行配置1.格式2.具体配置 4.查看桶5.给桶开放权限 3.搭建minio模块1.创建一个oss模块1.在sun-common下创建2.…...
解决ssh和git秘钥认证失败问题
已正确上传公钥到远程服务器,但是本地的连接认证还是使用默认秘钥文件名id_rsa或者默认用户名,导致了认证失败,总结了以下解决办法: 1、ssh秘钥认证 远程登录的时候可能ssh客户端默认使用id_rsa文件名秘钥,但是之前生…...
AI安全的挑战:如何让人工智能变得更加可信
引言 随着人工智能(AI)技术在各个领域的广泛应用,尤其是在医疗、金融、自动驾驶和智能制造等行业,AI正在重塑我们的工作和生活方式。从提高生产效率到实现个性化服务,AI带来了前所未有的便利。然而,在享受这…...
腾讯通RTX升级迁移攻略,兼容Linux内核国产系统及移动端
一、腾讯通RTX继续使用的主要难题 腾讯通RTX停更后,用户不仅无法继续获得更新、技术支持和资源下载,还面临着以下无法解决的使用问题: ● 不兼容国产系统与移动端:腾讯通RTX仅支持Windows和Mac操作系统,无法在基于Li…...
用css实现瀑布流布局
上效果 知识理解 column-count: 4; column-gap: 15px;实现固定四行瀑布流布局 columns: 200px auto;column-gap: 15px;由浏览器根据容器的宽度自动调整,尽可能一行多个200px宽度的列数 <!DOCTYPE html> <html lang"en"><head><me…...
FortiAl为擎重塑网络与安全运营未来
在当今数字化浪潮汹涌的时代,网络安全运营的重要性愈发凸显,而人工智能的迅猛发展则如同一股强劲的东风,为这一领域带来了革命性的变革。Fortinet攻防专家邹国雄在《FortiAI:以生成式人工智能(GenAI)简化Fo…...
优化租赁小程序提升服务效率与用户体验的策略与实践
内容概要 在这个快速发展的商业环境中,租赁小程序成为了提升服务效率和用户体验的重要工具。通过对用户需求的深入挖掘,我们发现他们对于功能的便捷性、响应速度和界面的友好性有着极高的期待。因此,针对这些需求,完善租赁小程序…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
