网易首页 > 网易号 > 正文 申请入驻

无人自动驾驶技术之使用OpenCV进行相机校准

0
分享至

照相机与摄像头,是机器人,人工智能,计算机视觉,工业自动化甚至娱乐行业等多个领域的组成部分。在我们使用此设备时,不仅要了解照相原理外,需要使用特殊的技术对摄像头进行相机校准,特别在自动化驾驶上,需要实时的对照相机进行校准操作

我们需要确定真实世界中3D点与其在该校准相机捕获的图像中其对应2D投影(像素)之间的精确关系所需的有关相机的所有信息(参数或系数)。

1、相机/镜头系统的内部参数。例如镜头的焦距,光学中心和径向畸变系数。

2、外部参数:这是指摄像机相对于某些世界坐标系的方向(旋转和平移)。

使用OpenCV进行相机校准

要了解校准过程,我们首先需要了解照相成像的几何原理。

为了轻松理解问题,我们假设在一个房间内部署了一个摄像头。

给定这个房间中的3D点P,我们想在相机拍摄的图像中找到该3D点的像素坐标(u,v)。

1.世界坐标系

世界坐标系和摄影机坐标系通过旋转和平移关联。

这六个参数(3个用于旋转,3个用于平移)称为相机的外部参数。

要定义房间中点的位置,我们首先需要为此房间定义一个坐标系。

原点:我们可以任意固定房间的一角作为原点

X,Y,Z轴:我们还可以沿着地板的两个维度定义房间的X和Y轴,并沿着垂直墙定义Z轴。

2.相机坐标系3.图像坐标系

显示了点P在图像平面上的投影。

通过对点的世界坐标进行旋转和平移,在相机的3D坐标系中获得点后,便可以将点投影到图像平面上,从而获得该点在图像中的位置。

当图像像素坐标系的原点位于左上角时,显示了一个更现实的场景。

固有相机矩阵需要考虑主要点的位置,轴的偏斜以及沿不同轴的潜在不同焦距。

将世界坐标系中的3D点投影到相机像素坐标的过程分为三个步骤。

  • 1、使用外部矩阵将3D点从世界坐标转换为摄像机坐标,该矩阵由两个坐标系之间的旋转和平移组成。

  • 2.摄像机坐标系中的新3D点使用内部矩阵投影到图像平面上,该矩阵由内部摄像机参数组成,例如焦距,光学中心等。

  • 3.要找到3D点在图像平面上的投影,我们首先需要使用外部参数(旋转)将点从世界坐标系转换为相机坐标系。

总之,相机校准算法具有以下输入和输出

输入:具有点的图像集合,这些点的2D图像坐标和3D世界坐标是已知的。

输出:3×3摄像机固有矩阵,每个图像的旋转和平移。

注意:在OpenCV中,相机固有矩阵没有偏斜参数。所以矩阵的形式是

通过以上的基础知识,我们开始我们的代码操作

步骤1:使用棋盘格图案定义现实世界的坐标

为什么在校准中广泛使用棋盘格图案?

棋盘图案独特且易于在图像中检测。不仅如此,棋盘上正方形的角对于它们的局部定位也是理想的,因为它们在两个方向上都有明显的渐变。此外,这些角还因为它们位于棋盘格线的交点而相关。所有这些事实均用于以棋盘格图案牢固地定位正方形的角。

第2步:从不同的角度捕获棋盘格的多个图像

接下来,我们保持棋盘格静止,并通过移动相机来拍摄棋盘格的多个图像。

或者,我们也可以保持相机恒定不变,并以不同的方向拍摄棋盘格图案。

步骤3:查找棋盘的二维坐标

现在,我们有多个棋盘图像。我们还知道世界坐标下棋盘上点的3D位置。我们需要的最后一件事是图像中这些棋盘格角的2D像素位置。

3.1查找棋盘角

OpenCV提供了一个内置函数findChessboardCorners ,该函数查找棋盘并返回角的坐标。

主要参数如下:

int cvFindChessboardCorners( const void* image, CvSize pattern_size,
CvPoint2D32f* corners, int* corner_count = NULL,
int flags = CV_CALIB_CB_ADAPTIVE_THRESH );
参数说明
Image: 输入的棋盘图,必须是8位的灰度或者彩色图像。
pattern_size: 棋盘图中每行和每列角点的个数。
Corners: 检测到的角点
corner_count: 输出,角点的个数。如果不是NULL,函数将检测到的角点的个数存储于此变量。
Flags: 各种操作标志,可以是0或者下面值的组合:
CV_CALIB_CB_ADAPTIVE_THRESH - 使用自适应阈值(通过平均图像亮度计算得到)
将图像转换为黑白图,而不是一个固定的阈值。
CV_CALIB_CB_NORMALIZE_IMAGE - 在利用固定阈值或者自适应的阈值进行二值化之前,
先使用cvNormalizeHist来均衡化图像亮度。
CV_CALIB_CB_FILTER_QUADS - 使用其他的准则(如轮廓面积,周长,方形形状)
来去除在轮廓检测阶段检测到的错误方块。
函数根据是否检测到图案,输出为真还是假。

3.2优化棋盘格角

良好的校准与精度有关。为了获得良好的结果,重要的是获得具有亚像素精度的角的位置。

OpenCV提供cornerSubPix功能,接收原始图像和拐角位置,并在原始位置的一个小邻域内寻找最佳拐角位置。该算法本质上是迭代的,因此我们需要指定终止条件(例如,迭代次数和/或精度)

主要参数如下:


void cv::cornerSubPix(
cv::InputArray image, // 输入图像
cv::InputOutputArray corners, // 角点(既作为输入也作为输出)
cv::Size winSize, // 区域大小为 NXN; N=(winSize*2+1)
cv::Size zeroZone, // 类似于winSize,但是总具有较小的范围,Size(-1,-1)表示忽略
cv::TermCriteria criteria // 停止优化的标准
参数解析:
第一个参数是输入图像,和cv::goodFeaturesToTrack()中的输入图像是同一个图像。
第二个参数是检测到的角点,即是输入也是输出。
第三个参数是计算亚像素角点时考虑的区域的大小,大小为NXN; N=(winSize*2+1)。
第四个参数作用类似于winSize,但是总是具有较小的范围,通常忽略(即Size(-1, -1))。
第五个参数用于表示计算亚像素时停止迭代的标准,可选的值有cv::TermCriteria::MAX_ITER 、cv::TermCriteria::EPS(可以是两者其一,或两者均选),
前者表示迭代次数达到了最大次数时停止,后者表示角点位置变化的最小值已经达到最小时停止迭代。二者均使用cv::TermCriteria()构造函数进行指定。

步骤4:校准相机

校准的最后一步是将世界坐标中的3D点及其在所有图像中的2D位置传递给OpenCV的calibrateCamera方法。

retval, cameraMatrix, distCoeffs, rvecs, tvecs = cv2.calibrateCamera(
objectPoints, imagePoints, imageSize)
第一个参数objectPoints,为世界坐标系中的三维点。
需要依据棋盘上单个黑白矩阵的大小,计算出(初始化)每一个内角点的世界坐标;
第二个参数imagePoints,为每一个内角点对应的图像坐标点;
第三个参数imageSize,为图像的像素尺寸大小
,在计算相机的内参和畸变矩阵时需要使用到该参数;
第四个参数cameraMatrix为相机的内参矩阵;
第五个参数distCoeffs为畸变矩阵;
第六个参数rvecs为旋转向量;
第七个参数tvecs为位移向量;
第八个参数flags为标定时所采用的算法。有如下几个参数:
CV_CALIB_USE_INTRINSIC_GUESS:
使用该参数时,在cameraMatrix矩阵中应该有fx,fy,u0,v0的估计值。否则的话,将初始化(u0,v0)图像的中心点,使用最小二乘估算出fx,fy。
CV_CALIB_FIX_PRINCIPAL_POINT:
在进行优化时会固定光轴点。当CV_CALIB_USE_INTRINSIC_GUESS参数被设置,光轴点将保持在中心或者某个输入的值。
CV_CALIB_FIX_ASPECT_RATIO:
固定fx/fy的比值,只将fy作为可变量,进行优化计算。
当CV_CALIB_USE_INTRINSIC_GUESS没有被设置,fx和fy将会被忽略。只有fx/fy的比值在计算中会被用到。
CV_CALIB_ZERO_TANGENT_DIST:设定切向畸变参数(p1,p2)为零。
CV_CALIB_FIX_K1,…,CV_CALIB_FIX_K6:对应的径向畸变在优化中保持不变。
CV_CALIB_RATIONAL_MODEL:计算k4,k5,k6三个畸变参数。
如果没有设置,则只计算其它5个畸变参数。
第九个参数criteria是最优迭代终止条件设定。

在使用该函数进行标定运算之前,需要对棋盘上每一个内角点的空间坐标系的位置坐标进行初始化,标定的结果是生成相机的内参矩阵cameraMatrix、相机的5个畸变系数distCoeffs,另外每张图像都会生成属于自己的平移向量和旋转向量。

利用求得的相机的内参和外参数据,可以对图像进行畸变的矫正,使用undistort函数实现,其函数原型如下

cv2.undistort()函数
第一个参数src,输入参数,代表畸变的原始图像;
第二个参数cameraMatrix,为之前求得的相机的内参矩阵;
第三个参数distCoeffs,为之前求得的相机畸变矩阵;
第四个参数dst,矫正后的输出图像,跟输入图像具有相同的类型和大小;
第五个参数newCameraMatrix,默认跟cameraMatrix保持一致;
完整代码:

根据以上的步骤,我们使用OpenCV来进行相机的校准操作

import cv2
import numpy as np
import os
import glob
# 定义checkboard的尺寸
CHECKERBOARD = (6,9)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# 保存checkerboard image 的 3D points
objpoints = []
# 保存checkerboard image 的 2D points
imgpoints = []
# 定义世界 坐标系3D points
objp = np.zeros((1, CHECKERBOARD[0]*CHECKERBOARD[1], 3), np.float32)
objp[0,:,:2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
prev_img_shape = None

代码截图

首先我们定义一下需要校准的初始化参数,包括世界坐标系以及checkboard的参数

# 获取所有图片的地址
images = glob.glob('./images/*.jpg')
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# findChessboardCorners函数,该函数查找棋盘并返回角的坐标
ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH+
cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)

if ret == True:
objpoints.append(objp)
# 接收原始图像和拐角位置,并在原始位置的一个小邻域内寻找最佳拐角位置
corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
imgpoints.append(corners2)
img = cv2.drawChessboardCorners(img, CHECKERBOARD, corners2,ret)

cv2.imshow('img',img)
cv2.waitKey(0)

代码截图

然后使用findChessboardCorners函数查找棋盘并返回角的坐标,然后使用cornerSubPix函数在原始位置的一个小邻域内寻找最佳拐角位置

cv2.destroyAllWindows()
h,w = img.shape[:2]
# calibrateCamera相机校准
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)

代码截图

经过以上步骤,便可以使用calibrateCamera函数对相机进行校准了,
我们也可以打印一下相机校准后的所有参数,到这里相机校准已经完成,
我们在校准后,需要对原始图片进行校正,使用到的函数便是undistort函数

# undistort对图像进行畸变的矫正
img = cv2.imread(images[0])
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
mapx,mapy=cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
cv2.imshow("undistorted image",dst)
cv2.waitKey(0)

代码截图

以上便是完整的相机校准的所有步骤,利用此步骤,我们可以使用到人工智能的自动化驾驶项目上,特别是一些车道线的检测,后期我们会介绍车道线的检测,哪里都需要相机校准的操作。

校准后的图片如下:

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
广东VS新疆万众瞩目!两大强援上演首秀,杜锋完整阵容拒绝爆冷

广东VS新疆万众瞩目!两大强援上演首秀,杜锋完整阵容拒绝爆冷

老叶评球
2026-03-07 21:16:35
小时候课本上猛夸的3个历史人物,长大后才发现:他们坏到骨子里

小时候课本上猛夸的3个历史人物,长大后才发现:他们坏到骨子里

收藏大视界
2026-03-07 18:11:42
伊朗仅允许中国船只通过霍尔木兹海峡?吴京的照片又发出来了

伊朗仅允许中国船只通过霍尔木兹海峡?吴京的照片又发出来了

历史总在押韵
2026-03-07 22:40:18
韦林顿缝了15针!姜至鹏道歉:看着触目惊心,我并非存心伤害对手

韦林顿缝了15针!姜至鹏道歉:看着触目惊心,我并非存心伤害对手

奥拜尔
2026-03-07 10:41:18
演员黄曼现状曝光!终于公开与李乃文真正关系,原来我们都被骗了

演员黄曼现状曝光!终于公开与李乃文真正关系,原来我们都被骗了

启迪你的思维
2026-02-23 20:37:56
人社部、财政部发布重要消息,2026年养老金上涨定了吗?了解下

人社部、财政部发布重要消息,2026年养老金上涨定了吗?了解下

云鹏叙事
2026-03-07 23:03:02
巴萨客战毕包:亚马尔、拉什福德首发,卡萨多、坎塞洛出战

巴萨客战毕包:亚马尔、拉什福德首发,卡萨多、坎塞洛出战

懂球帝
2026-03-08 03:01:32
养生长寿是骗局?Scienc研究:不管生活习惯好坏,顶多影响5年

养生长寿是骗局?Scienc研究:不管生活习惯好坏,顶多影响5年

思思夜话
2026-03-06 13:27:13
870万欧元,本周末米兰德比创造意甲历史单场票房纪录

870万欧元,本周末米兰德比创造意甲历史单场票房纪录

懂球帝
2026-03-08 03:01:32
成都一家三口滞留迪拜,平安回国后,被批炫富,遭遇网暴太心酸!

成都一家三口滞留迪拜,平安回国后,被批炫富,遭遇网暴太心酸!

眼光很亮
2026-03-07 22:31:07
室内大奖赛女60米决赛陈妤颉今年首冠 再创个人最佳升到历史前五

室内大奖赛女60米决赛陈妤颉今年首冠 再创个人最佳升到历史前五

威猛孟巍
2026-03-08 02:44:48
萨德被摧毁,美军要拿下伊朗领空?中东已接到通知,中方准备介入

萨德被摧毁,美军要拿下伊朗领空?中东已接到通知,中方准备介入

说历史的老牢
2026-03-07 04:30:58
记者:狄龙被逮捕并不是涉嫌酒驾,而是因为吸食大麻

记者:狄龙被逮捕并不是涉嫌酒驾,而是因为吸食大麻

懂球帝
2026-03-07 10:41:15
耿爽,有新职

耿爽,有新职

南方都市报
2026-03-06 16:43:06
验货成功!山东泰山葡萄牙中卫表现神勇 就等北京国安提高含金量

验货成功!山东泰山葡萄牙中卫表现神勇 就等北京国安提高含金量

80后体育大蜀黍
2026-03-07 23:46:25
伊朗顶住了,两大援军已到!特朗普宣布一件事,台当局坐不住了

伊朗顶住了,两大援军已到!特朗普宣布一件事,台当局坐不住了

各生欢喜者
2026-03-06 03:23:56
北京冷知识大公开,你知道几个

北京冷知识大公开,你知道几个

三农老历
2026-03-06 18:07:22
随着巴黎圣日耳曼爆冷1-3轰然倒下,法甲最新积分榜出炉

随着巴黎圣日耳曼爆冷1-3轰然倒下,法甲最新积分榜出炉

侧身凌空斩
2026-03-07 06:34:39
丹麦已成为世界上对乌克兰支持力度最高的国家

丹麦已成为世界上对乌克兰支持力度最高的国家

老马拉车莫少装
2026-02-03 18:38:36
一点别同情她!被教练性侵27次,却在奥运赛场上,把队友撞出赛道

一点别同情她!被教练性侵27次,却在奥运赛场上,把队友撞出赛道

来科点谱
2026-02-27 07:42:10
2026-03-08 04:43:00
人工智能研究所AI
人工智能研究所AI
python人工智能,大数据,人生苦短,我用python
153文章数 775关注度
往期回顾 全部

科技要闻

OpenClaw爆火,六位"养虾人"自述与AI共生

头条要闻

选举24小时内举行 伊朗今天或选出最高领袖

头条要闻

选举24小时内举行 伊朗今天或选出最高领袖

体育要闻

塔图姆298天走完这段路 只用27分钟征服这座城

娱乐要闻

汪小菲曝亲妈猛料,张兰公开财产分配

财经要闻

针对"不敢休、不让休"怪圈 国家出手了

汽车要闻

逃离ICU,上汽通用“止血”企稳

态度原创

教育
时尚
本地
游戏
手机

教育要闻

全国政协委员刘国梁建议通过体育锻炼加强挫折教育

2026春夏一定要拥有的6只包,好看又百搭

本地新闻

食味印象|一口入魂!康乐烤肉串起千年丝路香

外媒:Xbox新主机恐成微软绝唱!失败即退出硬件市场

手机要闻

网曝OPPO Find N6渲染图,或有橙色版本

无障碍浏览 进入关怀版