????????先前开源的一套旋转式三维彩色扫描仪Demo 得了很多小伙伴的关注,? ?但是当时仅为雏形Demo,仍然有许多悬而未决的问题,对于初学者非常不友好,很难复现。
基于MATLAB的线激光三维彩色扫描仪_Big_Huang的博客-CSDN博客暑期做的一个项目,开始并不是很熟悉,在网上查找的资料也不是很具体,但是自习学习了理论知识之后还是比较容易的做出来这个项目,现在开源整个项目,由于篇幅有限,本文适合稍微有点点基础的朋友。先显示下最后结果:一、硬件设计主要有步进电机(建议精度高点,这涉及到后面的精确度问题,一般42电机即可)、步进电机驱动、彩色相机、一字型激光头、arduino、各部分的供电单元;基本的...https://blog.csdn.net/Big_Huang/article/details/98779861
????????现整理了一套完整的,平移线扫重建 matlab代码,包含相机标定、光平面标定与方案、移动装置标定与方案、激光线条中心线自适应亚像素提取、畸变矫正、三维重建、点云滤波等部分,代码按模块编写,注释完整,附带一份完整苹果表面扫描数据,处理277张300w像素图片仅耗时15秒,测量精度0.1mm。 算法处理不感知硬件转置,按照数据说明要求采集数据后即可得到结果。
主函数代码如下, 涉及各部分的代码在均在工程中自定义实现,由于篇幅限制,完整工程可以有尝联系作者获取, 扣扣: 893231644
clear;
close all;
%% 获取相机标定结果
% MATLAB 需转置矩阵
load('cameraParams.mat');
intriMatrix = cameraParams.IntrinsicMatrix';
radialDistortion = cameraParams.RadialDistortion;
% 相机坐标系到唯一世界坐标系的旋转、平移矩阵
% 选定其中一张
Rw = cameraParams.RotationMatrices(:, :, 27)';
Tw = cameraParams.TranslationVectors(27, :)';
%% 光平面方程标定
% 获得激光平面参数
% z = planeParams(1) + planeParams(2) * x + planeParams(3) * y
planeParams = calibrateLightPlane(cameraParams, Rw, Tw, [21, 22, 23, 24, 25, 26], '.\images\Laser', 0);
%% 位移平台标定
% 获得平面位移参数 [dx, dy, dz]
[dx, dy, dz] = calibrateTranslationPlane(cameraParams, Rw, Tw, [27, 28], 60);
%% 点云生成
thresh = 0.3; % 激光图片二值化的阈值 阈值太重要了 ^_^
frame_num = 277; % 图片数目
WCS = zeros(200000, 3); % 所有点的坐标,预申请内存(发现处理的越来越慢则是申请内存开销较大,需提取申请更大内存)
index = 1; % 存储坐标
tic; % tic;与toc;配合使用能够返回程序运行时间
bar = waitbar(0,'读取数据中...'); % waitbar显示进度条
% 逐个图片
for frame_index = 1 : frame_num
frame = imread(['.\images\Frames\', num2str(frame_index), '.jpg']);
frame_grey = rgb2gray(frame);
% 畸变矫正 (自行选用)
% 相机畸变较小时,矫正前后精度差别不大,但是畸变矫正会额外增加近乎一倍的计算耗时
% frame_grey = undistortImage(frame_grey, intriMatrix, radialDistortion);
str=['处理中...', num2str(100 * frame_index / frame_num), '%']; % 百分比形式显示处理进程
wb = waitbar(frame_index / frame_num, bar, str) % 更新进度条bar
% 求解激光线条中心线像素坐标
laserPixel = getLaserCenter(frame_grey, thresh, 50, 'Adaptive', 0);
% 逐个像素
for pixel_index = 1 : length(laserPixel)
% 求解世界坐标系
[Xw, Yw, Zw] = pcs2wcs(laserPixel(pixel_index, 1), laserPixel(pixel_index,2), intriMatrix, Rw, Tw, planeParams);
% 加上平台位移量(先入的偏移量最大)
Xw = Xw + dx * (frame_num - frame_index);
Yw = Yw + dy * (frame_num - frame_index);
Zw = Zw + dz * (frame_num - frame_index);
% 存储点
WCS(index, :) = [Xw Yw Zw];
index = index + 1;
end
end
% 去除空白内存数据
WCS (all(WCS == 0, 2),:) = [];
% 空间分布的去噪
[idx1, a] = SOR(WCS, 0.2, 6);
% 可能还会存在些许离群点(一般是小块点云),但是多次空间分布去噪会腐蚀点云边界
% [idx2, a] = SOR(a, 0.8, 6);
% [idx3, a] = SOR(a, 0.5, 5);
toc; % tic与toc;配合使用能够返回程序运行时间
% 可视化
subplot(1,2,1),pcshow(WCS, idx1)
subplot(1,2,2),pcshow(a)
% 存储最终点云数据
close(wb);
save('apple.txt', 'a', '-ascii');
fprintf(' 处理完成! Saved as ‘apple.txt‘ \n');
|