OpenCV下的无标定校正(stereoRectifyUncalibrated)

OpenCV下的无标定校正(stereoRectifyUncalibrated)

文章目录

  • 1. 杂话
  • 2. 无标定校正
    • 2.1 先看代码
    • 2.2 一点解释
    • 2.3 findFundamentalMat参数
    • 2.4 stereoRectifyUncalibrated参数
  • 3. 矫正结果

1. 杂话

 咱们在之前的帖子里面讲了一些比较常规的标定和校正OpenCV下的单目标定,双目标定与立体校正(calibrateCamera, stereoCalibrate and stereoRectify),但是,如果说两个相机之间的转角比较大,那么可能并不适合用双目标定+立体校正的步骤来做,参考这个贴子立体校正失效的情况,所以为了解决这个问题,今天咱们就来说说如何使用非标定的校正函数:

 对了,我使用的数据和完整的代码在这里:Repo : Calibrate-and-Rectify

2. 无标定校正

2.1 先看代码

import cv2
import numpy as np
import glob
import matplotlib.pyplot as plt
from PIL import Imagec1_images_names = sorted(glob.glob('demo/left*.jpg'))
c2_images_names = sorted(glob.glob('demo/right*.jpg'))c1_images = []
c2_images = []
for im1, im2 in zip(c1_images_names, c2_images_names):_im = cv2.imread(im1, 1)c1_images.append(_im)_im = cv2.imread(im2, 1)c2_images.append(_im)def find_corners(image_names):images = []for imname in image_names:im = cv2.imread(imname, 1)images.append(im)criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)rows = 6 #number of checkerboard rows.columns = 9 #number of checkerboard columns.#coordinates of squares in the checkerboard world spaceobjp = np.zeros((rows*columns,3), np.float32)objp[:,:2] = np.mgrid[0:rows,0:columns].T.reshape(-1,2)#frame dimensions. Frames should be the same size.width = images[0].shape[1]height = images[0].shape[0]#Pixel coordinates of checkerboardsimgpoints = [] # 2d points in image plane.for frame in images:gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)gray = cv2.rotate(gray, cv2.ROTATE_90_CLOCKWISE)#find the checkerboardret, corners = cv2.findChessboardCorners(gray, (rows, columns), None)if ret == True:#Convolution size used to improve corner detection. Don't make this too large.conv_size = (11, 11)#opencv can attempt to improve the checkerboard coordinatescorners = cv2.cornerSubPix(gray, corners, conv_size, (-1, -1), criteria)imgpoints.append(corners)return imgpointsimgpoints1 = find_corners(c1_images_names)
imgpoints2 = find_corners(c2_images_names)# 将角点坐标转换为float32格式
points1all = np.array([pt.ravel() for pts in imgpoints1 for pt in pts], dtype=np.float32)
points2all = np.array([pt.ravel() for pts in imgpoints2 for pt in pts], dtype=np.float32)# 计算基础矩阵
F, mask = cv2.findFundamentalMat(points1all, points2all, cv2.FM_RANSAC)# 图像大小
img_size = (640, 480)img1 = cv2.imread('demo/left03.jpg', 1)
img2 = cv2.imread('demo/right03.jpg', 1)img1 = cv2.rotate(img1, cv2.ROTATE_90_CLOCKWISE)
img2 = cv2.rotate(img2, cv2.ROTATE_90_CLOCKWISE)gray_left = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray_right = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)# 找到棋盘格角点
ret_left, corners_left = cv2.findChessboardCorners(gray_left, (6, 9), None)
ret_right, corners_right = cv2.findChessboardCorners(gray_right, (6, 9), None)criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)print(ret_left, ret_right)if ret_left and ret_right:# 提高角点的精度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)# 将角点坐标转换为float32格式
points1 = np.array([pt[0] for pt in corners_left], dtype=np.float32).reshape(-1, 2)
points2 = np.array([pt[0] for pt in corners_right], dtype=np.float32).reshape(-1, 2)# 进行立体校正
retval, H1, H2 = cv2.stereoRectifyUncalibrated(points1, points2, F, img_size)# 裁剪图像去除黑边
def crop_image(image):gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)_, thresh = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)x, y, w, h = cv2.boundingRect(contours[0])cropped_image = image[y:y+h, x:x+w]return cropped_imageif retval:# 计算校正映射img1_rectified = cv2.warpPerspective(img1, H1, img_size)img2_rectified = cv2.warpPerspective(img2, H2, img_size)# 显示校正后的图像cv2.imwrite('Rectified Image 1.png', img1_rectified)cv2.imwrite('Rectified Image 2.png', img2_rectified)
else:print("立体校正失败")plt.figure(figsize=(20, 20))for i in range(0,1):  # 以第一对图片为例im_L=Image.fromarray(img1_rectified) # numpy 转 image类im_R=Image.fromarray(img2_rectified) # numpy 转 image 类width = im_L.size[0]*2height = im_L.size[1]img_compare = Image.new('RGBA',(width, height))img_compare.paste(im_L,box=(0,0))img_compare.paste(im_R,box=(640,0))#在已经极线对齐的图片上均匀画线for i in range(1,20):len=480/20plt.axhline(y=i*len, color='r', linestyle='-')plt.imshow(img_compare)plt.savefig('epipolar_lines_ro.png', bbox_inches='tight', pad_inches=0)plt.show()

2.2 一点解释

 其实也没啥好解释的吧,一些基础的参数都在上面说的另外一篇帖子里面写好了。主要就是说一下思路,因为是标定图片,所以还是用角点做关键点,之后通过匹配的关键点和findFundamentalMat去计算基础矩阵,描述两个图片的映射关系。然后针对示例图片,应用这个映射,也就是stereoRectifyUncalibrated函数。

2.3 findFundamentalMat参数

 findFundamentalMat 是 OpenCV 中用于计算基础矩阵的函数。基础矩阵描述了两个图像之间的点对应关系,是立体视觉计算中的一个重要概念。以下是该函数的详细解释:

cv2.findFundamentalMat(points1, points2[, method[, ransacReprojThreshold[, confidence[, maxIters]]]]) -> fundamentalMatrix, mask输入参数
points1:
描述:在第一幅图像中检测到的特征点列表或数组。应该是 Nx2 的二维点坐标列表,其中 N 是特征点的数量。points2:
描述:在第二幅图像中检测到的特征点列表或数组。应该与 points1 中的点一一对应,且格式相同。method (可选):
描述:用于估算基础矩阵的方法。可以是以下之一:
cv2.FM_7POINT: 七点算法。要求点数量为 7。
cv2.FM_8POINT: 八点算法。要求点数量大于或等于 8。
cv2.FM_RANSAC: 使用 RANSAC 方法。推荐用于处理带有噪声的点。
cv2.FM_LMEDS: 使用最小中值平方算法。也用于处理带有噪声的点。ransacReprojThreshold (可选):
描述:RANSAC 算法中的最大重投影误差阈值,仅在使用 RANSAC 方法时有效。默认值为 3。confidence (可选):
描述:RANSAC 算法中的置信度,仅在使用 RANSAC 方法时有效。默认值为 0.99。maxIters (可选):
描述:RANSAC 算法的最大迭代次数,仅在使用 RANSAC 方法时有效。默认值为 1000。输出参数
fundamentalMatrix:
描述:计算得到的基础矩阵,大小为 3x3。mask:
描述:输出参数,用于标识内点(inliers)。大小为 Nx1 的二值数组,其中 N 是输入特征点的数量。值为 1 的元素表示对应的特征点是内点,值为 0 的元素表示对应的特征点是外点(outliers)。

2.4 stereoRectifyUncalibrated参数

cv2.stereoRectifyUncalibrated(points1, points2, F, imgSize[, H1[, H2[, threshold]]]) -> retval, H1, H2
输入参数points1:
描述:在左图中检测到的特征点列表或数组。应该是 Nx2 的二维点坐标列表,其中 N 是特征点的数量。points2:
描述:在右图中检测到的特征点列表或数组。应该与 points1 中的点一一对应,且格式相同。F:
描述:基础矩阵(3x3),它是在立体图像对之间通过特征点匹配估算得到的。imgSize:
描述:图像的尺寸,格式为 (width, height),即图像的宽度和高度。H1 (可选):
描述:输出参数,用于存储左图的 3x3 变换矩阵。如果提供了此参数,函数会将结果写入其中。H2 (可选):
描述:输出参数,用于存储右图的 3x3 变换矩阵。如果提供了此参数,函数会将结果写入其中。threshold (可选):
描述:用于 RANSAC 算法的阈值。RANSAC 算法用于估算变换矩阵时的容错范围。如果不提供,则使用默认值。输出参数
retval:
描述:函数执行成功与否的标志。返回 True 表示成功,返回 False 表示失败。H1:
描述:左图的 3x3 变换矩阵。只有在调用时提供了相应的参数,且函数执行成功时才会返回。H2:
描述:右图的 3x3 变换矩阵。只有在调用时提供了相应的参数,且函数执行成功时才会返回。

3. 矫正结果

在这里插入图片描述
 OK,基本符合预期哦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/415528.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决bug: RuntimeError: Address already in use,一个linux下pytorch多卡训练tcp端口占用的bug

时间:2024.9.3 1)bug: self._store TCPStore( # type: ignore[call-arg] RuntimeError: Address already in use2)原因分析 linux下pytorch多卡训练深度学习模型,训练中途暂停训练,但仍有进程占用某个端…

OcrLiteNcnn:Windows环境打包及Java调用

目录结构 前言cmake安装源码下载说明Windows源码编译执行“cmake -DCMAKE_BUILD_TYPE=Release ..”执行“cmake --build . --config Release -- -m:6”编译完成识别图片命令行调用Java调用前言 Java实现OCR识别图片中的文字,小编先前整理过一篇在Linux环境中基于“ChineseOcr…

iPhone升级iOS 18后遭遇“白苹果”?别怕,这几招教你轻松应对!

在这个科技日新月异的时代,苹果iOS系统的每一次更新都牵动着亿万果粉的心。iOS 18作为苹果最新的操作系统,不仅带来了全新的功能体验,也难免会遇到一些用户反馈的“小插曲”,比如升级后出现的“白苹果”现象。面对这一状况&#x…

安卓13拦截home功能 监听home键 禁用home键

总纲 android13 rom 开发总纲说明 目录 1.前言2.问题分析3.代码分析4.代码修改5.编译6.彩蛋1.前言 经常遇

KAN学习Day1——模型框架解析及HelloKAN

说明 最近了解到了一个新东西——KAN,我的毕设导师给推荐的船新框架。我看过很多剖析其原理的文章,发现大家对其持有的观点都各不相同,有的说可以颠覆传统MLP,有的说可以和Transformer同等地位,但是也有人说它训练速度…

缓存解决方案。Redis 和 Amazon ElastiCache 比较

欢迎来到雲闪世界。Redis 和 Amazon ElastiCache 等缓存解决方案是通过将频繁访问的数据存储在内存中来提高应用程序性能的热门选择。让我们从实施简单性、性能、成本和维护方面对它们进行比较。 实施简单 设置 Redis 需要在基础设施或云实例上安装和配置 Redis 服务器。它可…

通过cmd命令的方式转码MP4为webp动图。附带命令解释。

zihao 通过cmd命令的方式转码MP4为webp动图: 均衡大小和z效果的配置(直接拷贝后需要改下路径): ffmpeg -i E:\steam\222.mp4 -vcodec libwebp -filter:v fpsfps24 -lossless 0 -compression_level 5 -q:v 35 -loop 1 -preset def…

C++系列-STL容器之list

STL容器之list list容器的基本结构list容器的特点list容器的优点list容器的缺点 list容器的构造函数list容器的常用接口list赋值操作list大小及空否list访问list迭代器相关list增删查改push and popinsert其它 寄扬州韩绰判官 杜牧〔唐代〕 青山隐隐水迢迢,秋尽江南…

覃嘉仪,艺人经纪人、经纪人、影视经纪人。2002.7.9出生于四川省遂宁市射洪县

覃嘉仪,艺人经纪人、经纪人、影视经纪人。2002.7.9出生于四川省遂宁市射洪县 2020年开始从事宣传工作,2023成为“WP经纪工作室”艺人经纪,现担任孙亦欣、魏逸熙等艺人的经纪人。 2024年涉足于影视行业,并加入嘉林娱乐。2024年在由…

慢慢写材料

有一次,我要公司帮我提供一个材料。当时,我比较着急,于是非常简要、快速的写了一封邮件,发给公司负责人。 结果,两三天后,也没有收到公司的回复。 于是,我又耐心的写了一封新的邮件。说明&#…

华为云CCE集群创建loadBalancer

目录 一、目的 二、创建应用 三、创建服务 loadBalancer 四、域名解析 五、验证 一、目的 1、为CCE容器应用创建loadBalancer服务,并且绑定https协议的域名 2、公网访问域名: https://test.******.com 3、CCE创建用于公网域名访问的loadBalancer,不…

网站安全问题整改

网站安全、政务云、第三方安全检测机构等评测出来的网站web安全问题整改,如果你也正需要做这方面,请联系我吧

快速排序(动图详解)(C语言数据结构)

快速排序: 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为: 任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值&#xff0c…

个人怎么注册商标需要什么条件!

经常会遇到有人问普推知产老杨,个人怎么注册商标需要什么条件,首先会要有个体户执照,没有得先申请一个体工商户的执照才可以申请注册商标,再加身份证正反签字就可以,申请商标类别的类别与个体工商户经营范围无关&#…

APP 数据抓取 - Charles 抓包工具的使用(Charles 端口配置、CA 证书配置、Charles Android 模拟器配置)

前言说明 此文章是我在学习 Charles APP 抓包时编写,内容都是亲测有效,文章内容也有参考其他人,参考文章如下: Android 手机使用 charles 抓 https 请求(保姆级教程)网易 mumu 模拟器安装下载 charles 的…

redroid搭建云手机学习笔记(一)

参考链接 通过Redroid搭建自己的云手机 docker安装 docker官网目前打不开了,通过官网安装的方式无法实现,这里需要借助镜像网站来实现docker的安装 参考链接:https://developer.aliyun.com/mirror/docker-ce # step 1: 安装必要的一些系统…

ADB 获取屏幕坐标,并模拟滑动和点击屏幕

本文声明:本文是参考https://blog.csdn.net/beyond702/article/details/69258932编制。同时,补充了在windows系统模式下,详细的获取屏幕坐标的步骤。 1.判断设备与windows电脑USB连接是否正常 在CMD窗口输入命令:ADB devices,按ENTER键,输出如下结果,则表示连接正常。 …

【非常简单】 猿人学web第一届 第17题 天杀的 Http2.0

题目标题已经很明显了,Http2.0 数据接口 对应的请求协议也为 http2.0 python 代码 import httpx # pip install httpxheaders {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.…

LangChain学习资料

本文提供了一个LangChain框架的综合资源库,包括低代码工具、服务、代理、模板等,还列举了知识管理和聊天机器人等开源项目,以及学习笔记、视频教程等学习资料,旨在帮助开发者更好地利用和学习LangChain。 摘要由CSDN通过智能技术…

【深海王国】小学生都能玩的单片机!番外2:Arduino控制其他元器件(2)

Hi٩(๑ ^ o ^ ๑)۶, 各位深海王国的同志们,早上下午晚上凌晨好呀~辛勤工作的你今天也辛苦啦 (o゜▽゜)o☆ 今天大都督为大家带来单片机的新番外系列——小学生都能玩的单片机!番外2:Arduino控制其他元器件,带你学习如何使用Ard…