【matlab下的双目内窥镜标定与深度测距】
情景题要
最近一段时间在研究内窥镜的深度信息采集,再这一领域当前的研究相当少,且没有相关的供应商。
在去年的时候跟随师兄师姐们前往南京参加第七届中国内窥镜大会,大会理论上应该是涵盖了中国全方面的内窥镜生产工艺和内窥镜供应商。
但是在对参会的所有展位都进行询问之后了解到,当前在国内这一领域相当空白,当前没有任何一家供应商能够实现具有准确深度感知功能的内窥镜产品。
所有的与深度3D相关的产品实际上都是医生端的视觉3D效果,但是在研究领域,手术的自动化智能化是必然趋势,其中首当其冲的就是感知,内窥镜作为内窥镜手术的重要感知工具,在未来必将需要从技术上实现对人体腹腔信息的准确深度感知能力,并且后续的智能化操作和决策提供感知依据。
在以上前提背景之下,进行了内窥镜深度感知的探索,截止目前为止呢,狗某人这个探索基本上可以说是,比较失败了。但是希望该博文和研究经验,能为未来的青年工程师,科研人员以及开发者提供经验和参考。加油,不要放弃,彦祖们
内窥镜要求
在这一探索过程中,分别进行了单目深度和双目深度测距以及深度神经网络,包括从matlab到opencv-python以及opencv-c++下的测试。个人觉得比较靠谱的还是双目深度测距方法,标定最好使用matlab进行相机标定,在本文中详细介绍对双目内窥镜的标定和深度测距结果。但是请注意,标定和深度准确的前提是,双目内窥镜的设计合理可靠,否则即使算法再优秀也没有办法达到理想效果。
双目内窥镜标定
深度提取结果与标定质量密切相关
深度提取结果与标定质量密切相关
深度提取结果与标定质量密切相关
走传送门吧,内容有点多:
双目成像原理
辛苦再走一遍传送门吧彦祖:
【matlab下的双目内窥镜标定与深度测距-双目成像原理】
回看了以下,我这篇原理写的不太好,有点混乱,这篇的推导写的清楚一些:
双目成像
matlab代码
首先完成标定,使用matlab写代码的好处在于可以直接通过load函数直接读取标定参数,在通过C++和python语言时,都需要进行转换,且需要注意matlab标定参数的结果和opencv标定参数的结果格式并不完全相同,需要进行部分转换,否则在极线矫正阶段就会失真
% 读取图像文件
left_imageFileName = 'D://matlab双目标定//depth//left_image_5.jpg';
right_imageFileName = 'D://matlab双目标定//depth//right_image_5.jpg';
leftimg = imread(left_imageFileName);
rightimg = imread(right_imageFileName);
% 加载相机标定参数(示例,需要替换为实际路径和文件名)
stereoParams = load('weigao024.mat');
% 获取左右相机的标定参数
cameraParamsLeft = stereoParams.stereoParams.CameraParameters1;
cameraParamsRight = stereoParams.stereoParams.CameraParameters2;
在这里需要注意的一点时,如果通过load函数读取已经保存的mat相机参数时,需要用两个stereoParams.stereoParams.读取
% 进行去畸变
undistortedImageLeft = undistortImage(leftimg, cameraParamsLeft);
undistortedImageRight = undistortImage(rightimg, cameraParamsRight);
去畸变,然后极线对齐之后才能进行深度估计,不明白的彦祖走原理传送门
% 显示原始图像和去畸变后的图像
figure;
subplot(2, 2, 1);
imshow(leftimg);
title('Original Image left');
subplot(2, 2, 2);
imshow(undistortedImageLeft);
title('Undistorted Image left');
subplot(2, 2, 3);
imshow(rightimg);
title('Original Image right');
subplot(2, 2, 4);
imshow(undistortedImageRight);
title('Undistorted Image right');
展示效果
% 进行立体校正
grayL = rgb2gray(leftimg);
grayR = rgb2gray(rightimg);
[re_imgleft, re_imgright,Q,Pl,Pr,Rl,Rr] = rectifyStereoImages(leftimg,rightimg,stereoParams.stereoParams,'OutputView', 'valid');
获得视差图,此时就已经得到深度关系
%计算视差
disparityMap = disparity(re_imgleft,re_imgright,'BlockSize',19);
计算真实距离
%根据小孔成像Z=bf/d
fx = (cameraParamsLeft.FocalLength(1,2)+cameraParamsRight.FocalLength(1,2))./2; % 焦距
% fx = stereoParams.stereoParams.CameraParameters2.IntrinsicMatrix(1,1);
baseline = norm(stereoParams.stereoParams.TranslationOfCamera2)/1000; % 基线长度 单位:mm
% baseline=0.00735
bf = fx*baseline;
disparityValues = double(disparityMap); % 转换为 double 类型
% 计算真实距离
Z = bf ./ disparityValues;
figure
imshow(Z)
都看到这了,点个赞再走吧彦祖
效果
输入图像,部分区域人为涂白了以遮挡信息,与原始图像无关
图像矫正结果
极线对齐结果未显示,可去标定篇查看
视差图:
深度图
为了测试深度结果,需要提取坐标点和其中储存的深度值
点击其中的 数据提示(A)
即可查看
分析
可以看到虽然能够有效的展现出深度关系,再部分范围之内也可以表现出厘米级甚至是厘米级一下的视觉精度,但是在部分区域内的视觉误差达到50mm以上,这是极难接受的误差级别,在医疗场景之下至少达到毫米级以及毫米级以下的精度。因此这一方法仍不适用。
此外,由于本次标定的重投影误差在0.18左右,因此标定结果并不是最优,也导致深度估计出现了问题,如果可以降低到0.05以下,精度应该可以有效提高。此外需要注意的是,深度准确区域一般是标定时标定板距离内窥镜的距离区域。
都看到这了,点个赞再走吧彦祖