单目与双目相机标定(一)

下面是几种常见的方法来获得三维点云重建的坐标系:

  1. 外部标定方法:在采集点云数据之前,通过使用已知尺寸和形状的校准物体在场景中放置特定的标记点或标定板。通过捕捉这些已知的标记点,可以建立一个参考坐标系,所有的点云数据都将相对于这个坐标系进行转换和合并。

  2. 内在参数和外在参数:对于基于摄像头的三维重建系统,首先需要通过相机标定的方式获取相机的内在参数(如焦距、主点等)和外在参数(相机相对于世界坐标系的位置和朝向)。这些参数可以用来将二维图像中的像素点转换为三维空间中的点,并建立一个全局坐标系。

  3. 迭代最近点(ICP)算法:在获得初步的三维点云之后,可以使用ICP算法来细化对齐和合并过程。ICP算法通过最小化两个点云之间的距离来优化它们之间的对齐,进而可以用来精确确定点云数据之间的相对位置和姿态,从而建立一个统一的坐标系。

  4. 多视图几何和结构从运动(SfM):结构从运动技术通过分析多个视角下的图像来估计摄像头的运动和场景的三维结构。这种方法不仅可以恢复出场景的三维结构,还可以确定相机视角之间的关系,进而构建一个全局坐标系。

  5. 深度学习方法:近年来,深度学习技术也被应用于三维重建和坐标系建立中,通过训练模型来预测点云数据或图像之间的空间关系,自动化地建立坐标系。

1. 相机标定

相机标定的目的是获取相机的内在参数(包括焦距、主点坐标、畸变系数等)和外在参数(相机相对于某些世界坐标系的位置和朝向)。为什么要进行相机标定呢?比如,当我们拿到一张图片,进行识别之后,得到的两部分之间的距离为多少多少像素,但是这多少多少像素究竟对应实际世界中的多少米呢?这就需要利用相机标定的结果来将像素坐标转换到物理坐标来计算距离(当然这里值得说明,仅仅利用单目相机标定的结果,是无法直接从像素坐标转化到物理坐标的,因为透视投影丢失了一个维度的坐标,所以测距其实需要双目相机)。

import numpy as np
import cv2
import glob# 准备标定板上角点的物理坐标,假设标定板正好在世界坐标系的原点,
# 例如,使用一个标准的棋盘格标定板,每个格子的大小为square_size,
# 棋盘格的大小为 (width, height)。
square_size = 1.0  # 实际测量的格子大小
width, height = 9, 6  # 内角点的数量
objp = np.zeros((width*height, 3), np.float32)
objp[:,:2] = np.mgrid[0:width,0:height].T.reshape(-1,2) * square_size# 保存角点的数组
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.# 读取图像文件
images = glob.glob('path/to/calibration/images/*.jpg')for fname in images:img = cv2.imread(fname)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 查找棋盘格角点ret, corners = cv2.findChessboardCorners(gray, (width,height), None)# 如果找到了,添加物理坐标和图像坐标if ret == True:objpoints.append(objp)imgpoints.append(corners)# 可以选择绘制并显示角点cv2.drawChessboardCorners(img, (width,height), corners, ret)cv2.imshow('img', img)cv2.waitKey(500)cv2.destroyAllWindows()# 标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)print("Camera matrix : \n")
print(mtx)
print("dist : \n")
print(dist)
print("rvecs : \n")
print(rvecs)
print("tvecs : \n")
print(tvecs)

cv2.calibrateCamera函数是OpenCV中用于相机标定的核心函数。它计算相机的内在参数(如焦距、主点坐标)和畸变系数,以及每个视图的旋转和平移向量。这些参数对于校正图像畸变、三维重建、物体定位等任务至关重要。

函数原型

 

ret, cameraMatrix, distCoeffs, rvecs, tvecs = cv2.calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs[, flags[, criteria]])

  • objectPoints:世界坐标系中的点。这是一个列表,其中每个元素是一个表示标定板上每个角点的三维点(X, Y, Z)的数组。对于每张标定图像,都有一个对应的点集。
  • imagePoints:图像坐标系中的点。这也是一个列表,其中每个元素是一个表示图像上对应角点的二维点(x, y)的数组。objectPointsimagePoints中的点必须是一一对应的。
  • imageSize:图像的大小。这应该是图像的宽度和高度,形式为(width, height)
  • cameraMatrix:输入/输出的相机内在参数矩阵。如果提供了初始估计值,标定算法会以此为基础进行优化。
  • distCoeffs:输入/输出的畸变系数。同样,如果提供了初始值,标定算法会进行优化。

返回值

  • ret:重投影误差,表示标定的质量。较小的值表示更好的标定结果。
  • cameraMatrix:优化后的相机内在参数矩阵。
  • distCoeffs:优化后的畸变系数。
  • rvecs:旋转向量,每张图像一个。表示将标定板从模型坐标系旋转到相机坐标系所需的旋转。
  • tvecs:平移向量,每张图像一个。表示将标定板从模型坐标系平移到相机坐标系所需的平移。

内部实现原理

相机标定的内部实现原理基于解决一个最小化重投影误差的优化问题。重投影误差是指在相机模型(包括内在参数、畸变系数、旋转和平移向量)下,将三维世界坐标点投影回二维图像平面上时,预测的图像点与实际观测到的图像点之间的距离。标定的目标是找到一组相机参数,使得这个误差最小。

  1. 初始估计:使用直接线性变换(DLT)或其他方法得到相机参数的初始估计。
  2. 优化:通过迭代优化方法(如Levenberg-Marquardt算法)调整相机参数,以最小化所有标定图像上的总重投影误差。
  3. 畸变校正:考虑畸变系数对图像点位置的影响,进一步优化这些系数以提高标定精度。

整个过程需要用户提供一组已知世界坐标系中位置的对象点(通常使用棋盘格的角点)和这些点在图像上的对应位置。通过分析这些点之间的几何关系,cv2.calibrateCamera能够计算出相机的内在参数和畸变系数,以及每张图像的视角(通过旋转和平移向量表示)。

[::-1]

  • 这是Python中的切片操作,用于反转序列。在这个上下文中,它被用来反转shape元组的元素顺序。
  • :表示选择序列中的所有元素,而-1作为步长值指示从后向前选择,即反向。
  • 因此,如果gray.shape返回(rows, columns),那么gray.shape[::-1]将返回(columns, rows)

使用场景

在图像处理和计算机视觉中,图像的尺寸经常需要以(width, height)的格式指定,而NumPy数组的shape属性则返回(height, width)格式的尺寸。因此,gray.shape[::-1]常用于将图像的尺寸从NumPy数组的形式转换为更通用的形式,特别是在调用需要(width, height)格式尺寸的OpenCV函数时。

例如,当使用cv2.calibrateCamera函数进行相机标定时,需要指定图像的尺寸。由于OpenCV期望的图像尺寸格式是(width, height),而gray.shape返回的是(height, width),所以使用gray.shape[::-1]来适配这个要求。

2.双目标定 

分别对双目的每个相机标定获得的外参通过代换推导得到双目相机中两个摄像头之间的相对位置关系。最终分别得到二者相对同一坐标系的旋转矩阵R和平移矩阵T能够使两个相机重合的过程。

立体校正的目的就是,利用立体标定所获得的参数将实际非共面行对准的两幅图像,校正成共面行对准。当两个图像平面是完全共面行对准时,立体匹配的效率更高且计算立体视差是最简单的。因为当两个图像平面是完全共面行对准时,立体匹配从二维搜索降至一维搜索,并且可以过滤掉无匹配点。但是,在现实的双目立体视觉系统中,是不存在完全的共面行对准的两个摄像机图像平面的,所以我们要进行立体校正(共面行对准是指:两摄像机图像平面在同一平面上,且同一点投影到两个摄像机图像平面时,应该在两个像素坐标系的同一行)

 

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

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

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

相关文章

【Java程序设计】【C00317】基于Springboot的智慧社区居家养老健康管理系统(有论文)

基于Springboot的智慧社区居家养老健康管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的智慧社区居家养老健康管理系统设计与实现,本系统有管理员、社区工作人员、医生以及家属四种角色权限 管…

Atcoder ABC341 D - Only one of two

Only one of two(只有两个中的一个) 时间限制:2s 内存限制:1024MB 【原题地址】 所有图片源自Atcoder,题目译文源自脚本Atcoder Better! 点击此处跳转至原题 【问题描述】 【输入格式】 【输出格式】 【样例1】 …

C语言--- 操作符详解(上)

目录 一.操作符的分类 1.算术操作符: - * / % 1. 和 - 2. * 3./ 4.% 2.移位操作符 3.位操作符 4.赋值操作符 1.连续赋值 2.复合赋值 5.单目操作符 1.和-- (1)前置 (2)后置 (3)前置…

用html编写的简易新闻页面

用html编写的简易新闻页面 相关代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document<…

【MySQL】表的约束 -- 详解

表中一定要有各种约束&#xff0c;通过约束让我们在未来插入数据库表中的数据是符合预期的。约束本质是通过技术手段倒逼程序员插入正确的数据&#xff0c;反过来站在 MySQL 的角度&#xff0c;凡是插入进来的数据都是符合数据约束的。约束的最终目标&#xff1a;保证数据的完整…

javaApI(Application Programming Interface)应用程序编程接口

ApI概念 Apl:指的是官方给开发人员提供的说明文档&#xff0c;对语言中有哪些类&#xff0c;类中有哪些方法进行说明 Objict 类 java.lang.Object 是java类体系结构中最顶层的类 Object可以表示java中任意的类 Object类中的方法 toString() 输出一个对象&#xff0c;但是…

在Ubuntu系统下搭建TDengine集群

目录 一、Ubuntu虚拟机创建 二、系统相关配置 1、设置系统hostname 2、网络配置及IP规划 3、配置FQDN&#xff08;etc/hosts&#xff09; 4、服务端口设置 三、TDengine server安装 1、服务安装 2、修改配置 3、启动taosd 4、服务卸载 四、客户端安装 1、client安…

大厂经验谈之OKR目标管理

前言 这是大厂经验谈系列第一篇文章,来看看互联网公司是如何制定和管理目标的。OKR是目前互联网公司经常采用的目标管理工具,最开始也是由国外著名公司推崇,比如Google、微软、亚马逊等,后面才逐步引入国内。既然是工具就有用得好和不好的地方,很多团队仍然把OKR当做KPI来…

vue2.0及起步(前端面试知识积累)

1、需要了解的vue概要知识 1、vue是什么&#xff1f; 一套用于构建用户界面的渐进式JavaScript框架。 为什么vue被称为是渐进式JS框架&#xff1f; 答&#xff1a;Vue允许开发者在不同的项目中以渐进式的方式使用它&#xff0c;这种渐进式表现在以下的方面&#xff1a; 逐步采…

这几个Python内置函数你都知道吗

divmod() divmod() 是一个 Python 内置函数&#xff0c;用于同时返回商和余数。它接受两个参数&#xff0c;第一个参数是被除数&#xff0c;第二个参数是除数&#xff0c;返回一个包含两个值的元组&#xff0c;第一个值是商&#xff0c;第二个值是余数。 示例用法如下&#…

【Simulink系列】——动态系统仿真 之 混合系统

声明&#xff1a;本系列博客参考有关专业书籍&#xff0c;截图均为自己实操&#xff0c;仅供交流学习&#xff01; 一、混合系统概述 由不同类型系统共同构成的系统称为混合系统&#xff01;仿真时必须考虑连续信号和离散信号的采样匹配问题&#xff0c;一般使用变步长连续求…

SpreadJS+vue3练手使用

SpreadJS的练手使用 // 首先在 package.json 这个文件里{"name": "app-admin","private": true,"version": "0.0.0","type": "module","scripts": {"dev": "vite",&quo…

【深度学习笔记】 3_13 丢弃法

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 3.13 丢弃法 除了前一节介绍的权重衰减以外&#xff0c;深度学习模型常常使用丢弃法&#xff08;dropout&#xff09;[1] 来应对过拟合…

阿里面试:最佳线程数,如何确定?

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、shein 希音、百度、网易的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 如何确定系统的最佳线程数&#xff1f; 小伙伴 没有回…

阿里云服务器ECS u1实例性能怎么样?

阿里云服务器ECS u1实例&#xff0c;2核4G&#xff0c;5M固定带宽&#xff0c;80G ESSD Entry盘优惠价格199元一年&#xff0c;性能很不错&#xff0c;CPU采用Intel Xeon Platinum可扩展处理器&#xff0c;购买限制条件为企业客户专享&#xff0c;实名认证信息是企业用户即可&a…

spring boot 集成科大讯飞星火认知大模型

一、安装依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/…

Educational Codeforces Round 160 (Rated for Div. 2) D. Array Collapse(笛卡尔树+DP)

原题链接&#xff1a;D. Array Collapse 题目大意&#xff1a; 给你一个长度为 n n n 的排列 p p p &#xff0c;排列的定义为 [ 1 , 2 , 3 , . . , n ] [1,2,3,..,n] [1,2,3,..,n] 中每个数都出现 恰好 一次。 你可以做 任意多次 这样的操作&#xff1a; 选出一个任意长度…

unity导航网格无法烘培到台阶和斜坡

如图是我在b站学Unity导航网格时建的一个示例场景&#xff0c;本场景使用的为棱长1m的立方体&#xff0c;读者可以以此为参照度量其他物体大小。 可见导航网格根本无法烘焙到斜坡和台阶上&#xff0c;为解决问题我做了不少尝试&#xff0c;调整最大坡度和步高都没办法解决问题…

AI新纪元:可能的盈利之道

本文来源于Twitter大神宝玉&#xff08;dotey&#xff09;在聊 Sora 的时候&#xff0c;总结了 Sora 的价值和可能的盈利方向&#xff0c;我把这部分内容单独摘出来再整理一下。现在的生成式 AI 大家应该不陌生&#xff0c;用它总结文章、翻译、写作、画图&#xff0c;当然真正…

搭建私有Git服务器:GitLab部署详解

引言&#xff1a; 为了方便团队协作和代码管理&#xff0c;许多组织选择搭建自己的私有Git服务器。GitLab是一个集成了Git版本控制、项目管理、代码审查等功能的开源平台&#xff0c;是搭建私有Git服务器的理想选择。 目录 引言&#xff1a; 一、准备工作 在开始部署GitLab之…