opencv stereoCalibrate/stereoRectify/StereoSGBM_create函数参数解析

本文详细介绍了双目视觉的关键步骤,包括相机标定(调整相机参数以获取准确的世界坐标)、立体校正(纠正图像扭曲,使两视图对应正确)和立体匹配(计算深度信息)。通过实例参数解读,帮助理解如何在实际项目中应用这些技术。

双目视觉主要步骤:相机标定--立体校正--立体匹配

1、双目相机标定:

stereoCalibrate(objectPoints, imagePoints1, imagePoints2, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R=None, T=None, E=None, F=None, flags=None, criteria=None)

# 参数含义
objectPoints- vector<point3f> 型的数据结构,存储标定角点在世界坐标系中的位置
imagePoints1- vector<vector<point2f>> 型的数据结构,存储标定角点在第一个摄像机下的投影后的亚像素坐标
imagePoints2- vector<vector<point2f>> 型的数据结构,存储标定角点在第二个摄像机下的投影后的亚像素坐标
cameraMatrix1-输入/输出型的第一个摄像机的相机矩阵。如果CV_CALIB_USE_INTRINSIC_GUESS , CV_CALIB_FIX_ASPECT_RATIO ,CV_CALIB_FIX_INTRINSIC , or CV_CALIB_FIX_FOCAL_LENGTH其中的一个或多个标志被设置,该摄像机矩阵的一些或全部参数需要被初始化
distCoeffs1-第一个摄像机的输入/输出型畸变向量。根据矫正模型的不同,输出向量长度由标志决定
cameraMatrix2-输入/输出型的第二个摄像机的相机矩阵。参数意义同第一个相机矩阵相似
distCoeffs2-第一个摄像机的输入/输出型畸变向量。根据矫正模型的不同,输出向量长度由标志决定
imageSize-图像的大小
R-输出型,第一和第二个摄像机之间的旋转矩阵
T-输出型,第一和第二个摄像机之间的平移矩阵
E-输出型,基本矩阵
F-输出型,

import cv2 import numpy as np import glob import matplotlib.pyplot as plt # ====================== 1. 相机标定 ====================== # ====================== 1. 相机标定 ====================== def stereo_calibration(left_images, right_images, checkerboard_size, square_size): """计算相机内参和外参""" # 准备标定板角点坐标 objpoints = [] # 3D点 imgpoints_left = [] # 左相机2D点 imgpoints_right = [] # 右相机2D点 # 提前定义图像尺寸变量 img_size = None # 创建标定板世界坐标 (0,0,0), (1,0,0), ... (8,5,0) objp = np.zeros((checkerboard_size[0] * checkerboard_size[1], 3), np.float32) objp[:, :2] = np.mgrid[0:checkerboard_size[0], 0:checkerboard_size[1]].T.reshape(-1, 2) * square_size # 检测左右图像角点 for left_img, right_img in zip(left_images, right_images): # 转换为灰度图 gray_left = cv2.cvtColor(left_img, cv2.COLOR_BGR2GRAY) gray_right = cv2.cvtColor(right_img, cv2.COLOR_BGR2GRAY) # 保存图像尺寸(所有图像应相同) img_size = gray_left.shape[::-1] # (width, height) # 检测角点 ret_left, corners_left = cv2.findChessboardCorners(gray_left, checkerboard_size, None) ret_right, corners_right = cv2.findChessboardCorners(gray_right, checkerboard_size, None) if ret_left and ret_right: # 亚像素级精确化 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) corners_left = cv2.cornerSubPix(gray_left, corners_left, (11, 11), (-1, -1), criteria) corners_right = cv2.cornerSubPix(gray_right, corners_right, (11, 11), (-1, -1), criteria) objpoints.append(objp) imgpoints_left.append(corners_left) imgpoints_right.append(corners_right) # 检查是否检测到角点 if len(objpoints) == 0: raise ValueError("未检测到任何有效的标定板角点!请检查:\n" "1. 图像路径是否正确\n" "2. 标定板尺寸设置是否正确\n" "3. 标定板是否在图像中清晰可见") # 检查图像尺寸是否已设置 if img_size is None: # 如果所有图像都失败,使用第一张图像的尺寸 gray_left = cv2.cvtColor(left_images[0], cv2.COLOR_BGR2GRAY) img_size = gray_left.shape[::-1] # 单目标定(获取初始内参) ret, mtx_left, dist_left, _, _ = cv2.calibrateCamera( objpoints, imgpoints_left, img_size, None, None) ret, mtx_right, dist_right, _, _ = cv2.calibrateCamera( objpoints, imgpoints_right, img_size, None, None) # 双目标定(获取外参) flags = cv2.CALIB_FIX_INTRINSIC ret, _, _, _, _, R, T, E, F = cv2.stereoCalibrate( objpoints, imgpoints_left, imgpoints_right, mtx_left, dist_left, mtx_right, dist_right, img_size, flags=flags ) return mtx_left, dist_left, mtx_right, dist_right, R, T # ====================== 2. 立体校正 ====================== def stereo_rectification(left_img, right_img, mtx_left, dist_left, mtx_right, dist_right, R, T): """校正图像并计算重映射矩阵""" # 计算校正矩阵 R1, R2, P1, P2, Q, roi_left, roi_right = cv2.stereoRectify( mtx_left, dist_left, mtx_right, dist_right, left_img.shape[:2], R, T, alpha=0 ) # 计算重映射矩阵 map_left_x, map_left_y = cv2.initUndistortRectifyMap( mtx_left, dist_left, R1, P1, left_img.shape[:2], cv2.CV_16SC2) map_right_x, map_right_y = cv2.initUndistortRectifyMap( mtx_right, dist_right, R2, P2, right_img.shape[:2], cv2.CV_16SC2) # 重映射图像 rect_left = cv2.remap(left_img, map_left_x, map_left_y, cv2.INTER_LINEAR) rect_right = cv2.remap(right_img, map_right_x, map_right_y, cv2.INTER_LINEAR) return rect_left, rect_right, Q # ====================== 3. 视差计算 ====================== def compute_disparity(rect_left, rect_right): """使用SGBM算法计算视差图""" # 转换为灰度图 gray_left = cv2.cvtColor(rect_left, cv2.COLOR_BGR2GRAY) gray_right = cv2.cvtColor(rect_right, cv2.COLOR_BGR2GRAY) # 创建SGBM对象 window_size = 5 min_disp = 0 num_disp = 16 * 5 stereo = cv2.StereoSGBM_create( minDisparity=min_disp, numDisparities=num_disp, blockSize=window_size, P1=8 * 3 * window_size ** 2, P2=32 * 3 * window_size ** 2, disp12MaxDiff=1, uniquenessRatio=15, speckleWindowSize=0, speckleRange=2, preFilterCap=63, mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY ) # 计算视差 disp = stereo.compute(gray_left, gray_right).astype(np.float32) / 16.0 # 后处理:中值滤波去除噪声 disp = cv2.medianBlur(disp, 5) return disp # ====================== 4. 深度图生成 ====================== def disparity_to_depth(disparity, Q): """将视差图转换为深度图""" # 使用重投影矩阵Q计算深度 depth = cv2.reprojectImageTo3D(disparity, Q)[:, :, 2] # 处理无效值(视差为0的点) depth[disparity == 0] = 0 # 归一化深度图用于显示 depth_norm = cv2.normalize(depth, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U) return depth, depth_norm # ====================== 主程序 ====================== if __name__ == "__main__": # 参数配置 # ---------------- 参数区 ----------------- CHESSBOARD = (8, 6) # 棋盘格内角点 (列, 行) SQUARE_SIZE = 25.0 # 棋盘格单格物理尺寸,单位 mm IMG_DIR = './stereo' # 图片目录 LEFT_IMG_PATH = 'left_*.png' # 左图标识(添加通配符) RIGHT_IMG_PATH = 'right_*.png' # 右图标识(添加通配符) # --------------------------------------- # 1. 加载标定图像 left_images = [cv2.imread(img) for img in sorted(glob.glob(LEFT_IMG_PATH))] right_images = [cv2.imread(img) for img in sorted(glob.glob(RIGHT_IMG_PATH))] # 添加检查确保图像加载成功 if len(left_images) == 0 or len(right_images) == 0: raise FileNotFoundError(f"未找到匹配的图像文件。请检查路径: {LEFT_IMG_PATH} 和 {RIGHT_IMG_PATH}") # 2. 执行双目标定 (修正参数传递) print("开始相机标定...") mtx_left, dist_left, mtx_right, dist_right, R, T = stereo_calibration( left_images, right_images, CHESSBOARD, SQUARE_SIZE # 添加了CHESSBOARD参数 ) # 打印标定结果 print(f"左相机内参:\n{mtx_left}") print(f"左相机畸变系数:\n{dist_left}") print(f"右相机内参:\n{mtx_right}") print(f"右相机畸变系数:\n{dist_right}") print(f"旋转矩阵:\n{R}") print(f"平移向量:\n{T}") # 3. 加载测试图像(需要添加测试图像加载) TEST_LEFT = 'test_left.png' TEST_RIGHT = 'test_right.png' test_left = cv2.imread(TEST_LEFT) test_right = cv2.imread(TEST_RIGHT) if test_left is None or test_right is None: raise FileNotFoundError(f"未找到测试图像: {TEST_LEFT} 或 {TEST_RIGHT}") # 4. 立体校正 print("执行立体校正...") rect_left, rect_right, Q = stereo_rectification( test_left, test_right, mtx_left, dist_left, mtx_right, dist_right, R, T ) # 5. 计算视差图 print("计算视差图...") disparity = compute_disparity(rect_left, rect_right) # 6. 生成深度图 print("生成深度图...") depth, depth_norm = disparity_to_depth(disparity, Q) # 7. 结果显示 (修正显示问题) plt.figure(figsize=(15, 10)) plt.subplot(231), plt.imshow(cv2.cvtColor(test_left, cv2.COLOR_BGR2RGB)) plt.title('原始左图'), plt.axis('off') plt.subplot(232), plt.imshow(cv2.cvtColor(rect_left, cv2.COLOR_BGR2RGB)) plt.title('校正左图'), plt.axis('off') plt.subplot(233), plt.imshow(disparity, cmap='jet') plt.title('视差图'), plt.axis('off'), plt.colorbar() plt.subplot(234), plt.imshow(depth_norm, cmap='jet') plt.title('深度图(归一化)'), plt.axis('off'), plt.colorbar() plt.subplot(235), plt.imshow(cv2.cvtColor(rect_left, cv2.COLOR_BGR2RGB)) plt.imshow(depth_norm, cmap='jet', alpha=0.5) plt.title('深度叠加图'), plt.axis('off') plt.tight_layout() plt.savefig('depth_result.png', dpi=300) plt.show() # 8. 保存结果 cv2.imwrite("disparity.png", disparity) cv2.imwrite("depth.png", depth_norm) np.savez("calibration_params.npz", mtx_left=mtx_left, dist_left=dist_left, mtx_right=mtx_right, dist_right=dist_right, R=R, T=T, Q=Q) print("处理完成! 结果已保存") 前面这段代码测试图像应该如何命名
最新发布
12-02
<think>好的,我现在需要解决用户提到的在OpenCV中'StereoSGBM_create'在'__init__.pyi'文件中找不到引用的问题。首先,我得理解这个问题出现的原因。用户可能是在使用Python的OpenCV时,在IDE(比如PyCharm或VS Code)中遇到这个引用错误,提示找不到StereoSGBM_create方法,尽管代码运行时可能没有问题。 首先,我应该考虑可能的原因。常见的情况包括OpenCV版本问题、IDE的静态类型检查器(如mypy或Pyright)无法识别某些方法,或者安装不完整。比如,用户可能安装了opencv-python而不是opencv-contrib-python,因为StereoSGBM_create属于contrib模块。或者,用户安装的OpenCV版本较旧,该函数在旧版本中可能不存在或者模块路径不同。 接下来,我需要验证这些可能性。首先检查用户是否安装了正确的包。opencv-python主库不包含contrib模块,而opencv-contrib-python则包含。因此,用户可能需要安装后者。另外,版本问题也很重要,StereoSGBM_create可能在较新的版本中有变动,或者某些版本中该函数所在的模块路径被调整了。例如,在OpenCV 4.x中,立体匹配相关的类可能在cv2模块下,但可能需要正确的导入方式。 然后,考虑IDE的问题。有时IDE的类型提示文件(.pyi)可能不完整或过时,导致误报引用错误,但实际运行时正常。这种情况下,可以尝试更新IDE或OpenCV的版本,或者忽略类型检查错误。用户可能需要配置IDE的检查规则,或者使用类型注释来避免误报。 另外,用户可能导入了错误的模块。比如,需要确保使用正确的导入语句,例如从cv2中导入,或者需要访问子模块。但根据OpenCV的Python绑定,通常所有函数都在cv2模块下,不需要额外导入子模块。 解决方案可能包括: 1. 确认安装了opencv-contrib-python包,而不是仅opencv-python。 2. 升级OpenCV到最新版本,以确保StereoSGBM_create存在。 3. 检查代码中的导入语句是否正确。 4. 处理IDE的类型检查错误,比如添加类型忽略注释或更新类型存根文件。 5. 在代码中使用try-except块来捕获导入错误,并提示用户安装正确的包。 同时,需要参考用户提供的引用内容。比如,引用[4]提到StereoSGBM_create的参数和用法,说明该函数确实存在于某些版本的OpenCV中。用户可能未正确安装包含该模块的版本。此外,引用[2]提到安装过程中可能出现的下载失败问题,可能影响库的完整性,导致某些模块缺失。因此,重新安装或修复OpenCV安装可能也是解决方案之一。 可能的验证步骤包括让用户检查OpenCV版本,尝试导入函数,或者运行一个简单的测试脚本。如果用户确认安装正确,但IDE仍然报错,可能需要处理IDE的配置问题。例如,在PyCharm中,可以标记目录为排除,或调整类型检查的设置。 最后,生成的相关问题需要考虑用户可能遇到的类似问题,例如其他函数找不到引用、安装问题,或者立体匹配的其他方法。这样能够帮助用户扩展解决其他潜在的问题。</think>### 解决OpenCV中'StereoSGBM_create'引用缺失问题的方法 #### 问题分析 `StereoSGBM_create` 是OpenCV中用于立体匹配的**半全局块匹配算法**的构造函数,属于`cv2`模块的扩展功能。若在`__init__.pyi`文件中找不到该引用,可能原因如下: 1. **OpenCV版本不匹配**:未安装包含`contrib`模块的版本(如仅安装`opencv-python`而非`opencv-contrib-python`)[^4]。 2. **IDE类型提示文件过时**:IDE的静态类型检查器(如PyCharm、VS Code)未正确识别OpenCV的类型存根(`.pyi`文件)。 3. **安装损坏**:安装过程中依赖文件下载失败(如`ippicv`或`ffmpeg`组件缺失)[^2]。 --- #### 解决方案步骤 1. **确认安装正确的OpenCV包** - **卸载旧版本**: ```bash pip uninstall opencv-python opencv-contrib-python ``` - **安装包含contrib模块的版本**: ```bash pip install opencv-contrib-python==4.5.5.64 # 指定兼容版本 ``` 或直接安装最新版: ```bash pip install opencv-contrib-python ``` 2. **验证函数是否存在** - 在Python终端中运行: ```python import cv2 print(cv2.StereoSGBM_create) # 应输出类似 <built-in function...> ``` - 若报错`AttributeError`,则安装包不完整,需重新安装。 3. **处理IDE类型检查错误** - **PyCharm**:右键点击报错行 → `Disable Inspection` → 临时忽略。 - **通用方法**:在代码中添加类型忽略注释: ```python sgbm = cv2.StereoSGBM_create() # type: ignore ``` 4. **修复安装依赖问题** - 若安装时出现网络错误(如引用[2]中的`ippicv_2019_win_intel64`下载失败): - 手动下载缺失文件并放置到`opencv`缓存目录(如`C:\Users\<User>\AppData\Local\opencv`)。 - 重新运行`pip install`。 --- #### 代码示例 ```python import cv2 # 创建StereoSGBM对象并设置参数 sgbm = cv2.StereoSGBM_create( minDisparity=0, numDisparities=64, blockSize=5, P1=8 * 3 * 5**2, P2=32 * 3 * 5**2, disp12MaxDiff=1, uniquenessRatio=10, speckleWindowSize=100, speckleRange=32 ) # 示例:计算视差图 left_img = cv2.imread("left.png", cv2.IMREAD_GRAYSCALE) right_img = cv2.imread("right.png", cv2.IMREAD_GRAYSCALE) disparity = sgbm.compute(left_img, right_img) ``` --- #### 引用验证 - `cv2.StereoSGBM_create` 的参数含义与用法可参考OpenCV官方文档(引用[1][^1]和引用[4])。 - 若需校准摄像头参数,可结合`stereoCalibrate`方法(引用[3][^3])。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值