首页 > 其他分享 >代码记录 -学习标定双目相机

代码记录 -学习标定双目相机

时间:2025-01-11 16:56:17浏览次数:1  
标签:right 双目 cv2 矩阵 标定 相机 print left

 

1、棋盘格拍照  20份以上

import cv2
import os

cap = cv2.VideoCapture(1)

# set the video frame width and height
cap.set(3,1280)
cap.set(4,480)

if not os.path.exists("left"):
    os.makedirs("left")

if not os.path.exists("right"):
    os.makedirs("right")

i = 1
try:
    while True:
        ret, frame = cap.read()
        if not ret:
            print("Failed to capture video")
            break

        # split the frame into left and right
        left_frame = frame[:, :640, :]
        right_frame = frame[:, 640:, :]

        cv2.imshow("Left Camera", left_frame)
        cv2.imshow("Right Camera", right_frame)

        key = cv2.waitKey(1) & 0xFF

        if key == ord('q'):
            break
        elif key == ord('s'):
            left_filename = "left" + str(i) + ".png"
            right_filename = "right" + str(i) + ".png"
            cv2.imwrite("left/" + left_filename, left_frame)
            cv2.imwrite("right/" + right_filename, right_frame)
            print("Image saved! left image:", left_filename)
            print("Image saved! right image:", right_filename)
            i += 1

except KeyboardInterrupt:
    cv2.destroyAllWindows()
    cap.release()

2、标定双目相机

# 文心一言 生成代码

import cv2
import numpy as np
import glob

# 棋盘格尺寸 (内部交叉点的数量)
chessboard_size = (12-1, 9-1) # 使用的12行*9列方块组成的棋盘格,填错时程序报错:找不到角点
square_size = 15.0  # 棋盘格每个小格的边长,单位为毫米

# 用于存储三维点和二维点的列表
objpoints = []  # 三维点在世界坐标系中的位置
imgpoints_left = []  # 左相机图像中的二维点
imgpoints_right = []  # 右相机图像中的二维点

# 准备棋盘格角点的三维坐标 (0,0,0), (1,0,0), (2,0,0), ..., (8,5,0)
objp = np.zeros((chessboard_size[0]*chessboard_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2)
objp *= square_size

# 加载左右相机的棋盘格图像
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

left_images = glob.glob('left/*.png')  # 替换为你的左相机图像路径
right_images = glob.glob('right/*.png')  # 替换为你的右相机图像路径

print(left_images )
assert len(left_images) == len(right_images), "左右相机图像数量不一致"

for left_img_path, right_img_path in zip(left_images, right_images):
    print(f"处理图像对: {left_img_path}, {right_img_path}")  # 添加打印语句以显示正在处理的图像对
    left_img = cv2.imread(left_img_path)
    right_img = cv2.imread(right_img_path)

    if left_img is None or right_img is None:
        print("警告: 无法加载一张或多张图像!")
        continue  # 跳过无法加载的图像对

    gray_left = cv2.cvtColor(left_img, cv2.COLOR_BGR2GRAY)
    gray_right = cv2.cvtColor(right_img, cv2.COLOR_BGR2GRAY)

    # 查找棋盘格角点
    ret_left, corners_left = cv2.findChessboardCorners(gray_left, chessboard_size, None)
    ret_right, corners_right = cv2.findChessboardCorners(gray_right, chessboard_size, None)

    # 输出角点检测结果
    print(f"左图像角点检测结果: {ret_left}")
    print(f"右图像角点检测结果: {ret_right}")

    if ret_left and ret_right:
        objpoints.append(objp)

        corners_left = cv2.cornerSubPix(gray_left, corners_left, (11, 11), (-1, -1), criteria)
        imgpoints_left.append(corners_left)

        corners_right = cv2.cornerSubPix(gray_right, corners_right, (11, 11), (-1, -1), criteria)
        imgpoints_right.append(corners_right)
    else:
        print("警告: 在一张或多张图像中未检测到棋盘格角点,跳过这对图像!")

# 检查是否有有效的角点数据
if not objpoints or not imgpoints_left or not imgpoints_right:
    print("错误: 没有有效的角点数据用于相机标定!")
else:
# 标定相机(这部分代码与之前相同)
    # 标定相机
    ret_left, mtx_left, dist_left, rvecs_left, tvecs_left = cv2.calibrateCamera(objpoints, imgpoints_left, gray_left.shape[::-1], None, None)
    ret_right, mtx_right, dist_right, rvecs_right, tvecs_right = cv2.calibrateCamera(objpoints, imgpoints_right, gray_right.shape[::-1], None, None)

    # 双目相机标定
    flags = cv2.CALIB_FIX_INTRINSIC + cv2.CALIB_USE_INTRINSIC_GUESS
    criteria_stereo = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-5)

    ret, camera_matrix1, dist_coeffs1, camera_matrix2, dist_coeffs2, T, E, R, F= cv2.stereoCalibrate(objpoints, imgpoints_left, imgpoints_right,
                                                 mtx_left, dist_left, mtx_right, dist_right,
                                                 gray_left.shape[::-1], criteria_stereo, flags=flags)
    # R 是旋转矩阵,T 是平移向量,E 是本质矩阵,F 是基础矩阵
    # 注意:根据您使用的OpenCV版本和传递的参数,返回值可能有所不同
    # 如果您不需要所有返回值,可以只接收您需要的部分

    # 计算重投影误差
    mean_error_left = 0
    mean_error_right = 0
    for i in range(len(objpoints)):
        imgpoints_left_proj, _ = cv2.projectPoints(objpoints[i], rvecs_left[i], tvecs_left[i], mtx_left, dist_left)
        imgpoints_right_proj, _ = cv2.projectPoints(objpoints[i], rvecs_right[i], tvecs_right[i], mtx_right, dist_right)
        error_left = cv2.norm(imgpoints_left[i], imgpoints_left_proj, cv2.NORM_L2) / len(imgpoints_left[i])
        error_right = cv2.norm(imgpoints_right[i], imgpoints_right_proj, cv2.NORM_L2) / len(imgpoints_right[i])
        mean_error_left += error_left
        mean_error_right += error_right

print(f"左相机重投影误差: {mean_error_left / len(objpoints)}")
print(f"右相机重投影误差: {mean_error_right / len(objpoints)}")

# 输出标定结果
print("左相机内参矩阵:\n", mtx_left)
print("左相机内参矩阵:\n", camera_matrix1)

print("左相机畸变系数:\n", dist_left)

print("右相机内参矩阵:\n", mtx_right)
print("右相机内参矩阵:\n", camera_matrix2)

print("右相机畸变系数:\n", dist_right)
print("旋转矩阵:\n", R)
print("平移向量:\n", T)
print("本质矩阵:\n", E)#E(本质矩阵)
print("基本矩阵:\n", F)#F(基础矩阵)

# 已经完成了双目摄像机的标定,并且得到了以下结果:
# R: 旋转矩阵
# T: 平移向量
# camera_matrix1, dist_coeffs1: 左相机的内参矩阵和畸变系数
# camera_matrix2, dist_coeffs2: 右相机的内参矩阵和畸变系数
# 保存数据
np.save('R.npy', R)#F(旋转矩阵)
np.save('T.npy', T)#F(平移向量)
np.save('E.npy', E)#F(基础矩阵)
np.save('F.npy', F)#E(本质矩阵)
np.save('camera_matrix1.npy', camera_matrix1)
np.save('camera_matrix2.npy', camera_matrix2)
np.save('dist_coeffs1.npy', dist_coeffs1)
np.save('dist_coeffs2.npy', dist_coeffs2)

#import numpy as np
# 已经完成了双目摄像机的标定,并且将得到了的结果保存在npy文件中:
# R: 旋转矩阵
# T: 平移向量
# camera_matrix1, dist_coeffs1: 左相机的内参矩阵和畸变系数
# camera_matrix2, dist_coeffs2: 右相机的内参矩阵和畸变系数
# 读取数据
_R = np.load('R.npy')
_T = np.load('T.npy')
_E = np.load('E.npy')
_F = np.load('F.npy')
_camera_matrix1= np.load('camera_matrix1.npy')
_camera_matrix2 = np.load('camera_matrix2.npy')
_dist_coeffs1 = np.load('dist_coeffs1.npy')
_dist_coeffs2 = np.load('dist_coeffs2.npy')
print("基本矩阵:\n", _F)#F(基础矩阵)

 

在计算机视觉和立体视觉中,R(旋转矩阵)、T(平移向量)、E(本质矩阵)和F(基础矩阵)具有特定的含义和作用。以下是它们的详细解释:

  1. 旋转矩阵 R:
    • 旋转矩阵是一个3x3的正交矩阵,用于描述两个坐标系之间的旋转变换。
    • 在立体视觉中,它通常表示两个相机坐标系之间的相对旋转。
    • 通过旋转矩阵,可以将一个相机坐标系中的点转换到另一个相机坐标系中。
  2. 平移向量 T:
    • 平移向量是一个三维向量,用于描述两个坐标系之间的平移变换。
    • 在立体视觉中,它表示一个相机相对于另一个相机在三维空间中的位置偏移。
    • 结合旋转矩阵,平移向量可以完整地描述两个相机之间的相对位置关系。
  3. 本质矩阵 E:
    • 本质矩阵是一个3x3的矩阵,专门用于双目相机或多视图立体视觉的情况。
    • 它描述了两个相机光心连线和三维空间中同名点构成的平面之间的关系。
    • 本质矩阵由相对姿态(旋转矩阵R和平移向量T)派生而来,具体形式可以表示为E = [t]×R,其中[t]×是一个由平移向量t衍生出的反对称矩阵。
    • 通过分解本质矩阵,可以得到相机的相对姿态参数(旋转矩阵R和平移向量T)。
  4. 基础矩阵 F:
    • 基础矩阵是一个3x3的矩阵,用于描述在两个不同视点下观测到的同名点对之间的约束关系。
    • 在理想情况下,一对共轭的图像点(即立体匹配成功找到的对应点对)必须满足p2TFp1 = 0的关系,其中p1和p2分别是左、右相机图像上的齐次坐标点。
    • 基础矩阵由两幅图像的相对运动参数(旋转和平移)确定,但不包含相机的内参数(如焦距、主点等)。
    • 通过至少四对匹配点可以估算出基础矩阵,并且可以通过相机内参矩阵将基础矩阵转换为本质矩阵。

这些矩阵和向量在计算机视觉和立体视觉中起着至关重要的作用,它们为我们提供了描述和计算两个相机之间相对运动和空间关系的工具。在实际应用中,这些矩阵和向量通常用于三维重建、目标检测、图像配准等任务。

 

3、标定双目相机

标签:right,双目,cv2,矩阵,标定,相机,print,left
From: https://www.cnblogs.com/excellentHellen/p/18665840

相关文章

  • OpenCV相机标定与3D重建(53)解决 Perspective-3-Point (P3P) 问题函数solveP3P()的使
    操作系统:ubuntu22.04OpenCV版本:OpenCV4.9IDE:VisualStudioCode编程语言:C++11算法描述根据3个3D-2D点对应关系找到物体的姿态。cv::solveP3P是OpenCV中的一个函数,用于解决Perspective-3-Point(P3P)问题。该问题的目标是根据给定的三个空间点(世界坐标系中......
  • 《鸿蒙开发-答案之书》使用系统相机拍照
    《鸿蒙开发-答案之书》使用系统相机拍照调用系统相机拍照,不用询问拍照权限直接上代码:/***@desc:使用系统相机拍照*@author:conggeon2024-07-1310:56*注:不用申请相机权限**/publicstaticasyncusePhoto(context:common.UIAbilityContext......
  • 3D视觉工坊 | UC伯克利重磅开源HSfM:联合估计3D重建、相机位姿、3D人体姿态!
    本文来源公众号“3D视觉工坊”,仅用于学术分享,侵权删,干货满满。原文链接:UC伯克利重磅开源HSfM:联合估计3D重建、相机位姿、3D人体姿态!0.论文信息标题:ReconstructingPeople,Places,andCameras作者:LeaMüller,HongsukChoi,AnthonyZhang,BrentYi,JitendraMalik,A......
  • matlab的标定工具箱
    https://blog.csdn.net/weixin_43159148/article/details/97918258https://blog.csdn.net/qq_41372644/article/details/121089361Camera1Intrinsics相机1内参Focallength(pixels):[534.3145+/-0.3389534.3111+/-0.3287]Principalpoint(pixels):[3......
  • 相机的镜像畸变和切向畸变公式
    在相机标定中,镜像畸变和切向畸变是常见的畸变类型。它们通过特定的公式来描述,通常使用相机的内参和畸变系数来进行补偿。1.镜像畸变(径向畸变)镜像畸变主要是由于镜头的光学特性引起的,通常用以下公式表示:[x_{d}=x(1+k_1r^2+k_2r^4+k_3r^6)][y_{d}=y(1+k_1r^......
  • VS相机和AM521之间的EIP通讯
    1,设置VS系列相机的IP地址 2,设置VS系列的EIP通讯为有效 3, 切换VS系列的设置模式和运行模式 4,输入触发并接受综合判定 5,切换检测程序在设置模式下无法切换检测程序。需要在运行模式下执行。      6,输出检测值,判定值  ......
  • opencv中标定函数
    calibrateCamera在OpenCV中,calibrateCamera函数用于进行相机标定,估计相机的内参和外参。相机标定的目的是确定相机在三维空间中的位置和方向,以及其光学特性。函数原型doublecv::calibrateCamera(conststd::vector<std::vector<cv::Point3f>>&objectPoints,cons......
  • opencv中findCirclesGrid在标定时使用,blobDetector 参数怎么定义?
    在OpenCV中,findCirclesGrid是一个用于检测图像中的圆形格点(通常用于相机标定或校正的检测目标)的函数。它可以用于查找在特定模式下排列的圆形图案,如棋盘格或圆形网格。该函数是相机标定和立体视觉的重要工具。函数原型boolcv::findCirclesGrid(InputArrayimage,S......
  • 飞拍如何进行相机选型计算
    飞拍如何进行相机选型计算相机飞拍存在拖影问题,需正确选择高帧率,高频高亮光源,以及短曝光值。公式:曝光时间*物体运动速度≤运动方向精度需求即(1/实际帧率)*物体运动速度≤运动方向精度需求飞拍一般要求:精度要求拖影不超过1/2像素例如:相机现在的曝光时间是200......
  • 激光雷达和相机联合半自动标定
    文章目录1.背景描述2.整体架构3.核心理论3.1相机内外参3.2自动标定4.关键代码4.1读取雷达点云4.2读取相机图像4.3点云分割找棋盘格4.4相机内参标定4.5图像棋盘格描点4.6世界坐标系转相机坐标系4.6保存内外参数5.总体结论6.......