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(基础矩阵)具有特定的含义和作用。以下是它们的详细解释:
- 旋转矩阵 R:
- 旋转矩阵是一个3x3的正交矩阵,用于描述两个坐标系之间的旋转变换。
- 在立体视觉中,它通常表示两个相机坐标系之间的相对旋转。
- 通过旋转矩阵,可以将一个相机坐标系中的点转换到另一个相机坐标系中。
- 平移向量 T:
- 平移向量是一个三维向量,用于描述两个坐标系之间的平移变换。
- 在立体视觉中,它表示一个相机相对于另一个相机在三维空间中的位置偏移。
- 结合旋转矩阵,平移向量可以完整地描述两个相机之间的相对位置关系。
- 本质矩阵 E:
- 本质矩阵是一个3x3的矩阵,专门用于双目相机或多视图立体视觉的情况。
- 它描述了两个相机光心连线和三维空间中同名点构成的平面之间的关系。
- 本质矩阵由相对姿态(旋转矩阵R和平移向量T)派生而来,具体形式可以表示为E = [t]×R,其中[t]×是一个由平移向量t衍生出的反对称矩阵。
- 通过分解本质矩阵,可以得到相机的相对姿态参数(旋转矩阵R和平移向量T)。
- 基础矩阵 F:
- 基础矩阵是一个3x3的矩阵,用于描述在两个不同视点下观测到的同名点对之间的约束关系。
- 在理想情况下,一对共轭的图像点(即立体匹配成功找到的对应点对)必须满足p2TFp1 = 0的关系,其中p1和p2分别是左、右相机图像上的齐次坐标点。
- 基础矩阵由两幅图像的相对运动参数(旋转和平移)确定,但不包含相机的内参数(如焦距、主点等)。
- 通过至少四对匹配点可以估算出基础矩阵,并且可以通过相机内参矩阵将基础矩阵转换为本质矩阵。
这些矩阵和向量在计算机视觉和立体视觉中起着至关重要的作用,它们为我们提供了描述和计算两个相机之间相对运动和空间关系的工具。在实际应用中,这些矩阵和向量通常用于三维重建、目标检测、图像配准等任务。
3、标定双目相机
标签:right,双目,cv2,矩阵,标定,相机,print,left From: https://www.cnblogs.com/excellentHellen/p/18665840