opencv实战项目二十四:棋盘格相机内参标定

news2024/9/22 10:10:12

文章目录

  • 前言
  • 一、简介:
  • 二、使用步骤
    • 2.1制作标定板
    • 2.2 拍摄不同角度的标定板
    • 2.3计算棋盘格角点并优化
    • 2.4计算相机参数
  • 三、整体代码实现:


前言

在数字图像处理和计算机视觉领域,相机标定是一个至关重要的步骤。它为相机提供了一个准确的数学模型,使我们能够从二维图像中准确地恢复三维世界信息。而在众多标定方法中,使用棋盘格图案进行相机内参标定无疑是最经典且广泛采用的技术之一。
在这篇博客中,我们将深入探讨棋盘格相机内参标定的原理、步骤及其在实际应用中的重要性。我们将详细介绍如何使用棋盘格图案来获取相机的内参矩阵,包括焦距、主点坐标以及镜头畸变系数等关键参数并通过Opencv实现它。


一、简介:

相机内参标定是图像处理和计算机视觉领域中的一个重要步骤,其必要性可以从以下几个方面进行介绍:

  • 校正镜头畸变:相机镜头通常存在一定的光学畸变,主要包括径向畸变和切向畸变。这些畸变会导致图像中的直线变弯,或者图像的某些部分相对于其他部分发生形变。通过内参标定,可以准确估计这些畸变参数,从而在后续的图像处理中对畸变进行校正。
  • 提高测量精度:在需要进行尺寸测量或三维重建的应用中,如工业检测、机器人导航等,准确的相机内参是必不可少的。内参标定提供了相机的焦距、主点位置等参数,这些参数对于从图像中提取准确的空间信息至关重要。
  • 统一图像坐标系:相机内参标定有助于将图像坐标转换到统一的坐标系中。这对于多相机系统或需要将不同时间或不同角度拍摄的图像进行拼接的场景尤为重要。
  • 优化算法性能:许多计算机视觉算法,如特征匹配、视觉SLAM(Simultaneous Localization andMapping)、立体视觉等,都依赖于相机的内参来进行优化。准确的内参可以显著提高这些算法的性能和鲁棒性。
  • 消除系统误差:相机内参标定有助于消除由于相机硬件特性引起的系统误差,从而提高图像质量和算法结果的可靠性。
  • 适应不同场景:不同的相机和镜头组合会有不同的内参。即使是同一相机,在不同的拍摄条件下(如不同的焦距、光圈设置),其内参也可能有所不同。因此,针对具体应用场景进行内参标定是必要的。

进行相机内参标定是为了确保相机成像系统的准确性和一致性,这对于依赖高质量图像数据进行进一步处理的计算机视觉应用来说是至关重要的。

二、使用步骤

2.1制作标定板

标定板制作可以点击此处:
在这里插入图片描述
选择好之后,点击图像下面的保存标定板作pdf即可,然后用a4纸打印

2.2 拍摄不同角度的标定板

保持相机的位置不变,移动标定板用来拍摄不同角度的图片,将图片放入一个文件夹下:
在这里插入图片描述

在这里插入图片描述

2.3计算棋盘格角点并优化

通过函数cv2.findChessboardCorners计算角点,函数 cv2.findChessboardCorners 是 OpenCV 库中的一个函数,用于检测图像中的棋盘格角点。这个函数在相机标定过程中非常关键,因为它能够帮助我们从标定图像中提取出用于计算相机内参的角点坐标。下面是对该函数及其参数的详细介绍:retval, corners = cv2.findChessboardCorners(image, patternSize, flags=None)

参数:
image: 输入图像,通常是灰度图像,因为它简化了处理过程并提高了角点检测的准确性。
patternSize: 一个元组,表示棋盘格的内部角点数量。例如,对于一个 6x9 的棋盘格,这个参数应该是 (5, 8),因为棋盘格内部的角点数是 5x8。
flags: 这个参数是可选的,用于指定各种操作标志,以优化角点检测过程。以下是一些可用的标志:
cv2.CALIB_CB_ADAPTIVE_THRESH: 使用自适应阈值来寻找角点,有助于在光照不均匀的条件下提高检测的鲁棒性。
cv2.CALIB_CB_NORMALIZE_IMAGE: 在处理之前对图像进行归一化,减少光照变化的影响。
cv2.CALIB_CB_FILTER_QUADS: 使用额外的标准(如角度、间隔、消失点的一致性)来过滤和保留可能的角点。
cv2.CALIB_CB_FAST_CHECK: 执行一个快速的检查,以确定图像中是否确实存在一个棋盘格。
返回值:
retval: 布尔值,表示是否找到了足够的角点。如果找到了足够的角点,则返回 True;否则返回 False。
corners: 检测到的角点的数组。每个角点由一个二维坐标表示,这些坐标是相对于输入图像的。

在获取到棋盘格每个角点之后,可以使用cv2.cornerSubPix ()对角点进行优化cv2.cornerSubPix 是 OpenCV 库中的一个函数,用于对已检测到的角点进行亚像素级精化。在计算机视觉中,尤其是在相机标定和特征点跟踪等应用中,提高角点坐标的精度是非常重要的。
cv2.cornerSubPix(image, corners, winSize, zeroZone, criteria)

参数:
image: 输入图像,通常是灰度图像。
corners: 一个数组,包含了初始检测到的角点的坐标。这些坐标通常是由 cv2.findChessboardCorners 或其他角点检测函数提供。
winSize: 窗口大小,用于考虑角点周围的像素。这个窗口用于计算角点的精确位置。通常,这个窗口大小应该足够大,以覆盖角点周围的区域,但又不能太大,以避免引入过多的噪声。
zeroZone: 这个参数是可选的,它指定了窗口内部的一个零区域,在这个区域内不进行像素值的加权计算。这有助于在某些情况下提高算法的稳定性。如果不需要,可以设置为 (-1, -1)。
criteria: 这个参数定义了迭代过程的停止准则。它是一个包含三个元素的元组 (type, maxCount, epsilon),其中:
type 是停止条件的类型,可以是 cv2.TERM_CRITERIA_EPS(达到指定的精度 epsilon)或 cv2.TERM_CRITERIA_MAX_ITER(达到最大迭代次数 maxCount)或两者的组合。
maxCount 是最大迭代次数。
epsilon 是所需的精度。
返回值:
函数没有直接的返回值,但它会直接修改输入的 corners 数组,填充更精确的角点坐标。

在检测到图像的角点后可以对它进行绘制,可以知道图像角点找的对不对,使用cv2.drawChessboardCorners可以绘制棋盘格角点,cv2.drawChessboardCorners(image, patternSize, corners, found)

参数:
image: 输入图像,通常是灰度图像。
patternSize: 一个元组,表示棋盘格的内部角点数量。例如,对于一个 6x9 的棋盘格,这个参数应该是 (5, 8),因为棋盘格内部的角点数是 5x8。
corners: 一个数组,包含了检测到的角点的坐标。这些坐标是相对于输入图像的。
found: 一个布尔值,表示是否找到了足够的角点。如果找到了足够的角点,则 found 为 True;否则为 False。
返回值:
函数没有直接的返回值,但它会直接修改输入的 image 数组,在其中绘制角点。

ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH +
                                             cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE)
    """
    使用cornerSubPix优化探测到的角点
    """
    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)

效果:
在这里插入图片描述

2.4计算相机参数

在获得精确的角点之后,就可以通过cv2.calibrateCamera获取相机自身的参数了,cv2.calibrateCamera 是 OpenCV 库中的一个函数,用于根据一系列带有标定板的图像来计算相机的内参(intrinsic parameters)和畸变系数(distortion coefficients)。这个函数是相机标定的核心步骤,它可以帮助我们理解相机的成像特性,并为后续的图像处理和三维重建等任务提供准确的相机模型。retval, cameraMatrix, distCoeffs, rvecs, tvecs = cv2.calibrateCamera(objectPoints, imagePoints, imageSize, None, None)

参数:
objectPoints: 一个数组,包含了所有标定图像中棋盘格在世界坐标系中的三维坐标。这些坐标通常是通过标定板上的角点坐标计算得到的。
imagePoints: 一个数组,包含了所有标定图像中棋盘格在图像平面上的二维坐标。这些坐标通常是由 cv2.findChessboardCorners 函数提供的。
imageSize: 一个元组,表示输入图像的尺寸。这通常是 (width, height) 格式。
cameraMatrix: 一个可选的参数,用于指定相机的内参矩阵。如果未指定,OpenCV 将使用默认值。
distCoeffs: 一个可选的参数,用于指定相机的畸变系数。如果未指定,OpenCV 将使用默认值。
返回值:
retval: 布尔值,表示标定是否成功。如果成功,返回 True;否则返回 False。
cameraMatrix: 一个浮点数数组,表示相机的内参矩阵。这个矩阵包含了焦距、主点坐标等信息。
distCoeffs: 一个浮点数数组,表示相机的畸变系数。这些系数用于描述镜头畸变。
rvecs: 一个浮点数数组,包含了所有标定图像中相机相对于世界坐标系的位置和方向。
tvecs: 一个浮点数数组,包含了所有标定图像中相机相对于世界坐标系的位置。

三、整体代码实现:

import glob

import cv2
import numpy as np
from PIL import Image

# 8行11列棋盘角点
CHECKERBOARD = (8, 11)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# 世界坐标中的3D角点,z恒为0
objpoints = []
# 像素坐标中的2D点
imgpoints = []

# 利用棋盘定义世界坐标系中的角点
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)

# 从文件夹中读取所有图片
images = glob.glob(r'F:\cccc/*.png')
print(images)
gray = None
for i in range(len(images)):
    fname = images[i]
    print(fname)
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 查找棋盘角点
    ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH +
                                             cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE)
    """
    使用cornerSubPix优化探测到的角点
    """
    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)
        # new_img = Image.fromarray(img.astype(np.uint8))
        # new_img.save('chessboard_{}.png'.format(i))
        # plt.imshow(img)
        # plt.show()

# cv2.destroyAllWindows()
# 标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

print("重投影误差:\n")
print(ret)
print("内参 : \n")
print(mtx)
print("畸变 : \n")
print(dist)
print("旋转向量 : \n")
print(rvecs)
print("平移向量 : \n")
print(tvecs)

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

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

相关文章

Tomcat 乱码问题彻底解决

1. 终端乱码问题 找到 tomcat 安装目录下的 conf ---> logging.properties .修改ConsoleHandler.endcoding GBK (如果在idea中设置了UTF-8字符集,这里就不需要修改) 2. CMD命令窗口设置编码 参考:WIN10的cmd查看编码方式&am…

Nature|PathChat:病理学多模态生成性AI助手的创新与应用|顶刊精析·24-09-21

小罗碎碎念 今日顶刊:Nature 这篇文章今年6月就发表了,当时我分析的时候,还是预印本,没有排版。今天第一篇推文介绍的是Faisal Mahmood ,所以又把这篇文章拉出来详细分析一下。 作者角色作者姓名单位名称单位英文名称第…

PMP--二模--解题--61-70

文章目录 4.整合管理61、 [单选] 为解决具有挑战性的客户请求,启动了一个项目。该项目必须在短时间内交付。项目经理应该怎么做来尽可能提高项目的成功率? 14.敏捷--MVP--最小可行产品--使用最小可行产品获得客户尽早地反馈。完整性和交付是主观的。团队…

构建高可用和高防御力的云服务架构第二部分:SLB负载均衡(2/5)

在现代云服务中,负载均衡(Load Balancing)是一种关键技术,用于优化资源利用、最小化响应时间、提高系统的可伸缩性和可靠性。负载均衡器位于客户端和服务器之间,根据预设的策略将请求分发到多个服务器上,以…

华为HarmonyOS地图服务 4 - 通过“地图相机“控制地图的可见区域

场景介绍 华为地图的移动是通过模拟相机移动的方式实现的,您可以通过改变相机位置,来控制地图的可见区域,效果如图所示。 本章节将向您介绍相机的各个属性与含义,并移动相机。 相机移动前 接口…

基于lnmp搭建wordpress

一、案例目标 (1)了解LNMP环境的组成。 (2)了解LNMP环境的部署与安装。 (2)了解WordPress应用的部署与使用。 二、节点规划 IP 主机名 节点 192.168.200.20 lnmp lnmp服务节点 三、案例实施 LN…

基于微信小程序的购物系统+php(lw+演示+源码+运行)

基于微信小程序的购物系统 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的购物系统的开发全过程。通过分析基于微信小程序的购物系统管理的不足,创建了一个计算机管理基于微信小…

1.Spring-容器-注册

一、Bean和获取Bean (1)创建IoC容器: SpringApplication.run(类名.class, args); ConfigurableApplicationContext ioc SpringApplication.run(Spring01IocApplication.class, args); (2)将对象注册到IoC容器中&am…

[Vue] 从零开始使用 Vite 创建 Vue 项目

📚 一、安装 Node.js Node.js 是一个运行 JavaScript 代码的 JavaScript 运行时,它允许我们在服务器端运行 JavaScript 代码。以下是安装 Node.js 的步骤: 🌐 访问 Node.js 国内网站:https://nodejs.cn/ &#x1f4…

【如何在 Windows 10 主机上通过 VMware 安装 Windows 11 虚拟机,并共享主机网络】

环境说明 主机操作系统:Windows 10虚拟机操作系统:Windows 11虚拟机软件:VMware 步骤一:确保主机(Windows 10)网络连接正常 启动网络加速软件:在主机上启动软件,确保主机可以正常访…

基于LSTM的温度时序预测

1.背景 本文接【时序预测SARIMAX模型】 一文,采用LSTM模型进行平均温度数据预测。具体的背景和数据分析就不做重复说明,感兴趣可以去看上文即可。 2.LSTM模型 RNN(Recurrent Neural Network,循环神经网络)是一种特殊…

AI驱动TDSQL-C Serverless 数据库技术实战营-ai学生选课系统数据分析

以前用过腾讯的TDSQL-MYSQL,TBASE,最近了解到TDSQL-C serverless,本次试验结合的AI大模型驱动来学习实战TDSQL-C serverless,体验服务化的数据库,和一句简单描述进行学生选课系统数据分析; 我使用的分析数据…

C++初阶-list用法总结

目录 1.迭代器的分类 2.算法举例 3.push_back/emplace_back 4.insert/erase函数介绍 5.splice函数介绍 5.1用法一:把一个链表里面的数据给另外一个链表 5.2 用法二:调整链表当前的节点数据 6.unique去重函数介绍 1.迭代器的分类 我们的这个迭代器…

【alluxio编译报错】Some files do not have the expected license header

Some files do not have the expected license header 快捷导航 在开始解决问题之前,大家可以通过下面的导航快速找到相关资源啦!💡👇 快捷导航链接地址备注相关文档-ambaribigtop自定义组件集成https://blog.csdn.net/TTBIGDA…

【Elasticsearch系列十八】Ik 分词器

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

通信入门系列书籍推荐一:通信原理和通信原理学习辅导

微信公众号上线,搜索公众号小灰灰的FPGA,关注可获取相关源码,定期更新有关FPGA的项目以及开源项目源码,包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 本节目录 一、背景 二、通信原理 …

石岩体育馆附近的免费停车场探寻

坐标:石岩体育馆侧的石清大道断头路, 如果运气好的话,遇到刚好有车开出的话,我觉得可以作为中长期的免费停车点 第一次路过的时候,把我震惊了,我一直以为石岩停车位紧张比市区还严重,因为石岩大部分为统建楼…

python画图|图像背景颜色设置

python画图出来的默认图形背景是白色,有时候并不适合大家表达想要表达的意思。 因此,我们很有必要掌握自己设置图形背景颜色的技巧。 【1】官网教程 首先请各位看官移步官网,看看官网如何设置,下述链接可轻松到达: …

Lubuntu电源管理

lxqt-config-powermanagement 打开托盘图标 Show icon 电源管理 电源管理管理笔记本电脑电池的低电量、关闭笔记本电脑盖的操作以及计算机长时间闲置时应采取的措施。 用法 LXQt 电源管理会监控您的电池、笔记本电脑盖、空闲情况,以及当您按下电源或睡眠按钮时会发…

IS-ISv6单拓扑存在的问题

文章目录 IS-ISv6单拓扑配置单拓扑存在的问题解决 IS-ISv6单拓扑B站视频传送门 IS-ISv6单拓扑 配置 R1:sy sy R1 ipv6 inter g0/0/0 ip add 12.1.1.1 24 ipv6 enable ipv add 2001:12::1 64 inter loop0 ip add 1.1.1.1 32 ipv6 enable ipv address 2002::1 128isi…