How can I speed this up (it takes days to run currently)?
Show older comments
I have a piece of code that I wrote that takes a 3D matrix containing imaging data of brain vessels and uses region growing starting at a user-defined seed. However it takes to long. I'm sure there's a way to speed this up as some pixels are reprocessed (found in the queue) multiple times. Also I think it's taking to long to process the pixels (my image contains approx. 1.6E7 pixels) however only a small percentage of them are "of interest", i.e. those that are at the minimum should be excluded from the computation as the probability that they belong to the volume of interest is 0%. Following is the code:
clc; clear all; close all;
load('Jmatrix.mat'); %this file contains a 3D matrix with the grayscale vessel slices (from DICOM).
dcmmov = implay(J); %allows the user to scan the images in order to select the slice containing the aneurysm.
waitfor(dcmmov); %waits for the user to close the image scanner (movie) above.
prompt = {'Enter slice number:'};
dlg_title = 'Slice Selection';
num_lines = 1;
slice = inputdlg(prompt,dlg_title,num_lines); %user inputs slice of interest for seeding.
z = str2double(slice{1});
imshow(J(:,:,z)); %shows the slice of interst
[y,x] = ginput; %permits the user to seed a point within the aneurysm to start the growing from.
% seed = [x,y];
% seed = [165,85];
x = round(x); %makes sure the co-ordinates are integers
y = round(y);
[h, w, d] = size(J); %gets the dimensions of the original image matrix.
V = zeros(w,h,d); %creates a prealocated matrix of the same size as the original (will be binary).
V(x,y,z)= 1; %assigns a 1 (i.e. true) to the seed pixel
error = .10; %current error threshold to be used when compairing neighbouring pixels.
queue = [x, y, z]; %creates the que for the pixels to be analysed.
bar = waitbar(0,'Segmenting image. Please wait...'); %starts a progress bar.
while size(queue, 1)
voxelx = queue(1,1); %indicate co-ordinates of the next pixel (voxel) in the queue.
voxely = queue(1,2);
voxelz = queue(1,3);
S = double(J(voxelx, voxely, voxelz)); %this is the pixel value to be compared with neighbours (originally the seed).
queue(1,:) = []; %deletes the queue
for i = -1:1
for j = -1:1
for k = -1:1
if J(voxelx+i,voxely+j,voxelz+k) == 1; %skips to the next text pixel if the value of this pixel is already 1 (removes redundancy).
V(voxelx+i,voxely+j,voxelz+k)=1;
elseif J(voxelx+i,voxely+j,voxelz+k) == 0; %skips to the next text pixel if the value of this pixel is already 1 (removes redundancy).
V(voxelx+i,voxely+j,voxelz+k)=1;
else
T = double(J(voxelx+i, voxely+j,voxelz+k)); %defines the neighbouring pixel to be tested.
if abs(T - S)/S < error %this is the formula that determines if the tested pixel is sufficiently similar (within an error threshold) to the comparison pixel S.
V(voxelx+i,voxely+j,voxelz+k) = 1; %if sufficiently similar assigns a 1 (i.e. true).
end
end
queue(end+1,:) = [voxelx+i, voxely+j,voxelz+k]; %adds the next pixel to the queue.
sizeq = size(queue); %these lines allow monitoring of the process
waitbar(sizeq(1) / (w*h*d));
pixel = [voxelx+i,voxely+j,voxelz+k];
value = V(voxelx+i,voxely+j,voxelz+k);
[sizeq(1) pixel value]
end
end
end
end
close(bar);
implay(V); %permits viewing of the final segmented volume.
end
Thanks, Daniel
3 Comments
It doesn't look like there's any way that your queue can empty. In one line you delete a voxel
queue(1,:) = []; %deletes the queue
but then later, in your triple for-loop, you re-include the same voxel plus 26 more in
queue(end+1,:) = [voxelx+i, voxely+j,voxelz+k];
Aside from that, when you say that there are some voxels that are not of interest, you should expect that only you (not us) are going to know which voxels those are.
Daniel
on 20 Oct 2012
I am not quite sure what you mean by saying that only I know which voxels are of interest.
I meant, "how would we know better than you"? Where in your code do you specify the thresholding criteria that determines whether a particular voxel belongs to a vessel?
It sort of looks like this is the criterion
abs(T - S)/S < error
but then why do you also set V=1 when J=1 and also V=1 when J=0?
And why do you always add the currently examined voxel to the queue regardless of what's inside it?
queue(end+1,:) = [voxelx+i, voxely+j,voxelz+k]; %adds the next pixel to the queue.
Accepted Answer
More Answers (1)
Image Analyst
on 19 Oct 2012
0 votes
The things that strikes me right ott the bat is that your indexes are in the reverse order. MATLAB is in "column major order". so that it goes down rows in a column before it moves over to the next column. So in imageArray(row, column) the left-most index, row, varies fastest and the rightmost one varies slowest. You have your loops in the opposite order so that is going to make it the most memory inefficient that it can be. Try putting your "i" loop inner-most and your k loop outer-most. Time it and see if it's faster. I bet it will be.
Categories
Find more on Image Processing Toolbox in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!