(Matrix) Print Pattern

本文介绍了一个程序,该程序读取一个整数n,并打印一个高度为n的图案,图案由2的幂组成,从2^0到2^(n-1)。输入范围限制在1到15之间。

Description

Write a program that reads an interger n, and then displays 2^0, 2^1, … 2^i-1, … 2^0 for each line, where i = n…1. For example, if n=4, the pattern is as follow:

Input

An integer n (1<=n<=15).

Ouput

The Pattern of height n.

Solution:

按照每行元素个数递增的顺序用stack依次存储数字,然后设置输出格式(宽度&靠右)并依次输出栈顶元素。

#include <iostream>
#include <stack>
#include <cmath>
#include <iomanip>
using namespace std;
int main() {
    int m, i = 0;
    cin >> m;
    stack<int> num;
    while(i < m) {
        int j = 0;
        while(j<i+1) {
            num.push(pow(2, j));
            j++;
        }
        j--;
        while(j) {
            j--;
            num.push(pow(2, j));
        }
        i++;
    }
    i = 0;
    while(!num.empty()) {
        int time = 2*m-1;
        for (int k = 0; k < i; k++) {
            cout<<setiosflags(ios::right)<<setw(8);
            cout << " ";
        }
        while(time--) {
            cout<<setiosflags(ios::right)<<setw(8);
            cout << num.top();
            num.pop();  
        }
        cout << endl;
        i++;
        m--;
    }
    cout << endl;
    return 0;
} 
import numpy as np import cv2 import os from matplotlib import pyplot as plt import matplotlib # 设置中文字体支持 def setup_chinese_font(): """设置中文字体支持,避免显示方块""" try: # 方法1: 使用系统自带的中文字体 plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans'] plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 # 方法2: 如果上述方法不行,尝试使用matplotlib的字体管理器 from matplotlib.font_manager import FontProperties chinese_font = None # 尝试常见的中文字体路径 font_paths = [ 'C:/Windows/Fonts/simhei.ttf', # 黑体 'C:/Windows/Fonts/msyh.ttc', # 微软雅黑 'C:/Windows/Fonts/simsun.ttc', # 宋体 ] for font_path in font_paths: if os.path.exists(font_path): chinese_font = FontProperties(fname=font_path) matplotlib.rcParams['font.family'] = chinese_font.get_name() break # 如果找不到中文字体,使用默认字体但避免中文 if chinese_font is None: print("警告: 未找到中文字体,将使用英文显示") return False return True except Exception as e: print(f"字体设置错误: {e}") return False # 在程序开始处调用字体设置 chinese_supported = setup_chinese_font() class ImprovedCameraCalibration: def __init__(self, pattern_size=(6, 4), square_size=0.025): # 核心修改:内角点改为6×4 """ 改进的相机标定类,包含多种角点检测方法 """ self.pattern_size = pattern_size # 6列(x方向)×4行(y方向)内角点 self.square_size = square_size self.objpoints = [] # 3D世界坐标点 self.imgpoints = [] # 2D图像坐标点 self.camera_matrix = None # 相机内参矩阵 self.dist_coeffs = None # 畸变系数 self.rvecs = None # 旋转向量 self.tvecs = None # 平移向量 self.reprojection_error = None # 重投影误差 self.errors_per_image = [] # 每张图像的重投影误差 self.detection_methods_used = [] # 记录每张图像使用的检测方法 def prepare_object_points(self): """准备世界坐标系中的棋盘格角点坐标""" # 核心逻辑不变:生成(6*4, 3)的3D坐标,x方向6个点,y方向4个点 objp = np.zeros((self.pattern_size[0] * self.pattern_size[1], 3), np.float32) objp[:, :2] = np.mgrid[0:self.pattern_size[0], 0:self.pattern_size[1]].T.reshape(-1, 2) objp *= self.square_size return objp def improved_find_chessboard_corners(self, image_path, show_corners=False): """ 改进的角点检测方法,尝试多种预处理技术 返回: (是否成功, 角点坐标, 使用的方法名称) """ # 读取图像 img = cv2.imread(image_path) if img is None: return False, None, "Cannot read image" gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) height, width = gray.shape # 定义不同的预处理方法和参数 methods = [ { "name": "Standard detection", "image": gray, "flags": cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE }, { "name": "Gaussian blur (3x3)", "image": cv2.GaussianBlur(gray, (3, 3), 0), "flags": cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE }, { "name": "Gaussian blur (5x5)", "image": cv2.GaussianBlur(gray, (5, 5), 0), "flags": cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE }, { "name": "Histogram equalization", "image": cv2.equalizeHist(gray), "flags": cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE }, { "name": "Median filter", "image": cv2.medianBlur(gray, 3), "flags": cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE }, { "name": "Bilateral filter", "image": cv2.bilateralFilter(gray, 9, 75, 75), "flags": cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE } ] # 尝试不同的检测标志组合 flag_combinations = [ cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE, cv2.CALIB_CB_FAST_CHECK, cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FILTER_QUADS ] # 首先尝试标准方法(使用修改后的pattern_size=6×4) for method in methods: for flags in flag_combinations: ret, corners = cv2.findChessboardCorners(method["image"], self.pattern_size, flags=flags) if ret: # 亚像素级优化 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) corners_refined = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria) # 验证角点质量:检查角点是否在合理范围内 corners_flat = corners_refined.reshape(-1, 2) x_coords = corners_flat[:, 0] y_coords = corners_flat[:, 1] # 确保角点不会太靠近图像边缘 margin = 20 if (np.min(x_coords) > margin and np.max(x_coords) < width - margin and np.min(y_coords) > margin and np.max(y_coords) < height - margin): if show_corners: img_draw = cv2.drawChessboardCorners(img.copy(), self.pattern_size, corners_refined, ret) plt.figure(figsize=(10, 8)) plt.imshow(cv2.cvtColor(img_draw, cv2.COLOR_BGR2RGB)) # 根据字体支持情况设置标题 if chinese_supported: plt.title(f'检测方法: {method["name"]} - {os.path.basename(image_path)}') else: plt.title(f'Method: {method["name"]} - {os.path.basename(image_path)}') plt.axis('off') plt.show() return True, corners_refined, method["name"] # 如果标准方法都失败,尝试更宽松的条件(使用修改后的pattern_size=6×4) for method in methods: ret, corners = cv2.findChessboardCorners(method["image"], self.pattern_size, flags=cv2.CALIB_CB_ADAPTIVE_THRESH) if ret: criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) corners_refined = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria) if show_corners: img_draw = cv2.drawChessboardCorners(img.copy(), self.pattern_size, corners_refined, ret) plt.figure(figsize=(10, 8)) plt.imshow(cv2.cvtColor(img_draw, cv2.COLOR_BGR2RGB)) # 根据字体支持情况设置标题 if chinese_supported: plt.title(f'检测方法: {method["name"]} (宽松条件) - {os.path.basename(image_path)}') else: plt.title(f'Method: {method["name"]} (Loose condition) - {os.path.basename(image_path)}') plt.axis('off') plt.show() return True, corners_refined, method["name"] + " (Loose condition)" return False, None, "All methods failed" def find_chessboard_corners(self, image_paths, show_corners=False): """检测所有图像中的棋盘格角点(使用改进的方法)""" objp = self.prepare_object_points() if chinese_supported: print("开始检测棋盘格角点(使用改进方法)...") print(f"使用内角点配置: {self.pattern_size[0]} × {self.pattern_size[1]}") # 显示修改后的6×4 else: print("Starting chessboard corner detection (improved method)...") print(f"Using pattern size: {self.pattern_size[0]} × {self.pattern_size[1]}") # 显示修改后的6×4 valid_images = 0 for i, image_path in enumerate(image_paths): print(f"Processing image {i+1}/{len(image_paths)}: {os.path.basename(image_path)}") # 使用改进的角点检测方法(依赖修改后的pattern_size) success, corners, method_used = self.improved_find_chessboard_corners(image_path, show_corners) if success: self.objpoints.append(objp) self.imgpoints.append(corners) self.detection_methods_used.append(method_used) valid_images += 1 print(f" ✓ Successfully found corners (Method: {method_used})") else: print(f" ✗ Failed to find corners") if chinese_supported: print(f"成功检测到 {valid_images}/{len(image_paths)} 张图像的角点") else: print(f"Successfully detected corners in {valid_images}/{len(image_paths)} images") # 打印使用的检测方法统计 if valid_images > 0: if chinese_supported: print("\n检测方法统计:") else: print("\nDetection method statistics:") method_counts = {} for method in self.detection_methods_used: method_counts[method] = method_counts.get(method, 0) + 1 for method, count in method_counts.items(): print(f" {method}: {count} images") return valid_images > 0 def calibrate_camera(self, image_size): """进行相机标定""" if len(self.objpoints) < 3: if chinese_supported: print("错误: 需要至少3张有效图像进行标定") else: print("Error: Need at least 3 valid images for calibration") return False if chinese_supported: print("开始相机标定...") else: print("Starting camera calibration...") # 相机标定(使用修改后的objpoints/imgpoints,对应6×4角点) ret, self.camera_matrix, self.dist_coeffs, self.rvecs, self.tvecs = cv2.calibrateCamera( self.objpoints, self.imgpoints, image_size, None, None) if ret: self.calculate_reprojection_error() return True else: if chinese_supported: print("错误: 相机标定失败") else: print("Error: Camera calibration failed") return False def calculate_reprojection_error(self): """计算重投影误差(逻辑不变,自动适配6×4角点数量)""" total_error = 0 self.errors_per_image = [] for i in range(len(self.objpoints)): # 将3D点投影到2D图像平面 imgpoints2, _ = cv2.projectPoints(self.objpoints[i], self.rvecs[i], self.tvecs[i], self.camera_matrix, self.dist_coeffs) # 计算误差(6×4=24个角点,自动按实际数量计算) error = cv2.norm(self.imgpoints[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2) self.errors_per_image.append(error) total_error += error self.reprojection_error = total_error / len(self.objpoints) return self.reprojection_error def evaluate_calibration_quality(self): """评估标定质量(逻辑不变)""" error = self.reprojection_error if chinese_supported: print(f"\n标定质量评估:") print(f"重投影误差: {error:.6f} 像素") if error < 0.1: print("质量评级: 优秀 - 标定结果非常精确") elif error < 0.3: print("质量评级: 良好 - 标定结果可用于大多数应用") elif error < 0.5: print("质量评级: 可接受 - 标定结果基本可用") else: print("质量评级: 需要改进 - 建议检查图像质量或增加标定图像数量") else: print(f"\nCalibration quality assessment:") print(f"Reprojection error: {error:.6f} pixels") if error < 0.1: print("Quality rating: Excellent - Very accurate calibration") elif error < 0.3: print("Quality rating: Good - Suitable for most applications") elif error < 0.5: print("Quality rating: Acceptable - Basically usable") else: print("Quality rating: Needs improvement - Check image quality or add more images") return error def print_results(self): """打印标定结果(逻辑不变)""" if self.camera_matrix is None: if chinese_supported: print("错误: 请先进行相机标定") else: print("Error: Please calibrate the camera first") return print("\n" + "="*60) if chinese_supported: print("相机标定结果分析") else: print("Camera Calibration Results Analysis") print("="*60) if chinese_supported: print(f"\n1. 相机内参矩阵 (Camera Matrix):") print("[[fx, 0, cx],") print(" [ 0, fy, cy],") print(" [ 0, 0, 1]]") print(f"fx (x轴焦距): {self.camera_matrix[0,0]:.2f} 像素") print(f"fy (y轴焦距): {self.camera_matrix[1,1]:.2f} 像素") print(f"cx (主点x坐标): {self.camera_matrix[0,2]:.2f} 像素") print(f"cy (主点y坐标): {self.camera_matrix[1,2]:.2f} 像素") print(f"\n完整矩阵:") else: print(f"\n1. Camera Intrinsic Matrix:") print("[[fx, 0, cx],") print(" [ 0, fy, cy],") print(" [ 0, 0, 1]]") print(f"fx (focal length x): {self.camera_matrix[0,0]:.2f} pixels") print(f"fy (focal length y): {self.camera_matrix[1,1]:.2f} pixels") print(f"cx (principal point x): {self.camera_matrix[0,2]:.2f} pixels") print(f"cy (principal point y): {self.camera_matrix[1,2]:.2f} pixels") print(f"\nFull matrix:") print(self.camera_matrix) if chinese_supported: print(f"\n2. 畸变系数 (Distortion Coefficients):") print(f"k1 (径向畸变1): {self.dist_coeffs[0,0]:.6f}") print(f"k2 (径向畸变2): {self.dist_coeffs[0,1]:.6f}") print(f"p1 (切向畸变1): {self.dist_coeffs[0,2]:.6f}") print(f"p2 (切向畸变2): {self.dist_coeffs[0,3]:.6f}") else: print(f"\n2. Distortion Coefficients:") print(f"k1 (radial distortion 1): {self.dist_coeffs[0,0]:.6f}") print(f"k2 (radial distortion 2): {self.dist_coeffs[0,1]:.6f}") print(f"p1 (tangential distortion 1): {self.dist_coeffs[0,2]:.6f}") print(f"p2 (tangential distortion 2): {self.dist_coeffs[0,3]:.6f}") if len(self.dist_coeffs[0]) > 4: if chinese_supported: print(f"k3 (径向畸变3): {self.dist_coeffs[0,4]:.6f}") else: print(f"k3 (radial distortion 3): {self.dist_coeffs[0,4]:.6f}") print(f"\n3. 重投影误差分析:" if chinese_supported else "\n3. Reprojection Error Analysis:") self.evaluate_calibration_quality() if chinese_supported: print(f"\n4. 各图像重投影误差 (前10张):") else: print(f"\n4. Reprojection Error per Image (first 10):") # 只显示前10张图像的误差,避免输出过长 for i, error in enumerate(self.errors_per_image[:10]): method = self.detection_methods_used[i] if chinese_supported: print(f" 图像 {i+1}: {error:.6f} 像素 (检测方法: {method})") else: print(f" Image {i+1}: {error:.6f} pixels (Method: {method})") # 显示误差统计信息 if len(self.errors_per_image) > 10: if chinese_supported: print(f" ... (共{len(self.errors_per_image)}张图像)") print(f" 最大误差: {max(self.errors_per_image):.6f} 像素") print(f" 最小误差: {min(self.errors_per_image):.6f} 像素") print(f" 误差标准差: {np.std(self.errors_per_image):.6f} 像素") else: print(f" ... (total {len(self.errors_per_image)} images)") print(f" Max error: {max(self.errors_per_image):.6f} pixels") print(f" Min error: {min(self.errors_per_image):.6f} pixels") print(f" Error std: {np.std(self.errors_per_image):.6f} pixels") if chinese_supported: print(f"\n5. 外参示例 (第一张图像):") else: print(f"\n5. Extrinsic Parameters Example (First Image):") # 将旋转向量转换为旋转矩阵 rmat, _ = cv2.Rodrigues(self.rvecs[0]) if chinese_supported: print(f"旋转矩阵:") else: print(f"Rotation Matrix:") print(rmat) if chinese_supported: print(f"平移向量 (): {self.tvecs[0].flatten()}") else: print(f"Translation Vector (meters): {self.tvecs[0].flatten()}") def visualize_results(self, image_paths): """可视化标定结果(使用修改后的pattern_size绘制角点)""" if self.camera_matrix is None: if chinese_supported: print("错误: 请先进行相机标定") else: print("Error: Please calibrate the camera first") return # 选择前3张图像进行可视化 num_show = min(3, len(image_paths)) fig, axes = plt.subplots(2, num_show, figsize=(5*num_show, 10)) if num_show == 1: axes = axes.reshape(2, 1) for i in range(num_show): img = cv2.imread(image_paths[i]) if img is None: continue # 去畸变 undistorted_img = cv2.undistort(img, self.camera_matrix, self.dist_coeffs) # 绘制角点重投影(使用修改后的pattern_size) imgpoints2, _ = cv2.projectPoints(self.objpoints[i], self.rvecs[i], self.tvecs[i], self.camera_matrix, self.dist_coeffs) # 原始图像(绘制6×4角点) img_with_corners = cv2.drawChessboardCorners(img.copy(), self.pattern_size, self.imgpoints[i], True) axes[0, i].imshow(cv2.cvtColor(img_with_corners, cv2.COLOR_BGR2RGB)) if chinese_supported: axes[0, i].set_title(f'原始图像 {i+1}\n误差: {self.errors_per_image[i]:.4f}px\n方法: {self.detection_methods_used[i]}') else: axes[0, i].set_title(f'Original Image {i+1}\nError: {self.errors_per_image[i]:.4f}px\nMethod: {self.detection_methods_used[i]}') axes[0, i].axis('off') # 去畸变图像 axes[1, i].imshow(cv2.cvtColor(undistorted_img, cv2.COLOR_BGR2RGB)) if chinese_supported: axes[1, i].set_title(f'去畸变后 {i+1}') else: axes[1, i].set_title(f'Undistorted {i+1}') axes[1, i].axis('off') plt.tight_layout() plt.show() # 绘制误差分布图(逻辑不变) plt.figure(figsize=(12, 6)) x_pos = range(1, len(self.errors_per_image)+1) bars = plt.bar(x_pos, self.errors_per_image) # 为不同检测方法使用不同颜色 method_colors = {} colors = ['blue', 'green', 'red', 'orange', 'purple', 'brown'] for i, method in enumerate(self.detection_methods_used): if method not in method_colors: method_colors[method] = colors[len(method_colors) % len(colors)] bars[i].set_color(method_colors[method]) plt.axhline(y=self.reprojection_error, color='r', linestyle='--', label=f'Average error: {self.reprojection_error:.4f}px') plt.xlabel('Image Number') plt.ylabel('Reprojection Error (pixels)') if chinese_supported: plt.title('各图像重投影误差分布 (颜色表示检测方法)') else: plt.title('Reprojection Error Distribution (Color indicates detection method)') # 添加图例 legend_handles = [] for method, color in method_colors.items(): legend_handles.append(plt.Rectangle((0,0),1,1, color=color, label=method)) legend_handles.append(plt.Line2D([0],[0], color='r', linestyle='--', label=f'Average error')) plt.legend(handles=legend_handles) plt.grid(True, alpha=0.3) plt.show() def main(): # 修改为新的数据集路径:从1.jpg到60.jpg image_dir = r"F:\JIQISHIJUE\13" image_paths = [] # 生成从1到60的图像路径 for i in range(1, 61): filename = f"{i}.jpg" full_path = os.path.join(image_dir, filename) image_paths.append(full_path) # 检查图像文件是否存在 existing_paths = [] for path in image_paths: if os.path.exists(path): existing_paths.append(path) else: print(f"Warning: Image file does not exist: {path}") if not existing_paths: print(f"Error: No image files found") return print(f"Found {len(existing_paths)} images:") # 只显示前10个文件路径,避免输出过长 for path in existing_paths[:10]: print(f" {os.path.basename(path)}") if len(existing_paths) > 10: print(f" ... (and {len(existing_paths)-10} more images)") # 创建改进的标定对象,核心修改:内角点设置为6×4 calibrator = ImprovedCameraCalibration(pattern_size=(6, 4), square_size=0.025) # 检测角点(设置show_corners=False避免显示过多图像) success = calibrator.find_chessboard_corners(existing_paths, show_corners=False) if not success: if chinese_supported: print("错误: 角点检测失败") print("可能的原因:") print("1. 棋盘格内角点数量设置不正确") print("2. 图像质量不佳") print("3. 棋盘格在图像中不完整或被遮挡") print("4. 棋盘格太小或太大") else: print("Error: Corner detection failed") print("Possible reasons:") print("1. Incorrect pattern size setting") print("2. Poor image quality") print("3. Chessboard not fully visible or occluded") print("4. Chessboard too small or too large") return # 获取图像尺寸 sample_img = cv2.imread(existing_paths[0]) image_size = (sample_img.shape[1], sample_img.shape[0]) print(f"Image size: {image_size}") # 进行相机标定 success = calibrator.calibrate_camera(image_size) if success: # 打印详细结果 calibrator.print_results() # 可视化结果 calibrator.visualize_results(existing_paths) # 保存标定结果(文件名添加6x4标识,避免与原结果混淆) np.savez('camera_calibration_6x4_results.npz', camera_matrix=calibrator.camera_matrix, dist_coeffs=calibrator.dist_coeffs, reprojection_error=calibrator.reprojection_error, image_size=image_size, detection_methods=calibrator.detection_methods_used) if chinese_supported: print(f"\n标定结果已保存到 'camera_calibration_6x4_results.npz'") else: print(f"\nCalibration results saved to 'camera_calibration_6x4_results.npz'") # 保存可用于OpenCV的YAML文件(文件名添加6x4标识) fs = cv2.FileStorage("camera_calibration_6x4.yml", cv2.FILE_STORAGE_WRITE) fs.write("camera_matrix", calibrator.camera_matrix) fs.write("distortion_coefficients", calibrator.dist_coeffs) fs.write("reprojection_error", calibrator.reprojection_error) fs.write("image_width", image_size[0]) fs.write("image_height", image_size[1]) fs.release() if chinese_supported: print(f"标定结果已保存到 'camera_calibration_6x4.yml'") else: print(f"Calibration results saved to 'camera_calibration_6x4.yml'") else: if chinese_supported: print("相机标定失败") else: print("Camera calibration failed") if __name__ == "__main__": main()把这里面的文件地址修改为"D:\jupyter notebook\homework3\images\13"
09-26
import cv2 import os import numpy as np import itertools import yaml # 定义文件夹路径 left_folder = "D:/homework/imgs/leftcamera" right_folder = "D:/homework/imgs/rightcamera" # 获取图像文件列表并排序 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 = (11, 7) 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((11 * 7, 3), dtype=np.float32) #创建40 行 3 列的零矩阵,用于存储棋盘格的三维坐标点。棋盘格的大小是 8 行 5 列,40 个角点。数据类型为 np.float32,这是一张图的,因为一个角点对应一个三维坐标 points[:, :2] = np.mgrid[0:11, 0:7].T.reshape(-1, 2) * 25 #给这些点赋予实际的物理坐标,* 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) 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.png",combined_img) cv2.waitKey(0) cv2.destroyAllWindows() # 加载并矫正示例图像 example_idx = 0 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) 级线颜色改成蓝色
12-01
先看效果: https://pan.quark.cn/s/c7070e7537b1 [!NOTE] 每到答辩季我就会喜获stars,谢谢大家的支持! 欢迎推广传播本repo(https://.com/atomiechen/THU-PPT-Theme),也欢迎贡献变体,提供更多选择 清华简约主题PPT模板 Repo stars 2020年春夏之交,答辩期间很多同学都在寻找清华主题的答辩模板。 一方面有使用LaTeX制作Beamer的模板(见Overleaf上的模板THU Beamer Theme),另一方面民间也存在着一些PPT模板。 很多人可能不适应Beamer的使用(主要是内容和排版设计不是可见即所得,定制有门槛),以及我找到的PPT模板也都不太好使(要么图案设计太复杂、不好看,要么没有制作成PPT母版导致每次使用都要复制粘贴+微调,不方便)。 我制作了清华简约主题的PPT模板,后续有新的设计我会逐渐加入,也欢迎有兴趣有想法的朋友们添砖加瓦! 内容 所有模板均为 文件。 此外也提供转换脚本用于 Pandoc自动生成PPTX。 各个版本的修改历史见 CHANGELOG.md。 下载 推荐直接从 Releases 下载最新发布版。 也可以在 仓库 单独下载所需文件。 效果 16:9比例,v1留边、v1顶边、v3留边白底、v3顶边白底: demo 16:9比例,其他风格模板:v1扁平、v2扁平、v1暗光 demo2 其他变体设计参见 variants/README.md。 使用方式 可以基于所提供的文件自行修改内容,也可以在新建的PPT文稿中应用该模板。 后者在 MS Office 2019 For Mac 的 PowerPoint 里的具体使用方式为:首先选择幻灯片尺...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值