基于matlab的sfm三维重建

2023-10-21 16:20
文章标签 matlab 三维重建 sfm

本文主要是介绍基于matlab的sfm三维重建,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于matlab的sfm三维重建

想学习三维重建,但是不会c++语言,python调用opencv弄得我头大,正好matlab上也有三维重建的代码,于是编跟着案例库的案例倒弄了一阵,大致弄明白了,分享一个流程给新手做参考。
ps:几个周以后再看自己做的这个,都是啥玩意,我都不好意思看了,事实上这个算不上稠密重建,纹理映射没有,由于手机是双摄标定出来也不准确,导致三角测量时相机位置偏的太多,在之后点云拼接的时候是一团乱麻,根本拼不上,毕竟新手起步,等我把整个完整流程弄完了再来分享。

1,加载图像和相机标定

相机参数需要先标定相机,matlab带有一个相机标定工具箱,很简单。一开始想做无标定三维重建的,但是方法我没找到。
本方法重建效果主要取决于三点:图像质量,相机校正好坏,特征匹配方法。

imageDir = fullfile('D:','picture','box');  % 这里输入路径,我重建的对象是一个盒子
imds = imageDatastore(imageDir);
load('calibrationSession');  % 加载相机参数,这个是matlab标定工具箱标定好后保存的mat文件
cameraParams = calibrationSession.CameraParameters;  %我们需要的是CameraParameters

将图像都转化为灰度图,特征检测只能检测灰度图。

images = cell(1, numel(imds.Files));
for i = 1:numel(imds.Files) % 图片的数量I = readimage(imds, i);images{i} = rgb2gray(I); 
end

实验室的盒子,一共拍摄了16张图片
实验室盒子

2、创建图像追踪和配置颜色模板

创建图像追踪,原理就是先检测第一张图片所有的特征点,然后设置一个追踪器tracker,和图像管理器vSet,在剩下图片中追踪该特征点,然后储存在vSet中,同时vSet还储存相机位置等。(vSet貌似不能储存颜色信息,所以我才把颜色单独弄出来)

以第一二张图为基准读取点云信息,用于后面的颜色匹配。

I1 = readimage(imds, 1);% 读取第1张图片
I2 = images{2};  % 这里读取的不是灰度图
[currPoints, validIdx] = step(tracker, I2);
matchedPoints = PrevPoints(validIdx, :);

特征检测,最小特征值检测方法,速度稍慢,特征多,surf特征检测方法,速度快,检测特征少,KAZE很慢,列出来的原因是因为matlab没自带sift。

I = images{1};  % 选择第一张灰度图像
prevPoints = detectMinEigenFeatures(I, 'MinQuality', 0.001,'FilterSize', 5);  
% prevPoints = detectSURFFeatures(I,'MetricThreshold',5,'NumScaleLevels',6);  
% prevPoints = detectKAZEFeatures(I,'Diffusion','region','Threshold',...
% 0.00001,'NumOctaves',4,'NumScaleLevels',5);  

创建追踪器来追踪特征点

tracker = vision.PointTracker('MaxBidirectionalError', 1, 'NumPyramidLevels',...
6,'BlockSize',[31,31]);
% 初始化点跟踪器。
PrevPoints = prevPoints.Location;
initialize(tracker, PrevPoints, I);

将检测出来的点存放在vSet中

vSet = viewSet;  % matlab自带的视图管理器
viewId = 1;
vSet = addView(vSet, viewId, 'Points', prevPoints, 'Orientation', ...eye(3, 'like', PrevPoints), 'Location', ...zeros(1, 3, 'like', PrevPoints));

MinEigen最小特征法检测的稠密点匹配(8w多个点)
detectMinEigenFeatures
kaze特征检测的稠密点(4w多个点)。
kaze

3、重建主流程

这里不分稀疏重建和稠密重建,根据特征检测时把对应参数调高或者调低,来控制稀疏还是稠密。
注意,我这里只重建第一张图所包含的内容!!!
在这里追踪器开始产生作用

for i = 2:numel(images)I = images{i};[currPoints, validIdx] = step(tracker, I); %追踪第i张图片的特征点,返回特征点和点的对应关系matchedPoints1 = PrevPoints(validIdx, :);  % 筛选出来的匹配点matchedPoints2 = currPoints(validIdx, :);[E, epipolarInliers] = estimateEssentialMatrix(matchedPoints1,...matchedPoints2,cameraParams);%警告:已达到最大审判次数。考虑增加最大距离或降低期望的信心。inlierPoints1 = matchedPoints1(epipolarInliers, :);inlierPoints2 = matchedPoints2(epipolarInliers, :);[orient, loc] = relativeCameraPose(E, cameraParams,... inlierPoints1,inlierPoints2);% 将当前视图匹配添加到视图集vSet = addView(vSet, i, 'Points', currPoints);% 存储上一个视图和当前视图之间的点匹配。matches = repmat((1:size(PrevPoints, 1))', [1, 2]);matches = matches(validIdx, :); vSet = addConnection(vSet, i-1, i, 'Matches',matches);% 因为储存的点为PrevPoints和currPoints,要变成 matchedPoints1,2的对应关系。% 获取包含前一个相机姿势的表。prevPose = poses(vSet, i-1);prevOrientation = prevPose.Orientation{1};prevLocation = prevPose.Location{1};% 计算当前相机在全局坐标系中相对于第一个视图的姿态。orientation = orient * prevOrientation;location    = prevLocation + loc * prevOrientation;vSet = updateView(vSet, i, 'Orientation', orientation, 'Location', location);tracks = findTracks(vSet);   % 在所有视图中查找轨迹camPoses = poses(vSet);    % 得到所有视角的相机姿态表% 确定三维世界点的初始位置。xyzPoints = triangulateMultiview(tracks, camPoses, cameraParams);% 改进三维世界点和相机的姿势.(光束平差法)[xyzPoints, camPoses, reprojectionErrors] = bundleAdjustment(xyzPoints, ...tracks, camPoses, cameraParams, 'FixedViewId', 1, ...'PointsUndistorted', true);% 保存精准的相机姿势vSet = updateView(vSet, camPoses);PrevPoints   = currPoints;  
end  

4、添加颜色

原理很简单,就是找三维点在像素平面中对应位置的颜色信息,然后添加上去。

numPixels = size(I1, 1) * size(I1, 2);   %读取图片尺寸
allColors = reshape(I1, [numPixels, 3]);   % 改变数组的维数。
colorIdx = sub2ind([size(I1, 1), size(I1, 2)], round(matchedPoints(:,2)), ...
round(matchedPoints(:, 1)));
color = allColors(colorIdx, :);
% 创建点云
goodIdx = (reprojectionErrors < 15);  % 删除误差大的点
xyzPoints = xyzPoints(goodIdx, :);
Color = color(goodIdx, :);
ptCloud = pointCloud(xyzPoints, 'Color', Color);   % 将点云添加上颜色

5、显示点云图

% 显示相机姿态
% camPoses = poses(vSet);
% figure;
% plotCamera(camPoses, 'Size', 0.2);
% hold on% 显示三维点.
pcshow(ptCloud, 'VerticalAxis', 'y', 'VerticalAxisDir', 'down', ...'MarkerSize', 45);
grid on
hold off
% 查看指定卷,免得图像乱跑
loc1 = camPoses.Location{1};
xlim([loc1(1)-5, loc1(1)+4]);
ylim([loc1(2)-5, loc1(2)+4]);
zlim([loc1(3)-1, loc1(3)+20]);
camorbit(0, -30);
% 储存点云
a = cell(1,i);
a{1} = ptCloud;
save('PtCloud.mat','a');

6、重建结果

minEigen特征
mineigen特征
surf特征
surf特征
kaze特征
kaze特征

目前遇到问题有两个,一个是颜色匹配有点误差,还有一个是太占内存了,如果电脑内存不够可能会出现错误。
接下来研究一下如何重建一个完整的盒子,考虑再用一个循环,然后点云拼接,本人新手上路,有大神的话可以指点一下。
附带我的程序和图片:sfm三维重建

这篇关于基于matlab的sfm三维重建的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/255525

相关文章

matlab读取NC文件(含group)

matlab读取NC文件(含group): NC文件数据结构: 代码: % 打开 NetCDF 文件filename = 'your_file.nc'; % 替换为你的文件名% 使用 netcdf.open 函数打开文件ncid = netcdf.open(filename, 'NC_NOWRITE');% 查看文件中的组% 假设我们想读取名为 "group1" 的组groupName

利用matlab bar函数绘制较为复杂的柱状图,并在图中进行适当标注

示例代码和结果如下:小疑问:如何自动选择合适的坐标位置对柱状图的数值大小进行标注?😂 clear; close all;x = 1:3;aa=[28.6321521955954 26.2453660695847 21.69102348512086.93747104431360 6.25442246899816 3.342835958564245.51365061796319 4.87

C# double[] 和Matlab数组MWArray[]转换

C# double[] 转换成MWArray[], 直接赋值就行             MWNumericArray[] ma = new MWNumericArray[4];             double[] dT = new double[] { 0 };             double[] dT1 = new double[] { 0,2 };

libsvm在matlab中的使用方法

原文地址:libsvm在matlab中的使用方法 作者: lwenqu_8lbsk 前段时间,gyp326曾在论坛里问libsvm如何在matlab中使用,我还奇怪,认为libsvm是C的程序,应该不能。没想到今天又有人问道,难道matlab真的能运行libsvm。我到官方网站看了下,原来,真的提供了matlab的使用接口。 接口下载在: http://www.csie.ntu.edu.

Matlab/Simulink中PMSM模型的反电动势系数和转矩系数

Matlab/Simulink中PMSM模型的反电动势系数和转矩系数_matlab pmsm-CSDN博客

MATLAB层次聚类分析法

转自:http://blog.163.com/lxg_1123@126/blog/static/74841406201022774051963/ 层次聚类是基于距离的聚类方法,MATLAB中通过pdist、linkage、dendrogram、cluster等函数来完成。层次聚类的过程可以分这么几步: (1) 确定对象(实际上就是数据集中的每个数据点)之间的相似性,实际上就是定义一个表征

MATLAB的fix(),floor()和ceil()函数的区别与联系

fix(x),floor(x)和ceil(x)函数都是对x取整,只不过取整方向不同而已。 这里的方向是以x轴作为横坐标来看的,向右就是朝着正轴方向,向左就是朝着负轴方向。 fix(x):向0取整(也可以理解为向中间取整) floor(x):向左取整 ceil(x):向右取整 举例: 4个数:a=3.3、b=3.7、c=-3.3、d=-3.7 fix(a)=3 fl

MATLAB中的eig函数

在MATLAB中,计算矩阵A的特征值和特征向量的函数是eig(A),常用的调用格式有5种: E=eig(A):求矩阵A的全部特征值,构成向量E。 [V,D]=eig(A):求矩阵A的全部特征值,构成对角阵D,并求A的特征向量构成V的列向量。 [V,D]=eig(A,'nobalance'):与第2种格式类似,但第2种格式中先对A作相似变换后求矩阵A的特征值和特征向量,而格式3直接求矩阵A的特

MATLAB中的diag函数

diag函数功能:矩阵对角元素的提取和创建对角阵 设以下X为方阵,v为向量 1、X = diag(v,k)当v是一个含有n个元素的向量时,返回一个n+abs(k)阶方阵X,向量v在矩阵X中的第k个对角线上,k=0表示主对角线,k>0表示在主对角线上方,k<0表示在主对角线下方。例1: v=[1 2 3]; diag(v, 3) ans =      0     0     0

Matlab simulink建模与仿真 第十章(模型扩展功能库)

参考视频:simulink1.1simulink简介_哔哩哔哩_bilibili 一、模型扩展功能库中的模块概览         注:下面不会对Block Support Table模块进行介绍。 二、基于触发的和基于时间的线性化模块 1、Trigger-Based Linearization基于触发的线性化模块 (1)每次当模块受到触发时,都会调用linmod或者dlinmod函数