Matlab provides a great environment to work with images and therefore a great place to develop the Structured Light Algorithm.  The beagle board was used to project the structured light images and capture the resulting scene.  These images were then loaded into matlab providing data needed to develop the algorithm.  Working with Hana Wang and Rajoshi Biswas, the majority of the algorithm was developed as follows:

At this point we were able to create decent point clouds with matlab.  The resulting pointclouds can be shown in matlab using the ‘mesh’ function.  To add color us the ‘caxis’ function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
%% Total number of Images n = 20 %%
n = 18;
height = 480;
width = 640;
%scan = zeros(height, width, 3, n);
figure;

l=[1,3,5,7,9,11,13,15,17,19];       %% Two sequences, l and r
r=[2,4,6,8,10,12,14,16,18,20];
binProjCol = zeros(height,width,9);
bright = zeros(height,width,9);
projCol = zeros(height,width);
projColNormalized = zeros(height,width);
dright = zeros(height,width);
camCol = zeros (height, width);
camColNormalized = zeros (height, width);
%y = zeros (height, width);
depth = zeros (height, width);
%% Read the images obtained by scanning %%
for i = 1 : n
    scan(:,:,:,i) = imread(strcat([num2str(i) '.png']));
    imshow(scan(:,:,:,i));
    %pause;
end

display('Images read')

%% To decode bit sequence %%
%grayscan = zeros(height,width,n);
grayProjCol = zeros(height,width,n);
binary = zeros(height,width);

fid = fopen('pointcloud_Steven.xyz','w');
%% Convert from rgb2gray
for i=1:n
    %grayscan(:,:,i)= mat2gray(scan(:,:,:,i)); % used to verify sl patterns
    grayscan(:,:,i)= rgb2gray(scan(:,:,:,i)); %grayscan is a double
    imshow(grayscan(:,:,i));
    %    pause;
end

%% Extract bitsequence, find column number and the final coordinates
for k = 1 : height
    for j = 1: width
        %% To extract bitsequence from the images
        for i=1:(n/2)
            if abs(grayscan(k,j,l(i))-grayscan(k,j,r(i))>50)
                if grayscan(k,j,l(i)) > grayscan(k,j,r(i))
                    grayProjCol(k,j,l(i))=1;
                    %grayProjCol(k,j,r(i))=0;
                else
                    grayProjCol(k,j,l(i))=0;
                    %grayProjCol(k,j,r(i))=1;
                end
            end
        end
    end
end
for i=1:n
    imshow(grayProjCol(:,:,i));
    %pause;
end
disp('bitsequence extracted');
%% Convert the gray code sequence to decimal number = column number

for k = 1 : height
    for j = 1: width
        binProjCol(k,j,1) = grayProjCol(k,j,l(1));
        projCol(k,j) = binProjCol(k,j,1)*2^((n/2)-1);
        for i = 2 :(n/2)
            binProjCol(k,j,i) = xor(grayProjCol(k,j,l(i)), binProjCol(k,j,i-1) );
            projCol(k,j) = projCol(k,j) + ((2^((n/2)-i))*(binProjCol(k,j,i)));
        end
    end
end

tempMax = 0;
tempMin = 2^(n/2);
projColMean = mean(projCol);
for k = 1 : height
    for j = 1: width
        if(projCol(k,j)>projColMean(j)+150)
            projCol(k,j) = NaN;
        elseif (projCol(k,j)> tempMax)
            tempMax = projCol(k,j);
        end
        if(projCol(k,j)<projcolmean (j)-20)
            projCol(k,j) = NaN;
        elseif (projCol(k,j)< tempMin)
            tempMin = projCol(k,j);
        end
    end
end

       
[r,firstCamCol,z] = find(projCol,1,'first');
[r,lastCamCol,z] = find(projCol,1,'last');
[r,c,projColList] = find(projCol);
numOfCamCol = lastCamCol-firstCamCol;
firstProjCol = min(projColList);
lastProjCol = max(projColList);
numOfProjCol = lastProjCol - firstProjCol;


for k = 1 : height
    for j = 1: width

        %y(k,j) = k;
        if (projCol(k,j) ~= NaN)
           
            %% Calculate the coordinates of the point
            projColNormalized(k,j) = (projCol(k,j)-(firstProjCol-1))/(numOfProjCol); %480
            camColNormalized(k,j) = ((j-(firstCamCol-1))/numOfCamCol); %width
           
            if ( abs(((camColNormalized(k,j)- projColNormalized(k,j))))&lt;0.10)
                depth(k,j) = (camColNormalized(k,j)-projColNormalized(k,j));
                %depth(k,j) = ((projColNormalized(k,j)-(camColNormalized(k,j))));
            end
        else
            depth(k,j) = NaN;
        end
        fprintf(fid,'%4.1f %4.1f %4.9f %d \r\n',j,k,depth(k,j),projCol(k,j));
    end
end

The code above works but notice it does not handle cleaning up any erroneous points where no Structured Light is found (fuzzy black and white areas).   This was implemented after the code was ported to C.  Since the noise has a gaussian distribution it can be filtered out using a gaussian filter.

1
2
3
4
5
6
7
8
9
disp('Calculated depth');
zInv = flipud(depth);
H2 = fspecial('gaussian',5,.6);
zInvFilt = imfilter(zInv,H2);

figure;
mesh(zInvFilt);
caxis ([0.001 0.013]);
%caxis ([-0.007 0.0125])

This cleans up the noise and provides good results.  The video below shows a better representation of the 3D model.  The noise has been greatly reduced in the blue area where no SL patterns were projected. There are a few areas that were not the best surfaces to reflect the projected light such as the glossy surface that is close to being parallel with the camera.

<–Previous     Project Home     Next –>


Be Sociable, Share!