机器视觉初步14:相机标定原理及应用

相机标定是指通过已知的相机参数,解算相机内部参数矩阵和外部参数矩阵。
在这里插入图片描述

文章目录

  • 1.为什么要标定?
  • 2.工业场景中常见的标定方法
    • 2.1. 使用棋盘格标定板(Checkerboard Markers)
    • 2.2 使用相机自标定
    • 2.3. 使用三维物体标定
    • 2.4.九孔标定

1.为什么要标定?

在工业中,更多的用户青睐于它在非接触三维尺寸测量上的应用。
所谓的三维测量是广义的三维测量,它不仅包括三维物体的重构与测量,还包括在三维空间中识别任意二维平面上的尺寸以及位置。
这种技术目前已被应用在高精度的工业模具以及装配测量中,其中任意二维平面上的尺寸检测技术应用得更为广泛。

参考文章:相机标定解析
在这里插入图片描述

相机的参数包含内参1和外参2,这些参数是将空间点坐标从相机坐标系转换到像素坐标系所需的。相机标定的目标是获得这些参数,使得我们可以从像素坐标系中的坐标得到图像中的坐标。

为了获取更高的测量精度,我们需要通过标定来实现坐标平面的转换以及图像的校正。
在这里插入图片描述

2.工业场景中常见的标定方法

在工业场景中,相机标定通常采用以下几种方法:

2.1. 使用棋盘格标定板(Checkerboard Markers)

棋盘格标定板是最常见的相机标定方法,它由黑白相间的正方形组成,棋盘格的对角线交点形成一个共用角点。使用棋盘格标定板,可以通过拍摄多张带有棋盘格的图像,并在图像中标记棋盘格的角点,从而计算相机的内外参数。在这里插入图片描述

例如,可以使用一个三维棋盘格标定板(或者投影到一张二维图像上),在相机拍摄的图像中标记棋盘格的角点。然后,通过最小化相机视场中像素坐标和标定板上角点坐标之间的误差来计算相机的内外参数。

import numpy as np
import cv2

# 棋盘格尺寸
pattern_size = (9, 6)

# 准备棋盘格标定板的世界坐标
objp = np.zeros((pattern_size[0] * pattern_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2)

# 存储棋盘格角点的世界坐标和图像坐标
objpoints = []  # 世界坐标系中的棋盘格角点
imgpoints = []  # 图像平面中的棋盘格角点

# 读取图像
images = ['image1.jpg', 'image2.jpg', 'image3.jpg']  # 替换为实际图像的文件名列表

for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 查找棋盘格角点
    ret, corners = cv2.findChessboardCorners(gray, pattern_size, None)

    # 如果找到棋盘格角点,则添加到objpoints和imgpoints中
    if ret == True:
        objpoints.append(objp)
        imgpoints.append(corners)

        # 绘制并显示角点
        cv2.drawChessboardCorners(img, pattern_size, 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("相机内参数矩阵:")
print(mtx)
print("\n畸变系数:")
print(dist)

2.2 使用相机自标定

相机自标定方法不需要使用特殊的标定板,而是通过拍摄带有不同纹理和几何形状的物体(如带有条纹的纸张、弯曲的金属片等),然后通过分析相机拍摄的图像来计算相机的内外参数。
例如,可以拍摄一张带有条纹的纸张,并在纸张上的条纹区域和背景区域拍摄多张图像。然后,通过最小化相机视场中像素坐标和条纹区域的边界之间的误差来计算相机的内外参数。

2.3. 使用三维物体标定

使用三维物体标定方法是通过将三维物体投影到二维图像中,然后计算相机的内外参数。这种方法通常用于三维物体的尺寸和形状对于相机的视场而言非常明显的场景。
例如,可以将一个具有不同尺寸和形状的三维物体(如盒子、球体等)放置在相机视场中,并拍摄多张带有该物体的图像。然后,通过最小化相机视场中像素坐标和物体边界之间的误差来计算相机的内外参数。

import cv2
import numpy as np

# 读取标定板图像
image = cv2.imread('calibration_image.jpg')

# 定义标定板的尺寸
board_size = (9, 6)

# 寻找标定板角点
ret, corners = cv2.findChessboardCorners(image, board_size, None)

# 如果找到了角点
if ret:
    # 优化角点位置
    corners = cv2.cornerSubPix(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY), corners, (11, 11), (-1, -1), (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))
    
    # 定义标定板上的三维点
    object_points = np.zeros((board_size[0] * board_size[1], 3), np.float32)
    object_points[:, :2] = np.mgrid[0:board_size[0], 0:board_size[1]].T.reshape(-1, 2)
    
    # 定义图像上的二维点
    image_points = corners.reshape(-1, 2)
    
    # 进行相机标定
    ret, camera_matrix, distortion_coefficients, rotation_vectors, translation_vectors = cv2.calibrateCamera([object_points], [image_points], image.shape[::-1], None, None)
    
    # 打印相机矩阵和畸变系数
    print("Camera Matrix:")
    print(camera_matrix)
    print("Distortion Coefficients:")
    print(distortion_coefficients)
else:
    print("Cannot find chessboard corners in the image.")

2.4.九孔标定

九孔标定(9-cell calibration)是指使用9个像素来检测和标定摄像头的标定方法。
在这里插入图片描述

在计算机视觉领域,这种方法常常被用来进行摄像头畸变校正、图像缩放、图像旋转等操作。下面是用Halcon实现九孔标定的步骤。
步骤1:准备九个像素
确保你有9个像素的图像,这些图像需要覆盖摄像头的每个视野。例如,你可以使用9张标定板(包含9个孔的标定板)的不同视图,或者9张带有9个明显标志的标定板。

步骤2:使用Halcon提供的函数计算图像尺寸
使用rectifyImage函数计算每个图像的像素尺寸。例如,假设你的标定板有500像素宽,500像素高,你可以这样计算:

read_image (Image, 'Calibration_board_images/Calibration_board.png')
get_image_size (Image, Width, Height)
rectify_image (Image, ImageReduced, 'nearest_neighbor', 'true')
dev_display (ImageReduced)

步骤3:调整相机参数
使用set_system函数设置相机参数。例如,你可能需要设置焦距、内径和外径等参数。

set_system ('Display Size', [8, 7])
set_system ('Cursor Size', [3, 4])
set_system ('Image Size', [Width, Height])
set_system ('Display Interval', 1000)

步骤4:使用Halcon的标定工具进行标定
在Halcon中,有一个内置的标定工具,可以自动计算摄像头参数并生成标定板图像。
首先,你需要运行以下代码以启动标定工具:

open_framegrabber ('DirectShow', 1, 1, 0, 0, 0, 0, 'default', 9, -1, -1, 'default', 'false', 0, 0, 'rgb_color', 'false', 1, 'default', [], [], [], [], [], [], [], ptr)
grab_image_start (Image, -1, -1, 'black', -1, 'false')
while (true)
    grab_image_async (Image, ImageGrabbed, -1, [], [], 'rgb_color', 'false', 'default', 'false')
    dev_update_window ('off')
    dev_display (ImageGrabbed)
    wait_seconds (1)
endwhile
close_framegrabber (ptr)

这段代码将运行标定工具并捕获标定板的图像。标定过程完成后,你可以将标定板图像绘制在标定板上,计算它们的畸变系数,并使用这些参数进行图像畸变校正。
步骤5:使用图像畸变校正
首先,根据你的摄像头配置计算畸变参数。然后,使用Halcon的correct_image_points函数进行图像畸变校正:

read_image (Image, 'Calibration_board_images/Calibration_board.png')
dev_close_window ()
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_color ('red')
dev_display (Image)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

dev_set_color ('blue')
correct_image_points (Image, 'Default', 'true', 'true', CorrectedImage)
dev_set_color ('red')
dev_display (CorrectedImage)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

这段代码将使用correct_image_points函数对图像进行畸变校正,并将校正后的图像绘制在显示窗口中。
总之,要用Halcon实现九孔标定,你需要准备九张标定板图像,计算图像尺寸,调整相机参数,运行标定工具,然后使用畸变校正算法对图像进行畸变校正。


  1. 相机的内参数(Intrinsic Parameters)是描述相机自身几何特性的参数,包括:
    1.摄像机的主点(Principal Point):也称为摄像机的质心,它是由相机的各轴的中点组成的。
    2.摄像机的基线(Basis Line):也称为摄像机的成像基线,是主点和焦距的连线。
    3.摄像机的光学畸变参数:包括径向畸变(Radial Distortion)、切向畸变(Tangential Distortion)和垂轴畸变(Vertical Distortion)。
    4.焦距(Focal Length):是从摄像机光心到焦平面的距离。
    5.像素单位(Pixel Unit):相机的一个像素代表的实际物理长度。 ↩︎

  2. 相机的外参数(Extrinsic Parameters)是描述相机相对于外部世界的投影关系的参数,包括:
    1.旋转矩阵(Rotation Matrix):用于描述摄像机绕着某一坐标轴旋转的参数。
    2.平移矩阵(Translation Matrix):用于描述摄像机在某一位置的平移变换的参数。
    3.畸变参数:径向畸变参数、切向畸变参数和垂轴畸变参数。
    4.畸变系数(Distortion Coefficients):径向畸变参数、切向畸变参数和垂轴畸变参数的组合。 ↩︎

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【人工智能】神经网络、前向传播、反向传播、梯度下降、局部最小值、多层前馈网络、缓解过拟合的策略

神经网络、前向传播、反向传播 文章目录 神经网络、前向传播、反向传播前向传播反向传播梯度下降局部最小值多层前馈网络表示能力多层前馈网络局限缓解过拟合的策略前向传播是指将输入数据从输入层开始经过一系列的权重矩阵和激活函数的计算后,最终得到输出结果的过程。在前向…

【分布式】分布式唯一 ID 的 几种生成方案以及优缺点snowflake优化方案

在互联网的业务系统中,涉及到各种各样的ID,如在支付系统中就会有支付ID、退款ID等。那一般生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,我们应该采用哪种适合自己的解决方案是十分重要的。下面我们一一来列举一…

@monaco-editor/react组件CDN加载失败解决办法

monaco-editor/react引入这个cdn资源会load失败 网上很多例子都是这样写的,我这样写monaco会报错 import * as monaco from monaco-editor; import { loader } from monaco-editor/react;loader.config({ monaco });改成这样 import * as monaco from monaco-edi…

基于Centos 7虚拟机的磁盘操作(添加磁盘、分区、格式分区、挂载)

目录 一、添加硬盘 二、查看新磁盘 三、磁盘分区 3.1新建分区 3.2 格式分区 3.3 挂载分区 3.4 永久挂载新分区 3.5 取消挂载分区 一、添加硬盘 1.在虚拟机处选择编辑虚拟机设置,然后选择添加 2.选择硬盘,然后选择下一步 3.默认即可,下一步…

TCP连接管理与UDP协议

“三次握手”与“四次挥手” TCP建立连接的过程叫做握手 采用三报文握手:在客户和服务器之间交换三个TCP报文段,以防止已失效的连接请求报文段突然又传送到了,因而产生TCP连接建立错误。 第一次握手 连续释放——“四次挥手” TCP连续释放…

Zabbix监控之分布式部署

文章目录 Zabbix监控之分布式部署zabbix proxy概述部署zabbix-proxy节点规划基础环境准备安装proxy以及数据库配置数据库添加服务端host解析修改zabbix-proxy配置文件启动代理服务器 zabbix页面(1)在zabbix页面添加代理(2)zabbix-agent连接proxy Zabbix监控之分布式部署 zabbi…

使用Nacos将单体服务注册成微服务的步骤以及相关问题解决

目录 1.改造单体服务的配置文件。 2.添加Nacosw相关的pom依赖 3.在nacos的配置列表中创建配置列表 4.相关问题的解决 1.改造单体服务的配置文件。 🔖创建一个bootstrap.yml的配置文件该文件通常放置在src/main/resources目录中,并且优先于applicati…

ping命令

上图为IA ping B的过程,在此过程中: 包传送在x位置时,DestMacB左,SourceMacMac_A,Dest ipIp_B,Src_ipIp_A包传送在y位置时,DestMacB右,SourceMacB左 , Dest ipIp_B,Src_ipIp_A MAC…

多线程(Java系列6)

目录 前言: 1.什么是线程池 2.标准库中的线程池 3.实现线程池 结束语: 前言: 在上一节中小编带着大家了解了一下Java标准库中的定时器的使用方式并给大家实现了一下,那么这节中小编将分享一下多线程中的线程池。给大家讲解一…

三言两语说透process.stdout.write和console.log的区别

Node.js中的process.stdout.write和console.log都是用于向标准输出流(stdout)打印输出的方法,但二者在使用场景和实现方式上有些区别。本文将详细介绍process.stdout.write和console.log的区别。 process.stdout.write介绍 process.stdout.write是Node.js中的一个…

vue解决跨域访问问题(个人学习笔记六)

目录 友情提醒第一章、跨越问题解决1.1)什么是跨域问题?1.2)第一种解决方式:后端设置允许跨域访问1.3)第二种解决方式:前端配置代理 第二章、配置代理服务器2.1)配置简单代理服务器2.2&#xff…

Langchain 集成 Milvus

Langchain 集成 Milvus 1. 安装 Docker2. 部署 Milvus3.4. Langchain 集成 Milvus 1. 安装 Docker refer: https://docs.docker.com/engine/install/centos/ Milvus 会以容器方式启动,所以先安装 Docker。(本示例使用的是 Alma Linux 9.2) 卸载旧版本&#xff0c…

WEB APIs day4 (2)

三、M端事件 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, …

深入学习 redis - Stream、Geospatial、HyperLogLog、Bitmap、Bitfields 类型扩展

目录 前言 Stream geospatial HyperLogLog Bitmaps Bitfields 前言 redis 中最关键的五个数据类型 String、List、Hash、Set、Zset 应用最广泛&#xff0c;同时 redis 也推出了额外的 5 个数据类型&#xff0c;他们分别是针对特殊场景才进行的应用的. Ps&#xff1a;这几种…

干货 | 电路设计中如何减少ESD?

干货 | 电路设计中如何减少ESD&#xff1f; 今天给大家分享的是&#xff1a;在电路设计和PCB设计如何防止ESD损坏设备。 在电子行业中&#xff0c;保护设备免受ESD损坏是必须要注意的。静电放电&#xff08;ESD&#xff09;是一种非常高的电压尖峰&#xff0c;很容易损坏集成电…

lc162.寻找峰值

由于题目假设nums[-1]和nums[n]等于负无穷 如果nums[i]>nums[i1]&#xff0c;即nums[-1]<nums[i]>nums[i1]&#xff0c;那么在[0,i]区间内一定存在峰值 如果nums[i]<nums[i1]&#xff0c;即nums[i]<nums[i1]>nums[n]&#xff0c;那么在[i1,n-1]区间内一定存…

【UE4】给角色添加脚步声

步骤&#xff1a; 1. 导入一个脚步声音频文件&#xff08;.wav格式&#xff09; 2. 打开角色蓝图&#xff0c;这里以第三人称角色模板蓝图“ThirdPersonCharacter”为例&#xff0c;在事件图表中添加一个生成音效的自定义事件。 3. 打开动画序列“ThirdPersonRun” 找到小白人…

【机器学习】异常检测

异常检测 假设你是一名飞机涡扇引擎工程师&#xff0c;你在每个引擎出厂之前都需要检测两个指标——启动震动幅度和温度&#xff0c;查看其是否正常。在此之前你已经积累了相当多合格的发动机的出厂检测数据&#xff0c;如下图所示 我们把上述的正常启动的数据集总结为 D a t…

基于飞桨paddle的极简方案构建手写数字识别模型测试代码

基于飞桨paddle的极简方案构建手写数字识别模型测试代码 原始测试图片为255X252的图片 因为是极简方案采用的是线性回归模型&#xff0c;所以预测结果数字不一致 本次预测的数字是 [[3]] 测试结果&#xff1a; PS E:\project\python> & D:/Python39/python.exe e:/pro…

性能提升,SpringBoot 3.2虚拟线程来了

spring boot 3.2 会提供默认支持&#xff0c;必须Java19。 在以往的项目中&#xff0c;我们面临了这样一种情况&#xff1a;我们收到了数千个认证请求。为了确保安全性&#xff0c;我们依靠第三方系统发送短信 OTP 进行验证。然而&#xff0c;有时候第三方系统花费的时间比预期…