How project Velodyne point clouds on image? (KITTI Dataset) - matlab

Here is my code to project Velodyne points into the images:
cam = 2;
frame = 20;
% compute projection matrix velodyne->image plane
R_cam_to_rect = eye(4);
[P, Tr_velo_to_cam, R] = readCalibration('D:/Shared/training/calib/',frame,cam)
R_cam_to_rect(1:3,1:3) = R;
P_velo_to_img = P*R_cam_to_rect*Tr_velo_to_cam;
% load and display image
img = imread(sprintf('D:/Shared/training/image_2/%06d.png',frame));
fig = figure('Position',[20 100 size(img,2) size(img,1)]); axes('Position',[0 0 1 1]);
imshow(img); hold on;
% load velodyne points
fid = fopen(sprintf('D:/Shared/training/velodyne/%06d.bin',frame),'rb');
velo = fread(fid,[4 inf],'single')';
% remove every 5th point for display speed
velo = velo(1:5:end,:);
fclose(fid);
% remove all points behind image plane (approximation
idx = velo(:,1)<5;
velo(idx,:) = [];
% project to image plane (exclude luminance)
velo_img = project(velo(:,1:3),P_velo_to_img);
% plot points
cols = jet;
for i=1:size(velo_img,1)
col_idx = round(64*5/velo(i,1));
plot(velo_img(i,1),velo_img(i,2),'o','LineWidth',4,'MarkerSize',1,'Color',cols(col_idx,:));
where readCalibration function is defined as
function [P, Tr_velo_to_cam, R_cam_to_rect] = readCalibration(calib_dir,img_idx,cam)
% load 3x4 projection matrix
P = dlmread(sprintf('%s/%06d.txt',calib_dir,img_idx),' ',0,1);
Tr_velo_to_cam = P(6,:);
R_cam_to_rect = P(5,1:9);
P = P(cam+1,:);
P = reshape(P ,[4,3])';
Tr_velo_to_cam = reshape(Tr_velo_to_cam ,[3,4])';
R_cam_to_rect = reshape(R_cam_to_rect ,[3,3])';
end
But here is the result:
what is wrong with my code? I changed the "cam" variable from 0 to 3 and none of them worked. You can find a sample of Calibration file in this link:
How to understand KITTI camera calibration files

I fixed it by myself. here is the modification in readCalibration function:
Tr_velo_to_cam = P(6,:);
Tr_velo_to_cam = reshape(Tr_velo_to_cam ,[4,3])';
Tr_velo_to_cam = [Tr_velo_to_cam;0 0 0 1];

Related

How to display a group of subplots as a movie?

I have 30 heatmap subplots. How could I present these subplots as an animation or a movie (i.e. one heatmap each 0.5 seconds)?
The subplots are obtained with the following code:
var = {'GeneX','GeneY','GeneZ'};
syms x y z S
alpha_x = 3.9e-2;
beta_x = 6.1;
z_x = 1.3e-5;
n_zx = 2.32;
alpha_y= 4.3e-2;
beta_y = 5.7;
x_y = 7.9e-4;
n_xy = n_zx;
delta_y = 1.05;
x_z = 12e-2;
n_xz = n_zx;
y_z = 11e-3;
n_yz = n_zx;
delta_z = 0.2;
ACDC_X = (alpha_x+beta_x*S)/(1+S+(z/z_x)^n_zx)-x;
ACDC_Y = (alpha_y+beta_y*S)/(1+S+(x/x_y)^n_xy)-delta_y*y;
ACDC_Z = 1/(1+(x/x_z)^n_xz+(y/y_z)^n_yz)-delta_z*z;
ACDCsys_div = [ ACDC_X, ACDC_Y, ACDC_Z ];
J = jacobian(ACDCsys_div,[x;y;z]);
Jsolnew(x,y,z,S) = [J];
%%Construction of the coordinates as a matrix
A = load('matlab.mat','unnamed');% import data from directory
a2 = struct2array(A);% coordinates of the equilibrium point.
numofGraphs = 80;
bx = length(a2(1,1:numofGraphs));
%% Construction of the heatmaps
figure;
hmapax = ceil(sqrt(bx));
for kk = 1:bx %bnx %All bin windows = iteration
JacACDCnew(:,:,kk) = Jsolnew(a2(1,kk),a2(2,kk),a2(3,kk),a2(4,kk));
ACDC_HmapJnew = double(JacACDCnew(:,:,kk));
subplot(hmapax,hmapax,kk);%
heatmap(var,var,ACDC_HmapJnew,'ColorScaling','log');
S = a2(4,kk);
title(['Jac','s=',num2str(S)]);
end
Consider the following example:
function q56130816
% Load some data:
frames = imread('https://i.stack.imgur.com/03kN8.gif');
frames(frames > 1) = 2;
% Create subplots:
figure('WindowState','maximized'); subplot(2,4,1);
for ind1 = 1:8
subplot(2,4,ind1);
imagesc(frames(:,:,1,ind1)); axis image; axis off;
end
colormap([255 255 255; 188 188 188; 244 128 36]./255);
% Capture subplots as frames:
for ind1 = 8:-1:1
frameHolder(ind1) = getframe( subplot(2, 4 ,ind1) );
end
% Play as movie:
hF = figure(); movie(hF, frameHolder, 20, 2);
Which will turn:
Into:
As you can see, in the example above I used getframe, but frames can also be captured using print, as mentioned in the getframe docs. Frames can also be exported to a video file, as explained here.
Animation credit: frames were screen-captured from Johan Lindell's Codepen example.

how to find the corners of rotated object in matlab?

I want to find the corners of objects.
I tried the following code:
Vstats = regionprops(BW2,'Centroid','MajorAxisLength','MinorAxisLength',...
'Orientation');
u = [Vstats.Centroid];
VcX = u(1:2:end);
VcY = u(2:2:end);
[VcY id] = sort(VcY); % sorting regions by vertical position
VcX = VcX(id);
Vstats = Vstats(id); % permute according sort
Bv = Bv(id);
Vori = [Vstats.Orientation];
VRmaj = [Vstats.MajorAxisLength]/2;
VRmin = [Vstats.MinorAxisLength]/2;
% find corners of vertebrae
figure,imshow(BW2)
hold on
% C = corner(VER);
% plot(C(:,1), C(:,2), 'or');
C = cell(size(Bv));
Anterior = zeros(2*length(C),2);
Posterior = zeros(2*length(C),2);
for i = 1:length(C) % for each region
cx = VcX(i); % centroid coordinates
cy = VcY(i);
bx = Bv{i}(:,2); % edge points coordinates
by = Bv{i}(:,1);
ux = bx-cx; % move to the origin
uy = by-cy;
[t, r] = cart2pol(ux,uy); % translate in polar coodinates
t = t - deg2rad(Vori(i)); % unrotate
for k = 1:4 % find corners (look each quadrant)
fi = t( (t>=(k-3)*pi/2) & (t<=(k-2)*pi/2) );
ri = r( (t>=(k-3)*pi/2) & (t<=(k-2)*pi/2) );
[rp, ip] = max(ri); % find farthest point
tc(k) = fi(ip); % save coordinates
rc(k) = rp;
end
[xc,yc] = pol2cart(tc+1*deg2rad(Vori(i)) ,rc); % de-rotate, translate in cartesian
C{i}(:,1) = xc + cx; % return to previous place
C{i}(:,2) = yc + cy;
plot(C{i}([1,4],1),C{i}([1,4],2),'or',C{i}([2,3],1),C{i}([2,3],2),'og')
% save coordinates :
Anterior([2*i-1,2*i],:) = [C{i}([1,4],1), C{i}([1,4],2)];
Posterior([2*i-1,2*i],:) = [C{i}([2,3],1), C{i}([2,3],2)];
end
My input image is :
I got the following output image
The bottommost object in the image is not detected properly. How can I correct the code? It fails to work for a rotated image.
You can get all the points from the image, and use kmeans clustering and partition the points into 8 groups. Once partition is done, you have the points in and and you can pick what ever the points you want.
rgbImage = imread('your image') ;
%% crop out the unwanted white background from the image
grayImage = min(rgbImage, [], 3);
binaryImage = grayImage < 200;
binaryImage = bwareafilt(binaryImage, 1);
[rows, columns] = find(binaryImage);
row1 = min(rows);
row2 = max(rows);
col1 = min(columns);
col2 = max(columns);
% Crop
croppedImage = rgbImage(row1:row2, col1:col2, :);
I = rgb2gray(croppedImage) ;
%% Get the white regions
[y,x,val] = find(I) ;
%5 use kmeans clustering
[idx,C] = kmeans([x,y],8) ;
%%
figure
imshow(I) ;
hold on
for i = 1:8
xi = x(idx==i) ; yi = y(idx==i) ;
id1=convhull(xi,yi) ;
coor = [xi(id1) yi(id1)] ;
[id,c] = kmeans(coor,4) ;
plot(coor(:,1),coor(:,2),'r','linewidth',3) ;
plot(c(:,1),c(:,2),'*b')
end
Now we are able to capture the regions..the boundary/convex hull points are in hand. You can do what ever math you want with the points.
Did you solve the problem? I Looked into it and it seems that the rotation given by 'regionprops' seems to be off. To fix that I've prepared a quick solution: I've dilated the image to close the gaps, found 4 most distant peaks of each spine, and then validated if a peak is on the left, or on the right of the centerline (that I have obtained by extrapolating form sorted centroids). This method seems to work for this particular problem.
BW2 = rgb2gray(Image);
BW2 = imbinarize(BW2);
%dilate and erode will help to remove extra features of the vertebra
se = strel('disk',4,4);
BW2_dilate = imdilate(BW2,se);
BW2_erode = imerode(BW2_dilate,se);
sb = bwboundaries(BW2_erode);
figure
imshow(BW2)
hold on
centerLine = [];
corners = [];
for bone = 1:length(sb)
x0 = sb{bone}(:,2) - mean(sb{bone}(:,2));
y0 = sb{bone}(:,1) - mean(sb{bone}(:,1));
%save the position of the centroid
centerLine = [centerLine; [mean(sb{bone}(:,1)) mean(sb{bone}(:,2))]];
[th0,rho0] = cart2pol(x0,y0);
%make sure that the indexing starts at the dip, not at the corner
lowest_val = find(rho0==min(rho0));
rho1 = [rho0(lowest_val:end); rho0(1:lowest_val-1)];
th00 = [th0(lowest_val:end); th0(1:lowest_val-1)];
y1 = [y0(lowest_val:end); y0(1:lowest_val-1)];
x1 = [x0(lowest_val:end); x0(1:lowest_val-1)];
%detect corners, using smooth data to remove noise
[pks,locs] = findpeaks(smooth(rho1));
[pksS,idS] = sort(pks,'descend');
%4 most pronounced peaks are where the corners are
edgesFndCx = x1(locs(idS(1:4)));
edgesFndCy = y1(locs(idS(1:4)));
edgesFndCx = edgesFndCx + mean(sb{bone}(:,2));
edgesFndCy = edgesFndCy + mean(sb{bone}(:,1));
corners{bone} = [edgesFndCy edgesFndCx];
end
[~,idCL] = sort(centerLine(:,1),'descend');
centerLine = centerLine(idCL,:);
%extrapolate the spine centerline
yDatExt= 1:size(BW2_erode,1);
extrpLine = interp1(centerLine(:,1),centerLine(:,2),yDatExt,'spline','extrap');
plot(centerLine(:,2),centerLine(:,1),'r')
plot(extrpLine,yDatExt,'r')
%find edges to the left, and to the right of the centerline
for bone = 1:length(corners)
x0 = corners{bone}(:,2);
y0 = corners{bone}(:,1);
for crn = 1:4
xCompare = extrpLine(y0(crn));
if x0(crn) < xCompare
plot(x0(crn),y0(crn),'go','LineWidth',2)
else
plot(x0(crn),y0(crn),'ro','LineWidth',2)
end
end
end
Solution

How to use the new functions of PDE toolbox in image processing (Matlab R2015a)

I want to use the line new command of PDE toolbox as Matlab R2015 to restore a noisy image with gaussian noise.
The PDE is:
∇.(( ∇u)/(√(1+|∇u|2))) +(f2)/(u2) = 1 in Ω (∂u)/(∂n)=0 in ∂Ω
Where f is the noisy image and u the restored image.
I tried the following code:
clear
close all
clc
img = 'AA.jpg';
mInputImage = double(imread(img));
mInputImage = rgb2gray(mInputImage);
[numRows, numCols] = size(mInputImage);
Var = 0.04;
Mean = 0;
mInputImageNoisy = imnoise((mInputImage(:,:,1)),'gaussian',Mean, Var);
% reshape the input and noisy images to vectors
mInputImageVector = reshape(mInputImage,numRows*numCols,1);
mInputImageNoisyVector = reshape(mInputImageNoisy,numRows*numCols,1);
Residu1 = norm(mInputImageVector-mInputImageNoisyVector)/norm(mInputImageVector)
RegularisationCoefficient = 0.7*ones((numRows-1)*(numCols-1),1);
mOutputImageVector = mInputImageNoisyVector;
%a = (mInputImageNoisyVector.^2) ./ mOutputImageVector.^3;
f = 1;
rtol = 1e-1;
c = '1./sqrt(1+ux.^2+uy.^2)';
% Create a PDE Model with a single dependent variable
numberOfPDE = 1;
pdem = createpde(numberOfPDE);
g = #squareg;
geometryFromEdges(pdem,g);
% Plot the geometry and display the edge labels for use in the boundary
% condition definition.
figure;
pdegplot(pdem, 'edgeLabels', 'on');
%axis([0 numRows 0 numCols]);
axis([-2 2 -2 2]);
title 'Geometry With Edge Labels Displayed'
b2 = applyBoundaryCondition(pdem,'Edge',[1 2 3 4], 'u', 0);
[p,e,t] = poimesh(g,numRows, numCols);
numCols
pdemesh(p,e,t);
axis equal
for iter = 1: numRows*numRows,
mOutputImageVector(iter) = pdenonlin(pdem,c,...
(mInputImageNoisyVector(iter).^2) ./ mOutputImageVector(iter).^3,...
f,'tol',rtol);
SaveImageVector(iter) = mOutputImageVector;
end
mOutputImage = reshape(SaveImageVector,numRows,numRows);
mOutputImage = uint8(mOutputImage);
figure()
imshow(mOutputImage)

Running matlab code through a folder

I have the following code for which instead of loading one image at a time, I'd like to run through every image in a folder (the defective folder in this code). I'd like the output to be an array containing the values of 'G' for each of the input images. I'm not too sure how to go about this - so any points appreciated. Many thanks!
%PCA code,
img = imread('C:\users\m7-miller\desktop\250images\defective\inkblob01.png');
img_gray = rgb2gray(img);
img_gray_double = im2double(img_gray);
figure,
set(gcf,'numbertitle','off','name','Grayscale Image'),
imshow(img_gray_double)
%find mean of the image
img_mean = mean(img_gray_double);
[m n] = size(img_gray);
%Make column vector of mean image value
new_mean = repmat(img_mean,m,1);
%Mean corrected image
Corrected_img = img_gray_double - new_mean;
%Covariance matrix of corrected image
cov_img = cov(Corrected_img);
%Eigenvalues of covariance matrix - columns of V are e-vectors,
%diagonals of D e-values
[V, D] = eig(cov_img);
V_T = transpose(V);
Corrected_image_T = transpose(Corrected_img);
FinalData = V_T * Corrected_image_T;
% Image approximation by choosing only a selection of principal components
PCs = 3;
PCs = n - PCs;
Reduced_V = V;
for i = 1:PCs,
Reduced_V(:,1) =[];
end
Y=Reduced_V'* Corrected_image_T;
Compressed_img = Reduced_V*Y;
Compressed_img = Compressed_img' + new_mean;
figure,
set(gcf,'numbertitle','off','name','Compressed Image'),
imshow(Compressed_img)
% End of image compression
% Difference of original image and compressed
S = (img_gray_double - Compressed_img);
figure,
set(gcf,'numbertitle','off','name','Difference'),
imshow(S)
% Sum of the differences
F = sum(S);
G = sum(F)
Are you looking for the dir command?
files = dir('*.png');
for n=1:size(files,1)
filename = files(n).name;
img = imread(filename);
....
G = sum(F);
end

Matlab figure keeps the history of the previous images

I am working on rotating image manually in Matlab. Each time I run my code with a different image the previous images which are rotated are shown in the Figure. I couldn't figure it out. Any help would be appreciable.
The code is here:
[screenshot]
im1 = imread('gradient.jpg');
[h, w, p] = size(im1);
theta = pi/12;
hh = round( h*cos(theta) + w*abs(sin(theta))); %Round to nearest integer
ww = round( w*cos(theta) + h*abs(sin(theta))); %Round to nearest integer
R = [cos(theta) -sin(theta); sin(theta) cos(theta)];
T = [w/2; h/2];
RT = [inv(R) T; 0 0 1];
for z = 1:p
for x = 1:ww
for y = 1:hh
% Using matrix multiplication
i = zeros(3,1);
i = RT*[x-ww/2; y-hh/2; 1];
%% Nearest Neighbour
i = round(i);
if i(1)>0 && i(2)>0 && i(1)<=w && i(2)<=h
im2(y,x,z) = im1(i(2),i(1),z);
end
end
end
end
x=1:ww;
y=1:hh;
[X, Y] = meshgrid(x,y); % Generate X and Y arrays for 3-D plots
orig_pos = [X(:)' ; Y(:)' ; ones(1,numel(X))]; % Number of elements in array or subscripted array expression
orig_pos_2 = [X(:)'-(ww/2) ; Y(:)'-(hh/2) ; ones(1,numel(X))];
new_pos = round(RT*orig_pos_2); % Round to nearest neighbour
% Check if new positions fall from map:
valid_pos = new_pos(1,:)>=1 & new_pos(1,:)<=w & new_pos(2,:)>=1 & new_pos(2,:)<=h;
orig_pos = orig_pos(:,valid_pos);
new_pos = new_pos(:,valid_pos);
siz = size(im1);
siz2 = size(im2);
% Expand the 2D indices to include the third dimension.
ind_orig_pos = sub2ind(siz2,orig_pos(2*ones(p,1),:),orig_pos(ones(p,1),:), (1:p)'*ones(1,length(orig_pos)));
ind_new_pos = sub2ind(siz, new_pos(2*ones(p,1),:), new_pos(ones(p,1),:), (1:p)'*ones(1,length(new_pos)));
im2(ind_orig_pos) = im1(ind_new_pos);
imshow(im2);
There is a problem with the initialization of im2, or rather, the lack of it. im2 is created in the section shown below:
if i(1)>0 && i(2)>0 && i(1)<=w && i(2)<=h
im2(y,x,z) = im1(i(2),i(1),z);
end
If im2 exists before this code is run and its width or height is larger than the image you are generating the new image will only overwrite the top left corner of your existing im2. Try initializing im2 by adding adding
im2 = zeros(hh, ww, p);
before
for z = 1:p
for x = 1:ww
for y = 1:hh
...
As a bonus it might make your code a little faster since Matlab won't have to resize im2 as it grows in the loop.