上传文件至 Code
This commit is contained in:
		
							parent
							
								
									433359be75
								
							
						
					
					
						commit
						bace0c9870
					
				
							
								
								
									
										210
									
								
								Code/biaoding.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								Code/biaoding.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,210 @@ | |||||||
|  | import cv2 | ||||||
|  | import os | ||||||
|  | import numpy as np | ||||||
|  | import itertools | ||||||
|  | import yaml | ||||||
|  | 
 | ||||||
|  | # 定义文件夹路径 | ||||||
|  | left_folder = "left" | ||||||
|  | right_folder = "right" | ||||||
|  | 
 | ||||||
|  | # 获取图像文件列表并排序 | ||||||
|  | left_images = sorted(os.listdir(left_folder)) | ||||||
|  | right_images = sorted(os.listdir(right_folder)) | ||||||
|  | 
 | ||||||
|  | # 确保左右相机图像数量一致 | ||||||
|  | assert len(left_images) == len(right_images), "左右相机图像数量不一致" | ||||||
|  | 
 | ||||||
|  | # 加载两个摄像头图片文件夹并将里面的彩图转换为灰度图 | ||||||
|  | def load_images(folder, images): | ||||||
|  |     img_list = [] | ||||||
|  |     for img_name in images: | ||||||
|  |         img_path = os.path.join(folder, img_name) | ||||||
|  |         frame = cv2.imread(img_path) | ||||||
|  |         if frame is not None: | ||||||
|  |             gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) | ||||||
|  |             img_list.append((frame, gray)) | ||||||
|  |         else: | ||||||
|  |             print(f"无法读取图像: {img_path}") | ||||||
|  |     return img_list | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # 检测棋盘格角点 | ||||||
|  | def get_corners(imgs, pattern_size): | ||||||
|  |     corners = [] | ||||||
|  |     for frame, gray in imgs: | ||||||
|  |         ret, c = cv2.findChessboardCorners(gray, pattern_size)     #ret 表示是否成功找到棋盘格角点,c 是一个数组,包含了检测到的角点的坐标 | ||||||
|  |         if not ret: | ||||||
|  |             print("未能检测到棋盘格角点") | ||||||
|  |             continue | ||||||
|  |         c = cv2.cornerSubPix(gray, c, (5, 5), (-1, -1), | ||||||
|  |                              (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))     #cv2.cornerSubPix 函数用于提高棋盘格角点的精确度,对初始检测到的角点坐标 c 进行优化 | ||||||
|  |         corners.append(c)      #将优化后的角点坐标 c 添加到 corners 列表中 | ||||||
|  | 
 | ||||||
|  |         # 绘制角点并显示 | ||||||
|  |         vis = frame.copy() | ||||||
|  |         cv2.drawChessboardCorners(vis, pattern_size, c, ret) | ||||||
|  |         new_size = (1280, 800) | ||||||
|  |         resized_img = cv2.resize(vis, new_size) | ||||||
|  |         cv2.imshow('Corners', resized_img) | ||||||
|  |         cv2.waitKey(150) | ||||||
|  | 
 | ||||||
|  |     return corners | ||||||
|  | 
 | ||||||
|  | # 相机标定 | ||||||
|  | def calibrate_camera(object_points, corners, imgsize): | ||||||
|  |     cm_input = np.eye(3, dtype=np.float32) | ||||||
|  |     ret = cv2.calibrateCamera(object_points, corners, imgsize, cm_input, None) | ||||||
|  |     return ret | ||||||
|  | 
 | ||||||
|  | def save_calibration_to_yaml(file_path, cameraMatrix_l, distCoeffs_l, cameraMatrix_r, distCoeffs_r, R, T, E, F): | ||||||
|  |     data = { | ||||||
|  |         'camera_matrix_left': { | ||||||
|  |             'rows': 3, | ||||||
|  |             'cols': 3, | ||||||
|  |             'dt': 'd', | ||||||
|  |             'data': cameraMatrix_l.flatten().tolist() | ||||||
|  |         }, | ||||||
|  |         'dist_coeff_left': { | ||||||
|  |             'rows': 1, | ||||||
|  |             'cols': 5, | ||||||
|  |             'dt': 'd', | ||||||
|  |             'data': distCoeffs_l.flatten().tolist() | ||||||
|  |         }, | ||||||
|  |         'camera_matrix_right': { | ||||||
|  |             'rows': 3, | ||||||
|  |             'cols': 3, | ||||||
|  |             'dt': 'd', | ||||||
|  |             'data': cameraMatrix_r.flatten().tolist() | ||||||
|  |         }, | ||||||
|  |         'dist_coeff_right': { | ||||||
|  |             'rows': 1, | ||||||
|  |             'cols': 5, | ||||||
|  |             'dt': 'd', | ||||||
|  |             'data': distCoeffs_r.flatten().tolist() | ||||||
|  |         }, | ||||||
|  |         'R': { | ||||||
|  |             'rows': 3, | ||||||
|  |             'cols': 3, | ||||||
|  |             'dt': 'd', | ||||||
|  |             'data': R.flatten().tolist() | ||||||
|  |         }, | ||||||
|  |         'T': { | ||||||
|  |             'rows': 3, | ||||||
|  |             'cols': 1, | ||||||
|  |             'dt': 'd', | ||||||
|  |             'data': T.flatten().tolist() | ||||||
|  |         }, | ||||||
|  |         'E': { | ||||||
|  |             'rows': 3, | ||||||
|  |             'cols': 3, | ||||||
|  |             'dt': 'd', | ||||||
|  |             'data': E.flatten().tolist() | ||||||
|  |         }, | ||||||
|  |         'F': { | ||||||
|  |             'rows': 3, | ||||||
|  |             'cols': 3, | ||||||
|  |             'dt': 'd', | ||||||
|  |             'data': F.flatten().tolist() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     with open(file_path, 'w') as file: | ||||||
|  |         yaml.dump(data, file, default_flow_style=False) | ||||||
|  |     print(f"Calibration parameters saved to {file_path}") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | img_left = load_images(left_folder, left_images)      #img_left是个列表,存放左摄像头所有的灰度图片。 | ||||||
|  | img_right = load_images(right_folder, right_images) | ||||||
|  | pattern_size = (8, 5) | ||||||
|  | corners_left = get_corners(img_left, pattern_size)       #corners_left的长度表示检测到棋盘格角点的图像数量。corners_left[i] 和 corners_right[i] 中存储了第 i 张图像检测到的棋盘格角点的二维坐标。 | ||||||
|  | corners_right = get_corners(img_right, pattern_size) | ||||||
|  | cv2.destroyAllWindows() | ||||||
|  | 
 | ||||||
|  | # 断言,确保所有图像都检测到角点 | ||||||
|  | assert len(corners_left) == len(img_left), "有图像未检测到左相机的角点" | ||||||
|  | assert len(corners_right) == len(img_right), "有图像未检测到右相机的角点" | ||||||
|  | 
 | ||||||
|  | # 准备标定所需数据 | ||||||
|  | points = np.zeros((8 * 5, 3), dtype=np.float32)   #创建40 行 3 列的零矩阵,用于存储棋盘格的三维坐标点。棋盘格的大小是 8 行 5 列,40 个角点。数据类型为 np.float32,这是一张图的,因为一个角点对应一个三维坐标 | ||||||
|  | points[:, :2] = np.mgrid[0:8, 0:5].T.reshape(-1, 2) * 21  #给这些点赋予实际的物理坐标,* 21 是因为每个棋盘格的大小为 21mm | ||||||
|  | 
 | ||||||
|  | object_points = [points] * len(corners_left)     #包含了所有图像中棋盘格的三维物理坐标点 points。这里假设所有图像中棋盘格的物理坐标是相同的,因此用 points 复制 len(corners_left) 次。 | ||||||
|  | imgsize = img_left[0][1].shape[::-1]     #img_left[0] 是左相机图像列表中的第一张图像。img_left[0][1] 是该图像的灰度图像。shape[::-1] 取灰度图像的宽度和高度,并反转顺序,以符合 calibrateCamera 函数的要求。 | ||||||
|  | 
 | ||||||
|  | print('开始左相机标定') | ||||||
|  | ret_l = calibrate_camera(object_points, corners_left, imgsize)    #object_points表示标定板上检测到的棋盘格角点的三维坐标;corners_left[i]表示棋盘格角点在图像中的二维坐标;imgsize表示图像大小 | ||||||
|  | retval_l, cameraMatrix_l, distCoeffs_l, rvecs_l, tvecs_l = ret_l[:5]    #返回值里就包含了标定的参数 | ||||||
|  | 
 | ||||||
|  | print('开始右相机标定') | ||||||
|  | ret_r = calibrate_camera(object_points, corners_right, imgsize) | ||||||
|  | retval_r, cameraMatrix_r, distCoeffs_r, rvecs_r, tvecs_r = ret_r[:5] | ||||||
|  | 
 | ||||||
|  | # 立体标定,得到左右相机的外参:旋转矩阵、平移矩阵、本质矩阵、基本矩阵 | ||||||
|  | print('开始立体标定') | ||||||
|  | criteria_stereo = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-5) | ||||||
|  | ret_stereo = cv2.stereoCalibrate(object_points, corners_left, corners_right, | ||||||
|  |                                  cameraMatrix_l, distCoeffs_l, | ||||||
|  |                                  cameraMatrix_r, distCoeffs_r, | ||||||
|  |                                  imgsize, criteria=criteria_stereo, | ||||||
|  |                                  flags=cv2.CALIB_FIX_INTRINSIC) | ||||||
|  | ret, _, _, _, _, R, T, E, F = ret_stereo | ||||||
|  | 
 | ||||||
|  | # 输出结果 | ||||||
|  | print("左相机内参:\n", cameraMatrix_l) | ||||||
|  | print("左相机畸变系数:\n", distCoeffs_l) | ||||||
|  | print("右相机内参:\n", cameraMatrix_r) | ||||||
|  | print("右相机畸变系数:\n", distCoeffs_r) | ||||||
|  | print("旋转矩阵 R:\n", R) | ||||||
|  | print("平移向量 T:\n", T) | ||||||
|  | print("本质矩阵 E:\n", E) | ||||||
|  | print("基本矩阵 F:\n", F) | ||||||
|  | print("标定完成") | ||||||
|  | 
 | ||||||
|  | # 保存标定结果 | ||||||
|  | save_calibration_to_yaml('calibration_parameters.yaml', cameraMatrix_l, distCoeffs_l, cameraMatrix_r, distCoeffs_r, R, T, E, F) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # 计算重投影误差 | ||||||
|  | def compute_reprojection_errors(objpoints, imgpoints, rvecs, tvecs, mtx, dist): | ||||||
|  |     total_error = 0 | ||||||
|  |     total_points = 0 | ||||||
|  |     for i in range(len(objpoints)): | ||||||
|  |         imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist) | ||||||
|  |         error = cv2.norm(imgpoints[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2) | ||||||
|  |         total_error += error | ||||||
|  |         total_points += len(imgpoints2) | ||||||
|  |     mean_error = total_error / total_points | ||||||
|  |     return mean_error | ||||||
|  | 
 | ||||||
|  | # 计算并打印左相机和右相机的重投影误差 | ||||||
|  | print("左相机重投影误差: ", compute_reprojection_errors(object_points, corners_left, rvecs_l, tvecs_l, cameraMatrix_l, distCoeffs_l)) | ||||||
|  | print("右相机重投影误差: ", compute_reprojection_errors(object_points, corners_right, rvecs_r, tvecs_r, cameraMatrix_r, distCoeffs_r)) | ||||||
|  | 
 | ||||||
|  | # 立体矫正和显示 | ||||||
|  | def stereo_rectify_and_display(img_l, img_r, cameraMatrix_l, distCoeffs_l, cameraMatrix_r, distCoeffs_r, R, T): | ||||||
|  |     img_size = img_l.shape[:2][::-1] | ||||||
|  | 
 | ||||||
|  |     # 立体校正 | ||||||
|  |     R1, R2, P1, P2, Q, _, _ = cv2.stereoRectify(cameraMatrix_l, distCoeffs_l, cameraMatrix_r, distCoeffs_r, img_size, R, T,alpha=0) | ||||||
|  |     map1x, map1y = cv2.initUndistortRectifyMap(cameraMatrix_l, distCoeffs_l, R1, P1, img_size, cv2.CV_32FC1) | ||||||
|  |     map2x, map2y = cv2.initUndistortRectifyMap(cameraMatrix_r, distCoeffs_r, R2, P2, img_size, cv2.CV_32FC1) | ||||||
|  | 
 | ||||||
|  |     # 图像矫正 | ||||||
|  |     rectified_img_l = cv2.remap(img_l, map1x, map1y, cv2.INTER_LINEAR) | ||||||
|  |     rectified_img_r = cv2.remap(img_r, map2x, map2y, cv2.INTER_LINEAR) | ||||||
|  | 
 | ||||||
|  |     # 显示矫正后的图像 | ||||||
|  |     combined_img = np.hstack((rectified_img_l, rectified_img_r)) | ||||||
|  |     cv2.imshow('Rectified Images', combined_img) | ||||||
|  |     cv2.imwrite("stereo_jiaozheng.jpg",combined_img) | ||||||
|  |     cv2.waitKey(0) | ||||||
|  |     cv2.destroyAllWindows() | ||||||
|  | 
 | ||||||
|  | # 加载并矫正示例图像 | ||||||
|  | example_idx = 3 | ||||||
|  | img_l = img_left[example_idx][0] | ||||||
|  | img_r = img_right[example_idx][0] | ||||||
|  | stereo_rectify_and_display(img_l, img_r, cameraMatrix_l, distCoeffs_l, cameraMatrix_r, distCoeffs_r, R, T) | ||||||
							
								
								
									
										55
									
								
								Code/rectify.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								Code/rectify.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | |||||||
|  | import cv2 | ||||||
|  | import yaml | ||||||
|  | import numpy as np | ||||||
|  | 
 | ||||||
|  | # 定义函数读取标定数据 | ||||||
|  | def read_calibration_data(calibration_file): | ||||||
|  |     with open(calibration_file, 'r') as f: | ||||||
|  |         calib_data = yaml.safe_load(f) | ||||||
|  |         cameraMatrix_l = np.array(calib_data['camera_matrix_left']['data']).reshape(3, 3) | ||||||
|  |         distCoeffs_l = np.array(calib_data['dist_coeff_left']['data']) | ||||||
|  |         cameraMatrix_r = np.array(calib_data['camera_matrix_right']['data']).reshape(3, 3) | ||||||
|  |         distCoeffs_r = np.array(calib_data['dist_coeff_right']['data']) | ||||||
|  |         R = np.array(calib_data['R']['data']).reshape(3, 3) | ||||||
|  |         T = np.array(calib_data['T']['data']).reshape(3, 1) | ||||||
|  |     return cameraMatrix_l, distCoeffs_l, cameraMatrix_r, distCoeffs_r, R, T | ||||||
|  | 
 | ||||||
|  | # 定义函数对图像进行矫正 | ||||||
|  | def rectify_images(left_image_path, right_image_path, calibration_file): | ||||||
|  |     # 读取标定数据 | ||||||
|  |     cameraMatrix_l, distCoeffs_l, cameraMatrix_r, distCoeffs_r, R, T = read_calibration_data(calibration_file) | ||||||
|  | 
 | ||||||
|  |     # 读取左右图像 | ||||||
|  |     img_left = cv2.imread(left_image_path) | ||||||
|  |     img_right = cv2.imread(right_image_path) | ||||||
|  | 
 | ||||||
|  |     # 获取图像尺寸(假设左右图像尺寸相同) | ||||||
|  |     img_size = img_left.shape[:2][::-1] | ||||||
|  | 
 | ||||||
|  |     # 立体校正 | ||||||
|  |     R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify(cameraMatrix_l, distCoeffs_l, | ||||||
|  |                                                      cameraMatrix_r, distCoeffs_r, | ||||||
|  |                                                      img_size, R, T) | ||||||
|  | 
 | ||||||
|  |     # 计算映射参数 | ||||||
|  |     map1_l, map2_l = cv2.initUndistortRectifyMap(cameraMatrix_l, distCoeffs_l, R1, P1, img_size, cv2.CV_32FC1) | ||||||
|  |     map1_r, map2_r = cv2.initUndistortRectifyMap(cameraMatrix_r, distCoeffs_r, R2, P2, img_size, cv2.CV_32FC1) | ||||||
|  | 
 | ||||||
|  |     # 应用映射并显示结果 | ||||||
|  |     rectified_img_l = cv2.remap(img_left, map1_l, map2_l, cv2.INTER_LINEAR) | ||||||
|  |     rectified_img_r = cv2.remap(img_right, map1_r, map2_r, cv2.INTER_LINEAR) | ||||||
|  | 
 | ||||||
|  |     # 合并图像显示 | ||||||
|  |     combined_img = np.hstack((rectified_img_l, rectified_img_r)) | ||||||
|  |     cv2.imshow('Rectified Images', combined_img) | ||||||
|  |     cv2.waitKey(0) | ||||||
|  |     cv2.destroyAllWindows() | ||||||
|  | 
 | ||||||
|  | # 设置路径和文件名 | ||||||
|  | left_image_path = "left/left_WIN_20241023_14_54_55_Pro.jpg" | ||||||
|  | right_image_path = "right/right_WIN_20241023_14_54_55_Pro.jpg" | ||||||
|  | calibration_file = "calibration_parameters.yaml" | ||||||
|  | 
 | ||||||
|  | # 调用函数进行图像矫正 | ||||||
|  | rectify_images(left_image_path, right_image_path, calibration_file) | ||||||
|  | 
 | ||||||
							
								
								
									
										48
									
								
								Code/stereo.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								Code/stereo.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | |||||||
|  | import cv2 | ||||||
|  | import os | ||||||
|  | 
 | ||||||
|  | # 定义输入文件夹路径和输出文件夹路径 | ||||||
|  | input_folder = 'images'  # 替换为你的输入文件夹路径 | ||||||
|  | output_folder_left = 'left' | ||||||
|  | output_folder_right = 'right' | ||||||
|  | 
 | ||||||
|  | # 创建输出文件夹,如果不存在则创建 | ||||||
|  | if not os.path.exists(output_folder_left): | ||||||
|  |     os.makedirs(output_folder_left) | ||||||
|  | if not os.path.exists(output_folder_right): | ||||||
|  |     os.makedirs(output_folder_right) | ||||||
|  | 
 | ||||||
|  | # 遍历输入文件夹中的所有图片 | ||||||
|  | for filename in os.listdir(input_folder): | ||||||
|  |     if filename.endswith(".png") or filename.endswith(".jpg"): | ||||||
|  |         # 构建图片的完整路径 | ||||||
|  |         img_path = os.path.join(input_folder, filename) | ||||||
|  |          | ||||||
|  |         # 读取图片 | ||||||
|  |         image = cv2.imread(img_path) | ||||||
|  |          | ||||||
|  |         if image is None: | ||||||
|  |             print(f"无法读取图像文件: {filename}") | ||||||
|  |             continue | ||||||
|  |          | ||||||
|  |         # 获取图片的高度和宽度 | ||||||
|  |         height, width, _ = image.shape | ||||||
|  |          | ||||||
|  |         # 计算左右图像的宽度 | ||||||
|  |         half_width = width // 2 | ||||||
|  |          | ||||||
|  |         # 切割出左半部分和右半部分图像 | ||||||
|  |         left_image = image[:, :half_width] | ||||||
|  |         right_image = image[:, half_width:] | ||||||
|  |          | ||||||
|  |         # 构建保存路径 | ||||||
|  |         left_image_path = os.path.join(output_folder_left, f"left_{filename}") | ||||||
|  |         right_image_path = os.path.join(output_folder_right, f"right_{filename}") | ||||||
|  |          | ||||||
|  |         # 保存左右图像 | ||||||
|  |         cv2.imwrite(left_image_path, left_image) | ||||||
|  |         cv2.imwrite(right_image_path, right_image) | ||||||
|  |          | ||||||
|  |         print(f"已保存:{left_image_path} 和 {right_image_path}") | ||||||
|  | 
 | ||||||
|  | print("所有图像已处理完成!") | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user