Code covered by the BSD License  

Highlights from
MATLAB to Point Cloud Library

4.5

4.5 | 8 ratings Rate this file 132 Downloads (last 30 days) File Size: 7.42 KB File ID: #40382
image thumbnail

MATLAB to Point Cloud Library

by

 

19 Feb 2013 (Updated )

matpcl is pure MATLAB code that allows interfacing with the Point Cloud Library (PCL) tools

| Watch this File

File Information
Description

matpcl is pure MATLAB code that allows interfacing with the Point Cloud Library (PCL) tools by reading and writing PCD format files. Being pure MATLAB avoids all kinds of headaches in trying to link PCL code into MEX files which involves various grief such as versions of compilers and support libraries such as boost.

There are only four user-level functions:

savepcd() writes a matrix as an optionally coloured point cloud in an ASCII PCD format file.

loadpcd() reads an optionally colored point cloud from a PCD format file (ASCII or binary) and returns a matrix.

pclviewer() writes a matrix to a temporary file and invokes the pcl_viewer app for visualization. This is much much faster for rotating a large point cloud than using a MATLAB 3D plot.

lscpd() shows the attributes of the PCD files in the current directory

Point clouds are considered to be either:

2-d matrices, with one column per point. The rows are X, Y, Z and for a colored point cloud X, Y, Z, R, G, B. (R,G,B) are in the range 0 to 1.

3-d matrices, with planes X, Y, Z and for a colored point cloud X, Y, Z, R, G, B. (R,G,B) are in the range 0 to 1.

Limitations (for now):

- No support for reading/writing normals

Required Products MATLAB
MATLAB release MATLAB 8.0 (R2012b)
Other requirements To run the viewer function pclviewer() you require an install of PCL. Edit pclviewer() to include the path to where your PCL binaries are installed, currently setup for MacOSX.
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (18)
15 Sep 2014 Dereck  
15 May 2014 Mohammad Nahangi  
17 Apr 2014 Jasper

Hi! Very useful when trying to use point clouds created with PCL in MATLAB. However, I have a couple of comments:
1.) The processing of RGBA values still does not work for my *.pcd files - also not with Rui's answer. I have noticed, that the A values actually are written BEFORE the RGB values, such that for me
A = double(bitand(255, bitshift(rgb, -24))); % A apparently is in front of RGB!
R = double(bitand(255, bitshift(rgb, -16)));
G = double(bitand(255, bitshift(rgb, -8)));
B = double(bitand(255, rgb));
is correct.

2.) There are problems when there are NaN-points in the cloud. I was able to correct the problems for ASCII files. When the read data is put into a single matrix, all values are cast to the same type. This can be a problem, since uint32(NaN) = 0! Therefore, make sure that this cast does not happen :)

07 Apr 2014 Justin Enjo

I'm trying to create a PCD from a Mx3 matrix of surface XYZ Data. I keep getting the following error:

Undefined function or variable "fields".

Error in savepcd (line 110)
fprintf(fp, 'FIELDS %s\n', fields);

Any suggestions?

06 Dec 2013 xuan yuanlei  
27 Oct 2013 Rui

How to solve the problem commented by Paul Doliotis:

Just do as suggested by Daniel Wolf, go to lines 231-239 and replace bitshift(rgb, x) by bitshift(rgb, -x),

Before:

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];

After:

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];

And it will work fine.

15 Sep 2013 Paul Doliotis

This code is very helpfull.
I am trying to load a pcd file (binary uncompressed). According to documentation P is a 3-dimensional matrix (HxWxN). P(:,:,4) should be the R channel, P(:,:,5) the G and P(:,:,6) the B channel. However R,G and B are full of zeros. Only P(:,:,7) is in the range [0-1]. But when I visualize using imshow its grayscale. Any help on this? Thanks!

08 Sep 2013 Kristen

This library is super helpful.

I am having one issue - I'm using savepcd.m to save a point cloud from matlab in ascii. When I run a simple input script in cpp, I get the error "Failed to find match for field 'rgb'." However, when I change the type in the header from int to float (TYPE F F F I >> TYPE F F F F), the data reads in correctly (though rgb values are not preserved)

05 Aug 2013 Johnathan

I think there is a bug in loadpcd.m. When you save and then reload an organized point cloud, visualization of the z component doesn't come out right.

The fix that I found was to switch height and width in line 248 of loadpcd.m. Corrected line:

points = permute( reshape( shiftdim(points, 1), width, height, []), [2 1 3]);

04 Jul 2013 Rui

I have the same error message in lzfd.m
Although I am not quite sure how it works, but you can easily change the line
outlen = 2 * length(in)
to
outlen = n * length(in) n>2

Then it will work.

18 Jun 2013 Siddharth Choudhary

Hi Peter,

I get the error:

Index exceeds matrix dimensions.

Error in lzfd (line 59)
out(op:op+len-1) = out(ref:ref+len-1);

Error in loadpcd (line 188)
uncompressed_data = lzfd(compressed_data);

when I run loadpcd on a PCD file link: http://cogrob-dell-desktop.cc.gt.atl.ga.us/test.pcd

Can you check it?

Thanks,

11 Jun 2013 Peter Corke

Lauri, sorry to hear this is not working. I don't fully understand the lzfd logic, just transliterated it from another language and it worked ok on the compressed files I had. Can you share the file that caused the problem?

28 Apr 2013 Lauri

Hi,

lzfd.m (run by loadpcd.m) gives this error:

Index exceeds matrix dimensions.
Error in lzfd (line 59)
out(op:op+len-1) = out(ref:ref+len-1);

with this data (compressed binary): http://www.cs.tut.fi/~virtanel/skene2.pcd

Unfortunately I have no other datafiles to test nor time to debug lzfd myself.

19 Apr 2013 Daniel Wolf

Thanks a lot for your helpful work!
I think I've found a small bug in the loadpcd function processing RGB values. When you split the 4th field into RGB or RGBA values, everytime you shift the field value in the wrong direction using bitshift. Instead of bitshift(rgb, 16) it should be bitshift(rgb, -16) for a right shift instead of a left shift.

23 Mar 2013 Peter Corke

Thanks for the addition. regexp(... 'split') is a useful thing, I was looking for the equivalent of python's split() but didn't find this.

binary_compressed format next?

22 Mar 2013 Will

For the binary case, I've written some code to handle the rgb / rgba case. Please feel free to use / modify as needed. I hope this helps.

case 'binary'
startPos_fp = ftell(fp);
numFields = numel(siz);
typeTokens = regexp(type,'\s+','split');
fieldTokens = regexp(fields,'\s+','split');

% Just initialize the xyz portion for now
points = zeros(3, npoints);

for i=1:numFields
% map IUF -> int, uint, float
typeToken = typeTokens{i};
switch typeToken
case 'I'
fmt = 'int';
case 'U'
fmt = 'uint';
case 'F'
fmt = 'float';
end

format = ['*' fmt num2str(siz(i)*8)];
fseek(fp, startPos_fp + sum(siz(1:i-1)), 'bof');
data = fread(fp, [1 npoints], format, sum(siz)-siz(i));

fieldToken = fieldTokens{i};
switch fieldToken
case 'x'
points(1,:) = data;
case 'y'
points(2,:) = data;
case 'z'
points(3,:) = data;
case 'rgb'
rgb = typecast(data, 'uint32');
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 'rgba'
rgb = typecast(data, 'uint32');
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];
end
end

12 Mar 2013 Peter Corke

Thanks for pointing this out, I fixed the problem and uploaded a revised version of the code.

10 Mar 2013 Albert

First of all, thank you very much for the software. It is being very useful to me.

In addition, I want to comment you something. I've had a problem trying to run the software. Concretely, in loadpcd.m I was having an error related to the function "numcols" at the line 81. Matlab interpreter was complaining about it in such a way: "undefined function".

Well, I don't like to do this at all, but I changed "numcols(size)" by simply "length(size)" and I think it's working now.

Maybe the error is given by the fact that I'm in Matlab 2012a. As I see, you specified 2012b as your release.

Anyway, I just want to warn you.

Updates
22 Feb 2013

added logo image

11 Mar 2013

Removed references to function numcols() and replaced with the standard MATLAB function size(). Bad coding habit on my part...

25 Mar 2013

Now support organized point clouds. In MATLAB these are treated as 3D matrices with planes for X, Y, Z, etc.

Incorporated patch by Will.

Added lspcd() function to show attributes of PCD files in current directory.

14 Apr 2013

I've added some code to handle binary_compressed format, but it's not fully tested. To read these files requires LZF decoding, and so I had to write MATLAB code to do that (included as lzfd.m).

14 Aug 2013

Fixed bugs as per online comments. Bug in decompressing binary files fixed, as well as dimension transposition. savepcd() now has an option to save binary files.

Contact us