Time-optimization? Digital image processing

1 view (last 30 days)
Hello,
For each column of the mask, I calculate the first non-zero pixel position (2000 images). Then, I save them to an array and compute the maximum; between other simple operations.
It is working fine, but it is not at all time-efficient. Would you have any suggestion?
Thank you very much,
Best regards,
Santiago
Base= Mask;
i=1;
b= zeros (y,1,num_images,'double'); %preallocating
rows= x;
columns= y;
for k= 1:num_images;
for col= 1: columns
a = find(D(:, col,k), 1, 'first'); %find the first non-zero pixel
if a > 0
b(i,k) = a;
c = max (b(:,k));
i= i+1;
else
continue
end
end
Base(c:rows,:,k)=1; %keeping the top part
end

Accepted Answer

Walter Roberson
Walter Roberson on 3 Jan 2017
The vectorized method of finding the first non-zero pixel for each column is:
leading_zero_count = sum( cumprod( ~D ) );
This will do the operation for all columns for all images simultaneously. The output will be 1 x number_of_columns x number_of_images
This is the count of the number of leading zeros, which is not exactly the same as the location of the first non-zero pixel. For any column that has a non-zero pixel, the leading zero count will be 1 less than the position of the first non-zero pixel. For any column that does not have any non-zero pixels, the leading zero count will be the same as the number of rows, which is a non-empty value, where-as the result of find() for such a case would be [] (the empty vector). A leading zero count can be easier to work with:
D(leading_zero_count(1,J,K)+1:end, J, K)
is easy to code without having to test for the [] that find() can return.
  2 Comments
Santi
Santi on 3 Jan 2017
Dear Walter Roberson,
Your approach works fine (just in few seconds) and of course I accept your answer.
However, I do not fully understand how the sum of the cumulative product acts in a logical matrix (in my opinion, the cumulative product of 0*1= 0). If posible, could you please elaborate on that very briefly? Thank you very much for your help!
Regards
Base= D;
rows= x;
leading_zero_count = sum( cumprod( ~D ) );
leading_zero_count(leading_zero_count==rows)=0;
leading_zero_count=leading_zero_count+1;
a= zeros (1,num_images); %preallocating
tic;
for k= 1:num_images;
a(:,k)= max (leading_zero_count(:,:,k));
Base(a(k):rows,:,k)=1; %keeping the top part
end
disp(['Elapsed time (topLine) = ',num2str(toc),' seconds']);
figure, imshow3D (Base);
Santi
Santi on 3 Jan 2017
Silly question.... thank you very much!

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 3 Jan 2017
Edited: Image Analyst on 3 Jan 2017
It looks like you're finding the lowest of the top-most pixels in each image and then setting Base array from that row downwards to 1. Well you don't have to do that setting of the Base matrix for each and every column. It can be done once, after the col loop ends. Inifialize c to -inf inside the k loop but before the col loop starts.
c = -inf;
Then set c like this:
c = max ([c ; b(:,k))];
Also, you should use
if ~isempty(a)
rather than
if a > 0

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!