双目测距工程Stereo-Vision-master学习笔记

硬件:
首先要要把两个摄像头固定到支架上,并且两个摄像头的间距应该在110mm,两个摄像头没有落差
在这里插入图片描述
相机的内参数包括焦距、主点坐标、像素尺寸等,这些参数决定了相机成像的几何变换关系。内参数是相机固有的属性,不会随着相机在空间中的位置和方向而改变。

相机的外参数包括相机的旋转矩阵和平移向量,用来描述相机在世界坐标系中的位置和方向。相机的外参数可以将相机坐标系中的点转换到世界坐标系中,或者将世界坐标系中的点转换到相机坐标系中。

步骤一:

首先要通过/Take_images_for_calibration_thread.py来保存正畸用的棋盘格图像;代码的逻辑是只要通过findChessboardCorners找到充足且满足预设个数的棋盘格脚点时保存双目的图像。
核心代码

retL, frameL= CamL.read()  
grayR= cv2.cvtColor(frameL,cv2.COLOR_BGR2GRAY)
retL, cornersL = cv2.findChessboardCorners(grayL,(9,6),None) 
cv2.cornerSubPix(grayL,cornersL,(11,11),(-1,-1),criteria)
cv2.drawChessboardCorners(grayR,(9,6),corners2R,retR)if(retL)& 0xFF == ord('q'):
cv2.imwrite('chessboard-L'+str_id_image+'.png',frameL)

如果存在角点且符合预设个数,会打印绘制完角点图后的图像,并且允许按键保存。
在这里插入图片描述
左摄像头:
在这里插入图片描述
右摄像头:
在这里插入图片描述

步骤二:消除畸变

常见的相机失真类型有径向失真(radial distortion)和切向失真(tangential distortion)。
径向失真包括:桶型和枕性,实际的相机使用弯曲的镜头来形成图像,并且光线通常在这些镜头的边缘弯曲得太多或太少。 这会产生扭曲图像边缘的效果,从而使线条或对象看起来比实际弯曲的程度或大或小。 这称为径向变形 ,这是最常见的变形类型。
在这里插入图片描述
在这里插入图片描述
另一类失真是切向失真 。 当相机镜头未完全平行于相机胶卷或传感器所在的成像平面对齐时,就会发生这种情况。 这会使图像看起来倾斜,从而使某些对象看起来比实际位置更远或更近。

在这里插入图片描述

步骤三 对极几何

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

但是在实际测距中,计算视差被转换成了,计算两个对应像素位置之间的不同(distance),没有解析解,只能算一个数值解。
在这里插入图片描述

参考:
https://www.cnblogs.com/clarenceliang/p/6704970.
htmlhttps://cloud.tencent.com/developer/article/2054308
在这里插入图片描述

在这里插入图片描述

代码

  1. 首先,程序会对摄像头进行畸变校正和立体标定,以获得相机的内参和外参。
  2. 程序会打开两个摄像头,并循环读取左右眼的图像。
  3. 对图像进行矫正,消除旋转和对齐带来的畸变。
  4. 将彩色图像转为灰度图像。
  5. 使用StereoSGBM算法计算出视差图。
  6. 使用WLS滤波器对视差图进行滤波,获得更加准确的深度图。
  7. 对深度图进行颜色映射,显示出深度信息。
  8. 通过鼠标双击深度图中的点,可以在控制台输出该点的实际距离。
  9. 按空格键退出程序。
#      ▄▀▄     ▄▀▄
#     ▄█░░▀▀▀▀▀░░█▄
# ▄▄  █░░░░░░░░░░░█  ▄▄
#█▄▄█ █░░▀░░┬░░▀░░█ █▄▄█###################################
##### Authors:                #####
##### Stephane Vujasinovic    #####
##### Frederic Uhrweiller     ##### 
#####                         #####
##### Creation: 2017          #####
####################################***********************
#**** Main Programm ****
#***********************# Package importation
import numpy as np
import cv2
from openpyxl import Workbook # Used for writing data into an Excel file
from sklearn.preprocessing import normalize
import time
# Filtering
kernel= np.ones((3,3),np.uint8)def coords_mouse_disp(event,x,y,flags,param):if event == cv2.EVENT_LBUTTONDBLCLK:#左键双击#print x,y,disp[y,x],filteredImg[y,x]average=0for u in range (-1,2):for v in range (-1,2):average += disp[y+u,x+v]average=average/9Distance= -593.97*average**(3) + 1506.8*average**(2) - 1373.1*average + 522.06Distance= np.around(Distance*0.01,decimals=2)print('Distance: '+ str(Distance)+' m')# This section has to be uncommented if you want to take mesurements and store them in the excelws.append([counterdist, average])print('Measure at '+str(counterdist)+' cm, the dispasrity is ' + str(average))if (counterdist <= 85):counterdist += 3elif(counterdist <= 120):counterdist += 5else:counterdist += 10print('Next distance to measure: '+str(counterdist)+'cm')
#将测量结果写入excel
# Mouseclick callback
wb=Workbook()
ws=wb.active  #*************************************************
#***** Parameters for Distortion Calibration *****
#*************************************************# Termination criteria
#设置了相机校准的参数,误差小于0.001或者迭代30次就停止
criteria =(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
criteria_stereo= (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)# Prepare object points棋盘格座标点初始化
objp = np.zeros((9*6,3), np.float32)
objp[:,:2] = np.mgrid[0:9,0:6].T.reshape(-1,2)# Arrays to store object points and image points from all images
objpoints= []   # 3d points in real world space
imgpointsR= []   # 2d points in image plane
imgpointsL= []# Start calibration from the camera
print('Starting calibration for the 2 cameras... ')
# Call all saved images
#重新检测棋盘格角点
print(time.localtime())
for i in range(0,60):   # Put the amount of pictures you have taken for the calibration inbetween range(0,?) wenn starting from the image number 0t= str(i)ChessImaR= cv2.imread('/home/nvidia/Desktop/gf-learning/Stereo-Vision-master/save_image/chessboard-R'+t+'.png',0)    # Right sideChessImaL= cv2.imread('/home/nvidia/Desktop/gf-learning/Stereo-Vision-master/save_image/chessboard-L'+t+'.png',0)    # Left sideretR, cornersR = cv2.findChessboardCorners(ChessImaR,(9,6),None)  # Define the number of chees corners we are looking forretL, cornersL = cv2.findChessboardCorners(ChessImaL,(9,6),None)  # Left sideif (True == retR) & (True == retL):objpoints.append(objp)cv2.cornerSubPix(ChessImaR,cornersR,(11,11),(-1,-1),criteria)cv2.cornerSubPix(ChessImaL,cornersL,(11,11),(-1,-1),criteria)imgpointsR.append(cornersR)imgpointsL.append(cornersL)#保存角点信息
print(time.localtime())# Determine the new values for different parameters
#   Right Side
#右相机标定,ret:标定结果的精度,mtx内参矩阵,dist畸变系数;外参数:rvecs旋转向量:描述相机坐标系相对于世界坐标系的旋转关系,tvecs平移向量:描述相机坐标系相对于世界坐标系的平移关系。
retR, mtxR, distR, rvecsR, tvecsR = cv2.calibrateCamera(objpoints,imgpointsR,ChessImaR.shape[::-1],None,None)
hR,wR= ChessImaR.shape[:2]
#畸变矫正,motx经过优化后相机内参,roi优化后有效区域的ROI坐标
OmtxR, roiR= cv2.getOptimalNewCameraMatrix(mtxR,distR,(wR,hR),1,(wR,hR))#   Left Side
retL, mtxL, distL, rvecsL, tvecsL = cv2.calibrateCamera(objpoints,imgpointsL,ChessImaL.shape[::-1],None,None)
hL,wL= ChessImaL.shape[:2]
OmtxL, roiL= cv2.getOptimalNewCameraMatrix(mtxL,distL,(wL,hL),1,(wL,hL))print('Cameras Ready to use')#********************************************
#***** Calibrate the Cameras for Stereo *****
#********************************************# StereoCalibrate function
flags = 0
flags |= cv2.CALIB_FIX_INTRINSIC#相机立体校准,stereoCalibrate计算立体校准所需要的参数,R两个相机间旋转矩阵,T平移矩阵,E本质矩阵,F基本矩阵
retS, MLS, dLS, MRS, dRS, R, T, E, F= cv2.stereoCalibrate(objpoints,#真实世界下坐标imgpointsL,#相机下投影角点左边imgpointsR,mtxL,#内参distL,#畸变系数mtxR,distR,ChessImaR.shape[::-1],criteria = criteria_stereo,flags = cv2.CALIB_FIX_INTRINSIC)# StereoRectify function
rectify_scale= 0 # if 0 image croped, if 1 image nor croped
#R用于校正图像的旋转矩阵、P用于校正图像的投影矩阵、Q重投影矩阵,可以用于计算深度信息
RL, RR, PL, PR, Q, roiL, roiR= cv2.stereoRectify(MLS, dLS, MRS, dRS,ChessImaR.shape[::-1], R, T,rectify_scale,(0,0))  # last paramater is alpha, if 0= croped, if 1= not croped
# initUndistortRectifyMap function
#初始化图像校正映射
Left_Stereo_Map= cv2.initUndistortRectifyMap(MLS, dLS, RL, PL,ChessImaR.shape[::-1], cv2.CV_16SC2)   # cv2.CV_16SC2 this format enables us the programme to work faster
Right_Stereo_Map= cv2.initUndistortRectifyMap(MRS, dRS, RR, PR,ChessImaR.shape[::-1], cv2.CV_16SC2)
#*******************************************
#***** Parameters for the StereoVision *****
#*******************************************# Create StereoSGBM and prepare all parameters
window_size = 3
min_disp = 2
num_disp = 130-min_disp
stereo = cv2.StereoSGBM_create(minDisparity = min_disp,#最小视差值numDisparities = num_disp,#视差范围blockSize = window_size,uniquenessRatio = 10,speckleWindowSize = 100,speckleRange = 32,disp12MaxDiff = 5,P1 = 8*3*window_size**2,P2 = 32*3*window_size**2)# Used for the filtered image
#计算右视角图像中每个像素与左视角图像中对应像素的差异,视差计算
stereoR=cv2.ximgproc.createRightMatcher(stereo) # Create another stereo for right this time# WLS FILTER Parameters
lmbda = 80000# 平滑度惩罚系数
sigma = 1.8
visual_multiplier = 1.0#提高深度估计的精度
wls_filter = cv2.ximgproc.createDisparityWLSFilter(matcher_left=stereo)
wls_filter.setLambda(lmbda)
wls_filter.setSigmaColor(sigma)#*************************************
#***** Starting the StereoVision *****
#*************************************# Call the two cameras
CamR= cv2.VideoCapture(6)   # Wenn 6 then Right Cam and wenn 7 Left Cam
CamL= cv2.VideoCapture(7)CamR.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
CamR.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
CamR.set(cv2.CAP_PROP_FPS, 30)CamL.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
CamL.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
CamL.set(cv2.CAP_PROP_FPS, 30)while True:# Start Reading Camera imagesretR, frameR= CamR.read()retL, frameL= CamL.read()# Rectify the images on rotation and alignement重映射是一种将图像从一个坐标系统映射到另一个坐标系统的过程Left_nice= cv2.remap(frameL,Left_Stereo_Map[0],Left_Stereo_Map[1], interpolation = cv2.INTER_LANCZOS4, borderMode = cv2.BORDER_CONSTANT)  # Rectify the image using the kalibration parameters founds during the initialisationRight_nice= cv2.remap(frameR,Right_Stereo_Map[0],Right_Stereo_Map[1], interpolation = cv2.INTER_LANCZOS4, borderMode = cv2.BORDER_CONSTANT)# Convert from color(BGR) to graygrayR= cv2.cvtColor(Right_nice,cv2.COLOR_BGR2GRAY)grayL= cv2.cvtColor(Left_nice,cv2.COLOR_BGR2GRAY)# Compute the 2 images for the Depth_image计算深度信息disp= stereo.compute(grayL,grayR)#.astype(np.float32)/ 16dispL= dispdispR= stereoR.compute(grayR,grayL)dispL= np.int16(dispL)dispR= np.int16(dispR)# Using the WLS filter加权最小二乘滤波平滑filteredImg= wls_filter.filter(dispL,grayL,None,dispR)filteredImg = cv2.normalize(src=filteredImg, dst=filteredImg, beta=0, alpha=255, norm_type=cv2.NORM_MINMAX);filteredImg = np.uint8(filteredImg)#cv2.imshow('Disparity Map', filteredImg)#归一化:这个操作的目的是将原始的视差值映射到一定范围内的浮点数。通常,在计算机视觉中,视差图的像素值表示了对应像素点的深度信息,而视差值的范围通常较大。为了方便处理和可视化,我们需要将其缩放到一个合适的范围,以便更好地表达深度差异。disp= ((disp.astype(np.float32)/ 16)-min_disp)/num_disp # Calculation allowing us to have 0 for the most distant object able to detect##    # Resize the image for faster executions
##    dispR= cv2.resize(disp,None,fx=0.7, fy=0.7, interpolation = cv2.INTER_AREA)# Filtering the Results with a closing filter#用一矩阵去噪closing= cv2.morphologyEx(disp,cv2.MORPH_CLOSE, kernel) # Apply an morphological filter for closing little "black" holes in the picture(Remove noise) # Colors mapdispc= (closing-closing.min())*255dispC= dispc.astype(np.uint8)                                   # Convert the type of the matrix from float32 to uint8, this way you can show the results with the function cv2.imshow()disp_Color= cv2.applyColorMap(dispC,cv2.COLORMAP_OCEAN)         # Change the Color of the Picture into an Ocean Color_Mapfilt_Color= cv2.applyColorMap(filteredImg,cv2.COLORMAP_OCEAN) # Show the result for the Depth_image#cv2.imshow('Disparity', disp)#cv2.imshow('Closing',closing)#cv2.imshow('Color Depth',disp_Color)cv2.imshow('Filtered Color Depth',filt_Color)# Mouse clickscv2.setMouseCallback("Filtered Color Depth",coords_mouse_disp,filt_Color)# End the Programmeif cv2.waitKey(1) & 0xFF == ord(' '):break# Save excel
wb.save("data4.xlsx")# Release the Cameras
CamR.release()
CamL.release()
cv2.destroyAllWindows()

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

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

相关文章

UE5 UE4 修复GPU驱动程序崩溃

原贴链接&#xff1a;https://mp.weixin.qq.com/s/e5l9XtfwEFWgwhHi1b2idg UE5 UE4在处理含有大量图形的项目时&#xff0c;你有可能会遇到GPU崩溃 可以通过修改注册表&#xff0c;修复崩溃。 GPU崩溃情况概述 UE5 UE4在处理含有大量图形的项目时&#xff0c;你有可能会遇到G…

通过生成mcs、bin文件将程序固化到FPGA

通过将程序固化到FPGA&#xff0c;可以做到断电不丢失程序&#xff0c;上电之后就自动启动程序的作用&#xff0c;整个固化步骤主要分为3步&#xff0c;一是修改约束文件&#xff0c;二是生成mcs或bin文件&#xff0c;三是将程序固化到开发板flash 1.修改约束文件 生成固化文…

弟12章 网络编程

文章目录 网络协议概述 p164TCP协议与UDP协议的区别 p165TCP服务器端代码的编写 p166TCP服务器端流程 TCP客户端代码的编写 p167TCP客户端流程主机和客户端的通信流程 tcp多次通信服务器端代码 p168TCP多次通信客户端代码 p169UDP的一次双向通信 p170udp通信模型udp接收方代码u…

Git核心知识总结

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 工具教程 ✨特色专栏&#xff1a; MyS…

车辆行驶控制运动学模型的matlab建模与仿真,仿真输出车辆动态行驶过程

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 基本假设 4.2 运动学方程 5.完整工程文件 1.课题概述 车辆行驶控制运动学模型的matlab建模与仿真,仿真输出车辆动态行驶过程. 2.系统仿真结果 3.核心程序与模型 版本&#xff1a;MATLAB2022a .…

【HarmonyOS】消息通知场景的实现

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…

adb 常用命令汇总

目录 adb 常用命令 1、显示已连接的设备列表 2、进入设备 3、安装 APK 文件到设备 4、卸载指定包名的应用 5、从设备中复制文件到本地 6、将本地文件复制到设备 7、查看设备日志信息 8、重启设备 9、截取设备屏幕截图 10、屏幕分辨率 11、屏幕密度 12、显示设备的…

Druid连接池报错

网上各种方法都试了&#xff0c;基本都不行&#xff0c;后来改了一下jar包版本&#xff0c;也就是第四点&#xff0c;才解决。 1、druid.properties文件位置 我学的时候说的是任意位置都行&#xff0c;除了web目录下&#xff0c;但是我试的时候必须要放在resources 文件夹下。…

黑马程序员JavaWeb开发|案例:tlias智能学习辅助系统(5)登录认证

指路&#xff08;1&#xff09;&#xff08;2&#xff09;&#xff08;3&#xff09;&#xff08;4&#xff09;&#x1f447; 黑马程序员JavaWeb开发|案例&#xff1a;tlias智能学习辅助系统&#xff08;1&#xff09;准备工作、部门管理_tlias智能学习辅助系统的需求分析-CS…

python学习笔记10(选择结构2、循环结构1)

&#xff08;一&#xff09;选择结构2 1、if……else……语句 #&#xff08;1&#xff09;基本格式 numbereval(input("请输入您的6位中奖号码&#xff1a;")) if number123456:print("恭喜您&#xff0c;中奖了") else:print("未中奖")#&…

2024美赛数学建模思路 - 案例:FPTree-频繁模式树算法

文章目录 算法介绍FP树表示法构建FP树实现代码 建模资料 ## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c…

深度解析JVM类加载器与双亲委派模型

概述 Java虚拟机&#xff08;JVM&#xff09;是Java程序运行的核心&#xff0c;其中类加载器和双亲委派模型是JVM的重要组成部分。本文将深入讨论这两个概念&#xff0c;并解释它们在实际开发中的应用。 1. 什么是类加载器&#xff1f; 类加载器是JVM的一部分&#xff0c;负…

java-Lambda 语法总结

文章目录 Lambda 语法概览Lambda 表达式语法1.Lambda 表达式与函数接口2.Lambda 遇上 this final Lambda 语法概览 String(] names {”Justi n ”,”caterpillar”,”Bush " }; Arrays . sort (names, new Compara tor<String> () { publ int compare (String na…

pytorch12:GPU加速模型训练

目录 1、CPU与GPU2、数据迁移至GPU2.1 to函数使用方法 3、torch.cuda常用方法4、多GPU并行运算4.1 torch.nn.DataParallel4.2 torch.distributed加速并行训练 5、gpu总结 往期回顾 pytorch01&#xff1a;概念、张量操作、线性回归与逻辑回归 pytorch02&#xff1a;数据读取Data…

WordPress企业模板

首页大图wordpress外贸企业模板 橙色的wordpress企业模板 演示 https://www.zhanyes.com/waimao/6250.html

【算法Hot100系列】全排列

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

【学习iOS高质量开发】——熟悉Objective-C

文章目录 一、Objective-C的起源1.OC和其它面向对象语言2.OC和C语言3.要点 二、在类的头文件中尽量少引用其他头文件1.OC的文件2.向前声明的好处3.如何正确引入头文件4.要点 三、多用字面量语法&#xff0c;少用与之等价的方法1.何为字面量语法2.字面数值3.字面量数组4.字面量字…

vivado IP使用

使用IP源 注意&#xff1a;有关IP的更多信息&#xff0c;包括添加、打包、模拟和升级IP&#xff0c;请参阅VivadoDesign Suite用户指南&#xff1a;使用IP&#xff08;UG896&#xff09;进行设计。在Vivado IDE中&#xff0c;您可以在RTL项目中添加和管理以下类型的IP核心&…

高通sm7250与765G芯片是什么关系?(一百八十一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

HTML--CSS--边框、列表、表格样式

边框样式 属性&#xff1a; border-width 边框宽度 border-style 边框外观 border-color 边框颜色 需要同时设定三个属性 border-width 边框宽度 取值为像素值 border-style 边框样式 none 无样式 dashed 虚线 solid 实线 border-color 边框颜色 如示例&#xff1a; 为div设…