python 手眼标定OpenCV手眼标定(calibrateHandeye())一

本文详细介绍了如何使用Python和OpenCV进行手眼标定,包括相机标定原理、参数说明、代码实现和解决常见问题。通过欧拉角计算旋转矩阵,利用pose_robot函数获取位姿变换矩阵,再结合calibrateHandeye()进行手眼标定,最终得到相机相对于末端的变换矩阵。此外,还提供了解决精度问题的方法和solvePnP函数的参数解释。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下代码来源
本篇博客通过该代码,附上记录的公式与查找连接,方面以后调用能弄懂各个参数的意思
本篇看完看第二篇代码踩坑部分python 手眼标定OpenCV手眼标定(calibrateHandeye())二
相机标定原理视频介绍

1.参数说明

calibrateHandeye()
参数描述如下:R_gripper2base,t_gripper2base是机械臂抓手相对于机器人基坐标系的旋转矩阵与平移向量,需要通过机器人运动控制器或示教器读取相关参数转换计算得到;R_target2cam
, t_target2cam 是标定板相对于双目相机的齐次矩阵,在进行相机标定时可以求取得到(calibrateCamera()得到),
也可以通过solvePnP()单独求取相机外参数获得 ; R_cam2gripper ,
t_cam2gripper是求解的手眼矩阵分解得到的旋转矩阵与平移矩阵;OpenCV实现了5种方法求取手眼矩阵 , Tsai两步法速度最快。

参考视频参数解释传送门

**以下为官方调用的参数说明图片,注意最下面python的那个:

官方函数说明网址**

官方原理说明网址

其他推导
在这里插入图片描述

2.引用代码

import cv2
import numpy as np
import glob
from math import *
import pandas as pd
import os

K=np.array([[4283.95148301687,-0.687179973528103,2070.79900757240],
            [0,4283.71915784510,1514.87274457919],
            [0,0,1]],dtype=np.float64)#大恒相机内参
chess_board_x_num=11#棋盘格x方向格子数
chess_board_y_num=8#棋盘格y方向格子数
chess_board_len=10#单位棋盘格长度,mm


#用于根据欧拉角计算旋转矩阵
def myRPY2R_robot(x, y, z):
    Rx = np.array([[1, 0, 0], [0, cos(x), -sin(x)], [0, sin(x), cos(x)]])
    Ry = np.array([[cos(y), 0, sin(y)], [0, 1, 0], [-sin(y), 0, cos(y)]])
    Rz = np.array([[cos(z), -sin(z), 0], [sin(z), cos(z), 0], [0, 0, 1]])
    R = Rz@Ry@Rx
    return R

#用于根据位姿计算变换矩阵
def pose_robot(x, y, z, Tx, Ty, Tz):
    thetaX = x / 180 * pi
    thetaY = y / 180 * pi
    thetaZ = z / 180 * pi
    R = myRPY2R_robot(thetaX, thetaY, thetaZ)
    t = np.array([[Tx], [Ty], [Tz]])
    RT1 = np.column_stack([R, t])  # 列合并
    RT1 = np.row_stack((RT1, np.array([0,0,0,1])))
    # RT1=np.linalg.inv(RT1)
    return RT1

#用来从棋盘格图片得到相机外参
def get_RT_from_chessboard(img_path,chess_board_x_num,chess_board_y_num,K,chess_board_len):
    '''
    :param img_path: 读取图片路径
    :param chess_board_x_num: 棋盘格x方向格子数
    :param chess_board_y_num: 棋盘格y方向格子数
    :param K: 相机内参
    :param chess_board_len: 单位棋盘格长度,mm
    :return: 相机外参
    '''
    img=cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    size = gray.shape[::-1]
    ret, corners = cv2.findChessboardCorners(gray, (chess_board_x_num, chess_board_y_num), None)
    # print(corners)
    corner_points=np.zeros((2,corners.shape[0]),dtype=np.float64)
    for i in range(corners.shape[0]):
        corner_points[:,i]=corners[i,0,:]
    # print(corner_points)
    object_points=np.zeros((3,chess_board_x_num*chess_board_y_num),dtype=np.float64)
    flag=0
    for i in range(chess_board_y_num):
        for j in range(chess_board_x_num):
            object_points[:2,flag]=np.array([(11-j-1)*chess_board_len,(8-i-1)*chess_board_len])
            flag+=1
    # print(object_points)

    retval,rvec,tvec  = cv2.solvePnP(object_points.T,corner_points.T, K, distCoeffs=None)
    # print(rvec.reshape((1,3)))
    # RT=np.column_stack((rvec,tvec))
    RT=np.column_stack(((cv2.Rodrigues(rvec))[0],tvec))
    RT = np.row_stack((RT, np.array([0, 0, 0, 1])))
    # RT=pose(rvec[0,0],rvec[1,0],rvec[2,0],tvec[0,0],tvec[1,0],tvec[2,0])
    # print(RT)

    # print(retval, rvec, tvec)
    # print(RT)
    # print('')
    return RT

folder = r"calib"#棋盘格图片存放文件夹
# files = os.listdir(folder)
# file_num=len(files)
# RT_all=np.zeros((4,4,file_num))

# print(get_RT_from_chessboard('calib/2.bmp', chess_board_x_num, chess_board_y_num, K, chess_board_len))
'''
这个地方很奇怪的特点,有些棋盘格点检测得出来,有些检测不了,可以通过函数get_RT_from_chessboard的运行时间来判断
'''
good_picture=[1,3,5,6,7,8,10,11,12,13,14,15]#存放可以检测出棋盘格角点的图片
# good_picture=[1,3,10,11,12]
file_num=len(good_picture)

#计算board to cam 变换矩阵
R_all_chess_to_cam_1=[]
T_all_chess_to_cam_1=[]
for i in good_picture:
    # print(i)
    image_path=folder+'/'+str(i)+'.bmp'
    RT=get_RT_from_chessboard(image_path, chess_board_x_num, chess_board_y_num, K, chess_board_len)

    # RT=np.linalg.inv(RT)

    R_all_chess_to_cam_1.append(RT[:3,:3])
    T_all_chess_to_cam_1.append(RT[:3, 3].reshape((3,1)))
# print(T_all_chess_to_cam.shape)

#计算end to base变换矩阵
file_address='calib/机器人基坐标位姿.xlsx'#从记录文件读取机器人六个位姿
sheet_1 = pd.read_excel(file_address)
R_all_end_to_base_1=[]
T_all_end_to_base_1=[]
# print(sheet_1.iloc[0]['ax'])
for i in good_picture:
    # print(sheet_1.iloc[i-1]['ax'],sheet_1.iloc[i-1]['ay'],sheet_1.iloc[i-1]['az'],sheet_1.iloc[i-1]['dx'],
    #                                   sheet_1.iloc[i-1]['dy'],sheet_1.iloc[i-1]['dz'])
    RT=pose_robot(sheet_1.iloc[i-1]['ax'],sheet_1.iloc[i-1]['ay'],sheet_1.iloc[i-1]['az'],sheet_1.iloc[i-1]['dx'],
                                      sheet_1.iloc[i-1]['dy'],sheet_1.iloc[i-1]['dz'])
    # RT=np.column_stack(((cv2.Rodrigues(np.array([[sheet_1.iloc[i-1]['ax']],[sheet_1.iloc[i-1]['ay']],[sheet_1.iloc[i-1]['az']]])))[0],
    #                    np.array([[sheet_1.iloc[i-1]['dx']],
    #                                   [sheet_1.iloc[i-1]['dy']],[sheet_1.iloc[i-1]['dz']]])))
    # RT = np.row_stack((RT, np.array([0, 0, 0, 1])))
    # RT = np.linalg.inv(RT)

    R_all_end_to_base_1.append(RT[:3, :3])
    T_all_end_to_base_1.append(RT[:3, 3].reshape((3, 1)))

# print(R_all_end_to_base_1)
R,T=cv2.calibrateHandEye(R_all_end_to_base_1,T_all_end_to_base_1,R_all_chess_to_cam_1,T_all_chess_to_cam_1)#手眼标定
RT=np.column_stack((R,T))
RT = np.row_stack((RT, np.array([0, 0, 0, 1])))#即为cam to end变换矩阵
print('相机相对于末端的变换矩阵为:')
print(RT)

#结果验证,原则上来说,每次结果相差较小
for i in range(len(good_picture)):

    RT_end_to_base=np.column_stack((R_all_end_to_base_1[i],T_all_end_to_base_1[i]))
    RT_end_to_base=np.row_stack((RT_end_to_base,np.array([0,0,0,1])))
    # print(RT_end_to_base)

    RT_chess_to_cam=np.column_stack((R_all_chess_to_cam_1[i],T_all_chess_to_cam_1[i]))
    RT_chess_to_cam=np.row_stack((RT_chess_to_cam,np.array([0,0,0,1])))
    # print(RT_chess_to_cam)

    RT_cam_to_end=np.column_stack((R,T))
    RT_cam_to_end=np.row_stack((RT_cam_to_end,np.array([0,0,0,1])))
    # print(RT_cam_to_end)

    RT_chess_to_base=RT_end_to_base@RT_cam_to_end@RT_chess_to_cam#即为固定的棋盘格相对于机器人基坐标系位姿
    RT_chess_to_base=np.linalg.inv(RT_chess_to_base)
    print('第',i,'次')
    print(RT_chess_to_base[:3,:])
    print('')

以上代码调用时的实际例子

R,T=cv2.calibrateHandEye(R_all_end_to_base_1,T_all_end_to_base_1,R_all_chess_to_cam_1,T_all_chess_to_cam_1)#手眼标定

1.根据欧拉角计算旋转矩阵
在这里插入图片描述

在这里插入图片描述

#用于根据欧拉角计算旋转矩阵
def myRPY2R_robot(x, y, z):
    Rx = np.array([[1, 0, 0], [0, cos(x), -sin(x)], [0, sin(x), cos(x)]])
    Ry = np.array([[cos(y), 0, sin(y)], [0, 1, 0], [-sin(y), 0, cos(y)]])
    Rz = np.array([[cos(z), -sin(z), 0], [sin(z), cos(z), 0], [0, 0, 1]])
    R = Rz@Ry@Rx
    return R

2.用于根据位姿计算变换矩阵推理在10分左右的地方 传送门

#用于根据位姿计算变换矩阵
def pose_robot(x, y, z, Tx, Ty, Tz):
    thetaX = x / 180 * pi
    thetaY = y / 180 * pi
    thetaZ = z / 180 * pi
    R = myRPY2R_robot(thetaX, thetaY, thetaZ)
    t = np.array([[Tx], [Ty], [Tz]])
    RT1 = np.column_stack([R, t])  # 列合并
    RT1 = np.row_stack((RT1, np.array([0,0,0,1])))
    # RT1=np.linalg.inv(RT1)
    return RT1

3.通过以上两部分,传入通过 good_picture 传入多张标定图片,即棋盘格图片,用之前需要先通过 calibrateCamera()函数测试看下能否提取出角点哈,从而得到 calibrateHandeye的前两个输入参数,具体调用流程结合代码看参数博客说明参考

R_gripper2base,t_gripper2base是机械臂抓手相对于机器人基坐标系的旋转矩阵与平移向量,需要通过机器人运动控制器或示教器读取相关参数转换计算得到
在这里插入图片描述
补如果完成后精度不行的话可以多试试该函数下不同的method 解法 如下
在这里插入图片描述

R_all_end_to_base_1=[]
T_all_end_to_base_1=[]
# print(sheet_1.iloc[0]['ax'])
for i in good_picture:
    # print(sheet_1.iloc[i-1]['ax'],sheet_1.iloc[i-1]['ay'],sheet_1.iloc[i-1]['az'],sheet_1.iloc[i-1]['dx'],
    #                                   sheet_1.iloc[i-1]['dy'],sheet_1.iloc[i-1]['dz'])
    RT=pose_robot(sheet_1.iloc[i-1]['ax'],sheet_1.iloc[i-1]['ay'],sheet_1.iloc[i-1]['az'],sheet_1.iloc[i-1]['dx'],
                                      sheet_1.iloc[i-1]['dy'],sheet_1.iloc[i-1]['dz'])
    # RT=np.column_stack(((cv2.Rodrigues(np.array([[sheet_1.iloc[i-1]['ax']],[sheet_1.iloc[i-1]['ay']],[sheet_1.iloc[i-1]['az']]])))[0],
    #                    np.array([[sheet_1.iloc[i-1]['dx']],
    #                                   [sheet_1.iloc[i-1]['dy']],[sheet_1.iloc[i-1]['dz']]])))
    # RT = np.row_stack((RT, np.array([0, 0, 0, 1])))
    # RT = np.linalg.inv(RT)

    R_all_end_to_base_1.append(RT[:3, :3])
    T_all_end_to_base_1.append(RT[:3, 3].reshape((3, 1)))

这里的代码作者是直接输入的相机内参,而得到rvec:标定板坐标系到相机坐标系的旋转向量,可用cv:Rodrigues()变为旋转矩阵tvec:标定板坐标系到相机坐标系的旋转矩阵,这些是通过 opencv的
calibrateCamera()得到函数的mtx变量输出得到内参也就是代码里面的 K,以下为我通过使用该函数得到的数据节选,这里可以直接引入图片通过该函数得到下面的,也可以把该部分数据提取出来,后自行添加到代码里面,提取成json文件的代码参考我的这个博客传送门
在这里插入图片描述
4.solvePnP原理说明
solvePnP函数参数解释
Parameters:

objectPoints - 世界坐标系下的控制点的坐标,vector的数据类型在这里可以使用
imagePoints - 在图像坐标系下对应的控制点的坐标。vector在这里可以使用
cameraMatrix - 相机的内参矩阵
distCoeffs - 相机的畸变系数
以上两个参数通过相机标定可以得到。相机的内参数的标定参见:http://www.cnblogs.com/star91/p/6012425.html
rvec - 输出的旋转向量。使坐标点从世界坐标系旋转到相机坐标系
tvec - 输出的平移向量。使坐标点从世界坐标系平移到相机坐标系
flags - 默认使用CV_ITERATIV迭代法
在这里插入图片描述

易错点提示

在这里插入图片描述
1.第一个的意思(来自b站木鱼木夕评论)

关于23:52 易错点一的笔记:

标定相机时, 使用calibrateCamera()函数的主要目的在于得到相机内参和畸变系数,
此外得到的cam_board_R和cam_board_T是几组相机外参; calibrateCamera()的功能:Finds the
camera intrinsic and extrinsic parameters from several views of a
calibration pattern.(从标定模式的几个视图中查找摄像机的内外参数。)
——————————————————————————————————————————————————————————————
手眼标定时, 使用solvePnP()函数的主要目的在于得到cam_board_R和cam_board_T,
使用solvePnP()函数时需要输入相机内参和畸变系数; solvePnP()的功能:Finds an object pose from
3D-2D point correspondences. This function returns the rotation and
the translation vectors that transform a 3D point expressed in the
object coordinate frame to the camera coordinate frame, using
different methods:
(:找到一个对象的姿势

3 d-2d通讯。这个函数返回旋转和

式中表示的三维点变换的平移向量

对象坐标帧到摄像机坐标帧,使用

不同的方法:)
—————————————————————————————————————————————————————————————
也就是说, 标定相机和手眼标定是两个有点区别的问题场景;

2.第二个反正就是手眼标定的时候棋盘格右下角在画面上要尽量偏向右方就是了。

补:旋转矩阵 旋转向量 欧拉角 互相转换

在这里插入图片描述
在这里插入图片描述

<think>根据用户的需求,用户希望获取使用Python实现OpenCV手眼标定的源代码。结合引用内容,我们了解到OpenCV提供了`calibrateHandEye`函数用于手眼标定手眼标定通常分为两种模式:眼在手上(eye-in-hand)和眼在手外(eye-to-hand)。我们将提供个示例代码,包括数据准备和函数调用。 ### 步骤说明 1. **数据准备**:需要机械臂末端执行器相对于基座的位姿(旋转矩阵R和平移向量t)以及标定板相对于相机的位姿(旋转矩阵R和平移向量t)。 2. **调用函数**:使用`cv2.calibrateHandEye`函数计算相机相对于机械臂末端执行器(眼在手上)或基座(眼在手外)的位姿。 3. **结果输出**:得到相机到机械臂末端执行器(或基座)的旋转矩阵和平移向量。 ### 代码示例 以下是个使用OpenCV进行手眼标定Python代码示例。假设我们已经从多个不同位姿采集了数据,并存储在列表中。 ```python import numpy as np import cv2 # 假设我们已经有了多组机械臂末端执行器相对于基座的位姿(R_gripper2base, t_gripper2base) # 以及标定板相对于相机的位姿(R_target2cam, t_target2cam) # 这里用些示例数据填充,实际应用中需要从实际采集的数据中获取 # 示例数据:四组位姿 # 机械臂末端到基座的旋转矩阵(3x3)和平移向量(3x1) R_gripper2base_list = [ np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=np.float64), # 示例旋转矩阵1 np.array([[0, -1, 0], [1, 0, 0], [0, 0, 1]], dtype=np.float64), # 示例旋转矩阵2 # ... 添加更多数据 ] t_gripper2base_list = [ np.array([0.1, 0.2, 0.3], dtype=np.float64).reshape(3,1), # 示例平移向量1 np.array([0.2, 0.1, 0.4], dtype=np.float64).reshape(3,1), # 示例平移向量2 # ... 添加更多数据 ] # 标定板到相机的旋转矩阵和平移向量 R_target2cam_list = [ np.array([[0.866, -0.5, 0], [0.5, 0.866, 0], [0, 0, 1]], dtype=np.float64), # 示例 np.array([[0.5, -0.866, 0], [0.866, 0.5, 0], [0, 0, 1]], dtype=np.float64), # 示例 # ... 添加更多数据 ] t_target2cam_list = [ np.array([0.05, 0.1, 0.2], dtype=np.float64).reshape(3,1), # 示例 np.array([0.1, 0.05, 0.3], dtype=np.float64).reshape(3,1), # 示例 # ... 添加更多数据 ] # 调用手眼标定函数 # 注意:这里使用眼在手上模式(EYE_IN_HAND),即相机固定在机械臂末端 R_cam2gripper, t_cam2gripper = cv2.calibrateHandEye( R_gripper2base=R_gripper2base_list, t_gripper2base=t_gripper2base_list, R_target2cam=R_target2cam_list, t_target2cam=t_target2cam_list, method=cv2.CALIB_HAND_EYE_TSAI # 可以选择不同的算法,如CALIB_HAND_EYE_TSAI, CALIB_HAND_EYE_PARK等 ) print("相机到机械臂末端执行器的旋转矩阵R_cam2gripper:\n", R_cam2gripper) print("相机到机械臂末端执行器的平移向量t_cam2gripper:\n", t_cam2gripper) ``` ### 参数说明 - `R_gripper2base`和`t_gripper2base`:机械臂末端执行器相对于基座的旋转矩阵和平移向量(通常从机器人控制器获取)。 - `R_target2cam`和`t_target2cam`:标定板相对于相机的旋转矩阵和平移向量(通过相机标定和姿态估计得到,如使用`cv2.solvePnP`)。 - `method`:标定方法,OpenCV提供了多种算法,包括: - `cv2.CALIB_HAND_EYE_TSAI` - `cv2.CALIB_HAND_EYE_PARK` - `cv2.CALIB_HAND_EYE_HORAUD` - `cv2.CALIB_HAND_EYE_ANDREFF` - `cv2.CALIB_HAND_EYE_DANIILIDIS` ### 注意事项 1. **数据采集**:需要多组(通常10组以上)不同位姿的数据,且位姿变化应尽可能大(旋转和平移都有明显变化)以提高标定精度。 2. **位姿表示**:旋转矩阵必须是3x3的正交矩阵,平移向量是3x1的向量。 3. **模式选择**:如果是眼在手上(相机固定在机械臂末端),则计算的是相机到末端执行器的变换;如果是眼在手外(相机固定在工作台上),则计算的是相机到基座的变换。在调用函数时,需要根据情况调整输入数据的含义。 ### 相关问题 1. 如何获取机械臂末端执行器相对于基座的位姿? 2. 如何通过相机图像计算标定板相对于相机的位姿? 3. 手眼标定中不同算法(如Tsai、Park等)有什么区别? 4. 如何评估手眼标定的精度? 5. 手眼标定中常见的误差来源有哪些? 希望这个示例代码能帮助您开始手眼标定的工作。如果您有具体的数据集或遇到问题,可以提供更多细节以便进步分析。</think>### OpenCV手眼标定Python实现代码 以下是使用Python实现OpenCV手眼标定的完整代码示例,包含详细注释: ```python import cv2 import numpy as np # 准备标定数据(实际应用中需替换为真实数据) # 1. 机械臂末端到基座的位姿 (R_gripper2base, t_gripper2base) R_gripper2base = [ np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]), # 位姿1旋转矩阵 np.array([[0, -1, 0], [1, 0, 0], [0, 0, 1]]), # 位姿2旋转矩阵 # ... 至少需要10组不同位姿 ] t_gripper2base = [ np.array([0.1, 0.2, 0.3]), # 位姿1平移向量 np.array([0.2, 0.1, 0.4]), # 位姿2平移向量 # ... 对应位姿的平移向量 ] # 2. 标定板到相机的位姿 (R_target2cam, t_target2cam) R_target2cam = [ np.array([[0.866, -0.5, 0], [0.5, 0.866, 0], [0, 0, 1]]), # 位姿1 np.array([[0.5, -0.866, 0], [0.866, 0.5, 0], [0, 0, 1]]), # 位姿2 # ... 与机械臂位姿对应的相机位姿 ] t_target2cam = [ np.array([0.05, 0.1, 0.2]), # 位姿1 np.array([0.1, 0.05, 0.3]), # 位姿2 # ... ] # 执行手眼标定(眼在手上模式) R_cam2gripper, t_cam2gripper = cv2.calibrateHandEye( R_gripper2base=R_gripper2base, t_gripper2base=t_gripper2base, R_target2cam=R_target2cam, t_target2cam=t_target2cam, method=cv2.CALIB_HAND_EYE_TSAI # 可选算法:TSAI/PARK/HORAUD等 ) print("相机到机械臂末端的旋转矩阵:") print(R_cam2gripper) print("\n相机到机械臂末端的平移向量:") print(t_cam2gripper) # 验证标定结果(可选) # 使用标定结果将相机坐标转换为机械臂坐标 cam_point = np.array([0.1, 0.2, 0.3]) # 相机坐标系下的点 gripper_point = R_cam2gripper @ cam_point + t_cam2gripper.flatten() print(f"\n相机坐标系点 {cam_point} 转换到机械臂坐标系: {gripper_point}") ``` ### 关键参数说明: 1. **`R_gripper2base`/`t_gripper2base`**:机械臂末端相对于基座的旋转矩阵和平移向量 2. **`R_target2cam`/`t_target2cam`**:标定板相对于相机的旋转矩阵和平移向量 3. **`method`**:标定算法选择: - `cv2.CALIB_HAND_EYE_TSAI`:Tsai经典算法[^1] - `cv2.CALIB_HAND_EYE_PARK`:Park优化算法 - `cv2.CALIB_HAND_EYE_HORAUD`:Horaud方法 ### 实际应用步骤: 1. **数据采集**: - 控制机械臂移动至10-15个不同位姿 - 每个位姿下采集标定板图像 - 记录机械臂末端位姿(通过运动学求解) - 使用`cv2.solvePnP()`计算标定板位姿 2. **标定流程**: ```mermaid graph TD A[采集多组机械臂位姿] --> B[计算标定板位姿] B --> C[调用calibrateHandEye] C --> D[获取相机-机械臂变换] ``` 3. **精度提升技巧**: - 位姿间旋转角度应大于30° - 平移距离应大于标定板尺寸的20% - 使用高精度标定板(如棋盘格/Charuco板) - 添加光照控制减少图像噪声 ### 相关问题 1. 如何获取高精度的机械臂末端位姿数据? 2. 手眼标定中不同算法(Tsai/Park/Horaud)有何区别? 3. 眼在手上(eye-in-hand)和眼在手外(eye-to-hand)标定有何不同? 4. 如何验证手眼标定结果的精度? 5. 标定过程中出现奇异矩阵错误如何解决? > 提示:实际应用中需确保**机械臂位姿数据**和**相机标定结果**的坐标系定义致。建议使用工业级棋盘格标定板,采集数据时覆盖机械臂工作空间的不同区域[^2]。 [^1]: OpenCV手眼标定函数文档:https://docs.opencv.org/4.x/d9/d0c/group__calib3d.html#gaebfc1c9f7434196a374c382abf43439b [^2]: 相机标定原理与实践:https://learnopencv.com/camera-calibration-using-opencv/
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员进化不脱发!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值