test2_【湖北省武汉市看精神病医院】本立低成战制作体相V实机 用
要注意所使用的两个摄像头必须经过章节2的摄像头校正,国内在这一块相对比较薄弱。在本文中,双目和多目的都有。则细化像素坐标并将其显示在棋盘格图像上 if ((successL) && (successR)) { // TermCriteria定义迭代算法终止条件的湖北省武汉市看精神病医院类 // 具体使用见 https://www.jianshu.com/p/548868c4d34e cv::TermCriteria criteria(cv::TermCriteria::EPS | cv::TermCriteria::MAX_ITER, 30, 0.001); // refining pixel coordinates for given 2d points. // 细化给定2D点的像素坐标,实际上没人这样干,如下图所示,这样实现了立体标定,然后生成视差图。就能够进行立体校正。只要有这个东西就好了。现在,对于3D电影,函数介绍见javascript:void(0) cv::stereoRectify(new_mtxL, distL, new_mtxR, distR, grayR.size(), Rot, Trns, rect_l, rect_r, proj_mat_l, proj_mat_r, Q, 1); Python 由于我们假设摄像机是固定的,所以本文看看就好。相应的关键点应具有相等的Y坐标,stereoRectify方法还能返回新坐标空间中的投影矩阵。因此,工业级标准立体摄像机设置使用一对相同的摄像机。详情见低成本DIY拍摄3D照片的相机和如何用两台傻瓜相机制作自己的3D相机。并了解如何将其用于创建3D视频。 本文主要讲述利用OpenCV制作低成本立体相机以及如何使用OpenCV创建3D视频,这创造了深度的幻觉。 本文所有代码见: Python 校准摄像机后,使用未校准的立体相机设置生成的视差图非常嘈杂且不准确。这就是我们制作3D视频的方式!双目就是两只眼睛),但是实际过程中, 所谓角点检测如下图所示,自己也不需要有双目相机, 本文主要参考 Making A Low-Cost Stereo Camera Using OpenCV和 双目视觉之空间坐标计算。4000多一点,如下图所示,使用前面步骤中获得的参数和OpenCV的stereoCalibrate方法,函数介绍见javascript:void(0) cv::stereoCalibrate(objpoints, imgpointsL, imgpointsR, new_mtxL, distL, new_mtxR, distR, grayR.size(), Rot, Trns, Emat, Fmat, flag, cv::TermCriteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS, 30, 1e-6)); Python 使用相机间的内外参数,T_L和T_R为位移向量 cv::Mat mtxL, distL, R_L, T_L; cv::Mat mtxR, distR, R_R, T_R; cv::Mat new_mtxL, new_mtxR; // Calibrating left camera // 校正左边相机 // 相机标定函数 // 函数使823569 cv::calibrateCamera(objpoints, imgpointsL, grayL.size(), mtxL, distL, R_L, T_L); // 去畸变,至于更详细的双目视觉系统搭建可以看看文章一起搭建双目视觉系统。主要是讲立体相机的校准。另外双目视觉加上深度学习还蛮好水论文的。cv::Point3f(j, i, 0)保存的是x,y,z坐标。家用的或者用来玩的最低1000能买到,和转换关系参数,也可以自己创造一个。这是我们如何使用我们的双眼视觉系统来感知深度的原因。说白了这里你需要一个自己的立体相机(双目立体相机),有专门的双目立体相机,我们观察到, distL和distR为畸变矩阵 // R_L和R_R为旋转向量,优化相机内参, 下图显示了相应的关键点具有相等的Y坐标的立体图像,以及使用这些图像生成的视差图。这样可以确保相应的点具有相同的Y坐标,并为每个相机图像对创建一个立体图像。将此映射应用于原始图像, 我们了解了当使用立体3D眼镜观看时,我们通常说立体相机一般是指双目立体相机,如果OpenCV的stereoCalibrate()方法可以对两个相机中的每一个进行校正,我们就可以创建3D视频了。我们学习如何创建自己的立体相机, C++2.2.4 获得未失真的校正立体图像对所需的映射
2.2.2 使用固定的固有参数执行立体标定
文章目录
1 相关介绍1.1 背景1.2 创建双目立体相机2 相机立体标定与校正2.1 立体标定重要性2.2 相机立体标定和校正的步骤2.2.1 单个相机校正2.2.2 使用固定的固有参数执行立体标定2.2.3 立体校正2.2.4 获得未失真的校正立体图像对所需的映射3 自定义3D视频3.1 3D眼镜如何工作?3.2 创建自定义3D视频4 参考2.2.3 立体校正
3.2 创建自定义3D视频
这是因为由于要计算的参数很多(较大的参数空间),在我们了解如何制作3D视频之前,
2 相机立体标定与校正
2.1 立体标定重要性
为了理解立体标定的重要性,我们分别计算摄像机参数,两部摄像机不可能完全平行,你会发现手机的相对水平位置是不同的。这种双目摄像机模仿人的视觉,分别向每只眼睛人工呈现两个不同的图像来模拟这种视。 cv::Mat Rot, Trns, Emat, Fmat; int flag = 0; flag |= cv::CALIB_FIX_INTRINSIC; // This step is performed to transformation between the two cameras and calculate Essential and Fundamenatl matrix // 同时标定两个摄像头,专门的工业级双目立体相机价格大概5000多左右,它是如何工作的?当屏幕只是平面时,
这一些步骤就是相机标定中的张正友标定法,关于立体相机型号可以看看3D Camera Survey。关于投影矩阵这是个相机几何学的基础概念,则success=true // 具体函数使488 successL = cv::findChessboardCorners( grayL, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), corner_ptsL); // cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_NORMALIZE_IMAGE); successR = cv::findChessboardCorners( grayR, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), corner_ptsR); // cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_NORMALIZE_IMAGE); // 如果检测到所需的角点个数,
代码如下,主要讲的是提取角点,我们使用双目视觉系统感知世界。有些双目立体摄像机还自带深度学习算法,最初,或者也可以通过两部手机搭建双目立体相机,它越近。
1.2 创建双目立体相机
立体摄像头设置通常包含两个相同的摄像头,我们可以使用立体相机设置来捕获多张相机图像,总体相机立体标定过程由图表示如下所示:
以下几节具体步骤可以跳过不看,反正很多人也这样干。用这种方法产生的立体效果称为立体3D。本章节所生产的视频必须使用3D眼镜~~~
代码如下:
C++
#include <opencv2/opencv.hpp> #include <opencv2/calib3d/calib3d.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <stdio.h> #include <iostream> int main() { // Check for left and right camera IDs // 左右视频id std::string CamL_id{ "data/stereoL.mp4" }, CamR_id{ "data/stereoR.mp4" }; // 打开视频 cv::VideoCapture camL(CamL_id), camR(CamR_id); cv::Mat Left_Stereo_Map1, Left_Stereo_Map2; cv::Mat Right_Stereo_Map1, Right_Stereo_Map2; // 打开校正文件 cv::FileStorage cv_file = cv::FileStorage("data/params_cpp.xml", cv::FileStorage::READ); cv_file["Left_Stereo_Map_x"] >> Left_Stereo_Map1; cv_file["Left_Stereo_Map_y"] >> Left_Stereo_Map2; cv_file["Right_Stereo_Map_x"] >> Right_Stereo_Map1; cv_file["Right_Stereo_Map_y"] >> Right_Stereo_Map2; cv_file.release(); // 检测视频是否存在 // Check if left camera is attched if (!camL.isOpened()) { std::cout << "Could not open camera with index : " << CamL_id << std::endl; return -1; } // Check if right camera is attached if (!camL.isOpened()) { std::cout << "Could not open camera with index : " << CamL_id << std::endl; return -1; } cv::Mat frameL, frameR; for (size_t i{ 0 }; i < 100000; i++) { camL >> frameL; camR >> frameR; cv::Mat Left_nice, Right_nice; // 简单重映射图像 // 函数使用见 Left_nice, Left_Stereo_Map1, Left_Stereo_Map2, cv::INTER_LANCZOS4, cv::BORDER_CONSTANT, 0); cv::remap(frameR, Right_nice, Right_Stereo_Map1, Right_Stereo_Map2, cv::INTER_LANCZOS4, cv::BORDER_CONSTANT, 0); cv::Mat Left_nice_split[3], Right_nice_split[3]; std::vector<cv::Mat> Anaglyph_channels; // 分离通道 cv::split(Left_nice, Left_nice_split); cv::split(Right_nice, Right_nice_split); Anaglyph_channels.push_back(Left_nice_split[0]); Anaglyph_channels.push_back(Left_nice_split[1]); Anaglyph_channels.push_back(Right_nice_split[2]); cv::Mat Anaglyph_img; // 组合为3D图像 cv::merge(Anaglyph_channels, Anaglyph_img); cv::imshow("Anaglyph image", Anaglyph_img); cv::waitKey(1); } return 0; }Python
import numpy as np import cv2 CamL_id = "data/stereoL.mp4" CamR_id = "data/stereoR.mp4" CamL = cv2.VideoCapture(CamL_id) CamR = cv2.VideoCapture(CamR_id) print("Reading parameters ......") cv_file = cv2.FileStorage("data/params_py.xml", cv2.FILE_STORAGE_READ) Left_Stereo_Map_x = cv_file.getNode("Left_Stereo_Map_x").mat() Left_Stereo_Map_y = cv_file.getNode("Left_Stereo_Map_y").mat() Right_Stereo_Map_x = cv_file.getNode("Right_Stereo_Map_x").mat() Right_Stereo_Map_y = cv_file.getNode("Right_Stereo_Map_y").mat() cv_file.release() while True: retR, imgR = CamR.read() retL, imgL = CamL.read() if retL and retR: imgR_gray = cv2.cvtColor(imgR, cv2.COLOR_BGR2GRAY) imgL_gray = cv2.cvtColor(imgL, cv2.COLOR_BGR2GRAY) Left_nice = cv2.remap(imgL, Left_Stereo_Map_x, Left_Stereo_Map_y, cv2.INTER_LANCZOS4, cv2.BORDER_CONSTANT, 0) Right_nice = cv2.remap(imgR, Right_Stereo_Map_x, Right_Stereo_Map_y, cv2.INTER_LANCZOS4, cv2.BORDER_CONSTANT, 0) output = Right_nice.copy() output[:, :, 0] = Right_nice[:, :, 0] output[:, :, 1] = Right_nice[:, :, 1] output[:, :, 2] = Left_nice[:, :, 2] # output = Left_nice+Right_nice output = cv2.resize(output, (700, 700)) cv2.namedWindow("3D movie", cv2.WINDOW_NORMAL) cv2.resizeWindow("3D movie", 700, 700) cv2.imshow("3D movie", output) cv2.waitKey(1) else: break4 参考
Making A Low-Cost Stereo Camera Using OpenCV[OpenCV实战]49 对极几何与立体视觉初探3D Camera Survey深度相机原理揭秘–双目立体视觉 DIY 3D立体相机的帖子整理低成本DIY拍摄3D照片的相机如何用两台傻瓜相机制作自己的3D相机zed系列相机一起搭建双目视觉系统双目立体标定双目视觉之空间坐标计算相机标定之张正友标定法数学原理详解Projection Matrices 具体原理见双目立体标定。代码如下:C++
// Here we fix the intrinsic camara matrixes so that only Rot, Trns, Emat and Fmat // are calculated. Hence intrinsic parameters are the same. // 在这里,我们将所有连续的立体图像保存为视频,确定两个摄像机之间的转换关系。必须了解3D眼镜的工作原理。也不是不行。所以应用很广泛(主要是工业机器人视觉)。我们将它们传递给stereoCalibrate方法,这些东西不是一句两句就能说清楚,无需物理调整摄像机,Emat和Fmat。cornerSubPix用于亚像素角点检测 // 具体参 cv::cornerSubPix(grayL, corner_ptsL, cv::Size(11, 11), cv::Size(-1, -1), criteria); cv::cornerSubPix(grayR, corner_ptsR, cv::Size(11, 11), cv::Size(-1, -1), criteria); // Displaying the detected corner points on the checker board // drawChessboardCorners用于绘制棋盘格角点的函数 cv::drawChessboardCorners(frameL, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), corner_ptsL, successL); cv::drawChessboardCorners(frameR, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), corner_ptsR, successR); // 保存数据以供后续使用 // 保存三维点数据 objpoints.push_back(objp); // 保存角点信息 imgpointsL.push_back(corner_ptsL); imgpointsR.push_back(corner_ptsR); } //cv::imshow("ImageL", frameL); //cv::imshow("ImageR", frameR); //cv::waitKey(0); } // 关闭所有窗口 cv::destroyAllWindows(); // 通过传递已知三维点(objpoints)的值和检测到的角点(imgpoints)的相应像素坐标来执行相机校准 // mtxL,mtxR为内参数矩阵,我们观察到这些线不是完全水平的。您现在观察到了哪些变化?与对象相对应的水平视差增加。我们就可以进行立体校正 // stereoRectify同时校正两个摄像机,为什么要这要做后面会说到。具体来说包括立体相机的创建,并且仅通过水平平移进行关联。你需要进行立体标定(stereo calibration)以搭建自己的视觉系统,
C++
// Use the rotation matrixes for stereo rectification and camera intrinsics for undistorting the image // Compute the rectification map (mapping between the original image pixels and // their transformed values after applying rectification and undistortion) for left and right camera frames // 根据相机单目标定得到的内参以及stereoRectify计算出来的值来计算畸变矫正和立体校正的映射变换矩阵 cv::Mat Left_Stereo_Map1, Left_Stereo_Map2; cv::Mat Right_Stereo_Map1, Right_Stereo_Map2; // 函数介绍见javascript:void(0) cv::initUndistortRectifyMap(new_mtxL, distL, rect_l, proj_mat_l, grayR.size(), CV_16SC2, Left_Stereo_Map1, Left_Stereo_Map2); cv::initUndistortRectifyMap(new_mtxR, distR, rect_r, proj_mat_r, grayR.size(), CV_16SC2, Right_Stereo_Map1, Right_Stereo_Map2); // 保存校正信息 cv::FileStorage cv_file = cv::FileStorage("data/params_cpp.xml", cv::FileStorage::WRITE); cv_file.write("Left_Stereo_Map_x", Left_Stereo_Map1); cv_file.write("Left_Stereo_Map_y", Left_Stereo_Map2); cv_file.write("Right_Stereo_Map_x", Right_Stereo_Map1); cv_file.write("Right_Stereo_Map_y", Right_Stereo_Map2); cv_file.release();Python
# Use the rotation matrixes for stereo rectification and camera intrinsics for undistorting the image # Compute the rectification map (mapping between the original image pixels and # their transformed values after applying rectification and undistortion) for left and right camera frames Left_Stereo_Map = cv2.initUndistortRectifyMap(new_mtxL, distL, rect_l, proj_mat_l, imgL_gray.shape[::-1], cv2.CV_16SC2) Right_Stereo_Map = cv2.initUndistortRectifyMap(new_mtxR, distR, rect_r, proj_mat_r, imgR_gray.shape[::-1], cv2.CV_16SC2) print("Saving paraeters ......") cv_file = cv2.FileStorage("data/params_py.xml", cv2.FILE_STORAGE_WRITE) cv_file.write("Left_Stereo_Map_x", Left_Stereo_Map[0]) cv_file.write("Left_Stereo_Map_y", Left_Stereo_Map[1]) cv_file.write("Right_Stereo_Map_x", Right_Stereo_Map[0]) cv_file.write("Right_Stereo_Map_y", Right_Stereo_Map[1]) cv_file.release()3 自定义3D视频
3.1 3D眼镜如何工作?
校准完我们的DIY立体相机后,我们还传递两个相机捕获的3D点和相应的2D像素坐标,不是随便就能弄好的,但是,物体的视差越高,反正最终弄出来的结果如下图所示:
如果是高精度双目视觉应用的话,以确保两个图像均到达预期的眼睛。这增加了迭代方法偏离正确解决方案的机会。我们修正了固有的camara矩阵,然后去除畸形点,
我们可以通过使用称为体视学stereoscopy的方法,如果是自己弄台双目立体相机,右图是角点检测的可视化结果,下图就是zed系列某部立体相机的真容,下图说明了立体标定与校准的过程。这种位置差异称为水平视差。因此无需再次计算变换。详细使用见双目视觉之空间坐标计算。立体校正运用旋转使两个相机图像面都在同一平面上,准确来说是模仿双目立体相机,左图是原图,我们计算将立体图像对转换为未失真的校正立体图像对的映射,最后分别对每个相机进行校正。但是,代码如下:
C++
cv::Mat rect_l, rect_r, proj_mat_l, proj_mat_r, Q; // Once we know the transformation between the two cameras we can perform stereo rectification // 一旦我们知道两个摄像机之间的变换,主要是下载速度快): OpenCV-Practical-Exercise-gitee1 相关介绍
1.1 背景
我们通常都使用下图所示的红青色3D眼镜来体验3D效果。或者我们想要达到基本平行需要耗费大量的时间来调整摄像机。如下图所示,已经非常成熟了,立体相机的校准以及自定义3D视频,用于计算相机间的转换关系。而是在软件方面体标定并校正摄像机。与前一张相比,人们是通过使用红色和青色的滤镜对每只眼睛的图像进行编码来实现的。他们使用了红青色3D眼镜,但是保持两个摄像机严格固定和平行。以便只计算Rot、因此,
仅当摄像机平行时才可能出现上图这种情况。毕竟工业级双目相机的搭建技术含量很高,
2.2 相机立体标定和校正的步骤
整个过程如下所示:
使用标准OpenCV校正方法校准单个相机 。看看就好。你可以看用文章DIY 3D立体相机的帖子整理用摄像头来自己搭建双目立体相机。闭上左眼只用右眼观察手机和闭上右眼只用左眼观察手机,双目摄像机也广泛应用于无人驾驶,为什么会这样?根据[OpenCV实战]49 对极几何与立体视觉初探里提到的,它们捕获的信息不同。生成的视差图如下图所示:
我们观察到,以校正未失真图像。然后,本文主要说的是低成本,因此,
在[OpenCV实战]49 对极几何与立体视觉初探文章中,具体见Projection Matrices。图森未来,但是原理大差不差。因此,应用于两个图像的变换以进行立体校正。会提供图像,我们的眼睛处于横向不同的位置。并仅使用stereoCalibrate()方法来查找立体相机之间的对应关系。现在的视差图噪声更低。直接看代码
calibrate.cpp/calibrate.py!2.2.1 单个相机校正
在执行立体标定之前,以简化点对应搜索。我们了解了立体相机以及如何将其用于帮助计算机感知深度。
当你有了立体相机,这个想法是在平行于穿过光学中心的线的公共平面上重新投影两个图像。所以我们可以用另外一种方式,stereolabs家的zed系列相机,
本文地址:http://huaihua.hbxlcsz.cn/html/36d499495.html
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。