1、MATLAB读取pcd文件
% 读取 pcd 文件,并取出 xyz 坐标
ptCloud = pcread('table.pcd');
% 可视化显示当前 pcd 文件
pcshow(ptCloud);
% 将该文件的 xyz 坐标取出
point_xyz = ptCloud.Location;
% 分别取出 x, y, z 坐标,并转化为 double 型(一开始是 single 类型)
px = double(point_xyz(:,1));
py = double(point_xyz(:,2));
pz = double(point_xyz(:,3));
用于存储所读取 pcd 文件变量 ptCloud 的数据格式:
其中Location 就是点云的 xyz 坐标,这里使用的是 n 行 3 列分别对应 xyz,所以将其取出可以进行后续的处理操作,例如转换为 mat 格式等。
2、pcd转ply
pcd文件
ply文件
用一个loadpcd函数导进matlab,然后再用工具箱自带的pointCloud函数把导进的三维点云矩阵变成点云对象,就可以进行其他操作了。以下是loadpcd文件代码
%LOADPCD Load a point cloud from a PCD format file
%
% P = LOADPCD(FNAME) is a set of points loaded from the PCD format
% file FNAME.
%
% For an unorganized point cloud the columns of P represent the 3D points,
% and the rows are: x, y, z, r, g, b, a depending on the FIELDS in the file.
%
% For an organized point cloud P is a 3-dimensional matrix (HxWxN) where the
% N planes are: x, y, z, r, g, b, a depending on the FIELDS in the file. This
% format is useful since the planes z, r, g, b, a can be considered as images.
%
% Notes::
% - Only the x y z field format are currently supported
% - The file can be in ascii or binary format, binary_compressed is not
% supported
%
% See also pclviewer, lspcd, loadpcd.
%
% Copyright (C) 2013, by Peter I. Corke
% TODO
% - handle binary_compressed
function points = loadpcd(fname)
verbose = true;
fp = fopen(fname, 'r');
while true
line = fgetl(fp);
if line(1) == '#'
continue;
end
[field,remain] = strtok(line, ' \t');
remain = strtrim(remain);
switch field
case 'VERSION'
continue;
case 'FIELDS'
FIELDS = remain;
case 'TYPE'
TYPE = remain;
case 'SIZE'
sizes = str2num(remain);
case 'WIDTH'
width = str2num(remain);
case 'HEIGHT'
height = str2num(remain);
case 'POINTS'
npoints = str2num(remain);
case 'COUNT'
count = str2num(remain);
case 'DATA'
mode = remain;
break;
otherwise
warning('unknown field %s\n', field);
end
end
% parse out details of the fields
% numFields the number of fields
% sizes vector of field sizes (in bytes)
% types vector of type identifiers (I U F)
% fields vector of field names (x y z rgb rgba etc)
numFields = numel(sizes);
types = cell2mat(regexp(TYPE,'\s+','split'));
fields = regexp(FIELDS,'\s+','split');
if verbose
% the doco says height > 1 means organized, but some old files have
% height = 1 and width > 1
if height > 1 && width > 1
organized = true;
org = 'organized';
else
organized = false;
org = 'unorganized';
end
fprintf('%s: %s, %s, <%s> %dx%d\n', ...
fname, mode, org, FIELDS, width, height);
fprintf(' %s; %s\n', TYPE, num2str(sizes));
end
if any(count > 1)
error('can only handle 1 element per dimension');
end
switch mode
case 'ascii'
format = '';
for j=1:numFields
switch types(j)
case 'I', typ = 'd';
case 'U', typ = 'u';
case 'F', typ = 'f';
end
format = [format '%' typ num2str(sizes(j)*8)];
end
c = textscan(fp, format, npoints);
points = [];
for j=1:length(c)
points = [points; c{j}'];
end
if size(points,2) ~= npoints
error('incorrect number of points in file: was %d, should be %d', ...
size(points,2), npoints);
end
case 'binary'
format = '';
if true || all(types == types(1)) && all(sizes == sizes(1))
% simple case where all fields have the same length and type
% map IUF -> int, uint, float
switch types(1)
case 'I'
fmt = 'int';
case 'U'
fmt = 'uint';
case 'F'
fmt = 'float';
end
format = [format '*' fmt num2str(sizes(1)*8)];
points = fread(fp, [numFields npoints], format);
else
% more complex case where fields have different length and type
% code contributed by Will
startPos_fp = ftell(fp);
% Just initialize the xyz portion for now
points = zeros(3, npoints);
for i=1:numFields
% map each field sequentially, using fread() skip functionality,
% essentially interleaved reading of the file
% map IUF -> int, uint, float
switch types(i)
case 'I'
fmt = 'int';
case 'U'
fmt = 'uint';
case 'F'
fmt = 'float';
end
format = ['*' fmt num2str(sizes(i)*8)];
fseek(fp, startPos_fp + sum(sizes(1:i-1)), 'bof');
data = fread(fp, [1 npoints], format, sum(sizes)-sizes(i));
switch fields{i}
case 'x'
points(1,:) = data;
case 'y'
points(2,:) = data;
case 'z'
points(3,:) = data;
case {'rgb', 'rgba'}
points(4,:) = data;
end
end
end
case 'binary_compressed'
% binary part of the file contains:
% compressed size of data (uint32)
% uncompressed size of data (uint32)
% compressed data
% junk
compressed_size = fread(fp, 1, 'uint32');
uncompressed_size = fread(fp, 1, 'uint32');
compressed_data = fread(fp, compressed_size, 'uint8')';
uncompressed_data = lzfd(compressed_data);
if length(uncompressed_data) ~= uncompressed_size
error('decompression error');
end
% the data is stored unpacked, that is one field for all points,
% then the next field for all points, etc.
start = 1;
for i=1:numFields
len = sizes(i)*npoints;
switch types(1)
case 'I'
fmt = 'int32';
case 'U'
fmt = 'uint32';
case 'F'
fmt = 'single';
end
field = typecast(uncompressed_data(start:start+len-1), fmt);
start = start + len;
switch fields{i}
case 'x'
points(1,:) = field;
case 'y'
points(2,:) = field;
case 'z'
points(3,:) = field;
case {'rgb', 'rgba'}
points(4,:) = field;
end
end
otherwise
error('unknown DATA mode: %s', mode);
end
if size(points,1) > 3
% convert RGB from float to rgb
rgb = typecast(points(4,:), 'uint32');
switch FIELDS
case 'x y z rgb'
R = double(bitand(255, bitshift(rgb, 16))) /255;
G = double(bitand(255, bitshift(rgb, 8))) /255;
B = double(bitand(255, rgb)) /255;
points = [points(1:3,:); R; G; B];
case 'x y z rgba'
R = double(bitand(255, bitshift(rgb, 24))) /255;
G = double(bitand(255, bitshift(rgb, 16))) /255;
B = double(bitand(255, bitshift(rgb, 8))) /255;
A = double(bitand(255, rgb)) /255;
points = [points(1:3,:); R; G; B; A];
end
end
if organized
% data is an organized point cloud, rearrange it into planes
points = permute( reshape( shiftdim(points, 1), width, height, []), [2 1 3]);
end
fclose(fp);
将pcd转成ply
pt=loadpcd('Worldpoints.pcd')
ptCloud = pointCloud(pt')
%ptCloudOut = pcdownsample(ptCloud,'gridAverage',1)
pcwrite(ptCloud,'Worldpoints_down.ply')
ply文件显示
ptCloud = pcread('Worldpoints_down.ply');
% 可视化显示当前 pcd 文件
pcshow(ptCloud);