Searching a matrix for duration value and replacing else

I have a 1600 X 821 matrix that is full of 1 and 0's that makes a binary image. I am trying to make a statement that will cycle through each column and find a series of 0's d (duration) long and then replace all other 0's in the column with 1's regardless of if there are more series of 20 zeroes later and move on to the next column. What I have doesn't work, but here's what I have so far.
k=0;
while (1+k:d+k);
if matrix(1+k:d+k);
else matrix(1+k)= 1;
end
k=k+1;
end
Thanks

 Accepted Answer

use function regionprops from Image Processing Toolbox
a - your array with size < 1600 x 821 >
out = ones(size(a))
for jj = 1:size(a,2)
s = regionprops(~a(:,jj),'Area','PixelIdxList');
out(s(find([s.Area] >= 20,1,'first')).PixelIdxList,jj) = 0;
end
or without Image Processing Toolbox
n = 20;
out = ones(size(a));
t = conv2(0+~a,ones(n,1),'same') == n;
q = fix(n/2);
ii = bsxfun(@plus,find(cumsum([false(1,size(a,2));diff(t)~=0]) == 1),-q+~rem(n,2):q);
out(ii) = 0;
ADD
n = 20;
out = ones(size(a));
for jj = 1:size(a,2)
s = regionprops(~a(:,jj),'Area','PixelIdxList');
ii = [s(find([s.Area] >= n,1,'first')).PixelIdxList];
if ~isempty(ii), out(ii(1),jj) = 0; end
end
or
n = 20;
out = ones(size(a));
t = conv2(0+~a,ones(n,1),'same') == n;
[ii,jj] = find(t);
[i00,i0] = unique(jj,'first');
out(sub2ind(size(a),ii(i0),i00) -fix(n/2)+~rem(n,2) ) = 0;

13 Comments

Thank you very much, that worked!!
Now if I wanted to also take that 20 long sample and pick just the first one, how would I do that?
in part my answer with regionprops:
out(s(find([s.Area] == 20,1,'first')).PixelIdxList,jj) = 0;
Matthew, I'm not sure what you mean. You have the 20 long sample - ok fine - but what does "pick just the first one" mean? The first what in the "20 long sample"? The first pixel in that "20 long sample"???
I meant, I have the 20 long sample, and I want to keep the first one a "0" and make the rest "1". So now I would have a single 0 in each coloumn. Sorry about the vagueness.
ALright, so now when I try the ADD part I get this error.
??? Too many outputs requested. Most likely cause is missing [] around left hand side that has a comma separated list expansion.
Error in ==> at 67 ii = s(find([s.Area] == n,1,'first')).PixelIdxList;
Sorry, now I get this error message.
??? Attempted to access ii(1); index out of bounds because numel(ii)=0.
Error in ==> at 68 TWTT_200(ii(1),jj) = 0;
Matthew, seems like an odd thing to want to do, but anyway, see the code in my answer which will do that. It makes a binary (logical) image all 1 (true) except at the pixel of the first row in each column that starts off a stretch of 20 or more 0's (false's).
Now I just get a grey image.
I tried the second one without the region props and that worked

Sign in to comment.

More Answers (1)

Matthew, try this:
clc;
format compact
%==============================================
% Make sample data.
% Make a 100 row by 4 columns image
binaryImage = true(100, 4);
% Place 30 random zeros around in it.
randomLocations = randperm(numel(binaryImage));
binaryImage(randomLocations(1:30)) = false;
% Put 2 stretches of zeros at least 20 long in each column
binaryImage(3:22, 1) = false;
binaryImage(33:62, 1) = false;
binaryImage(13:33, 2) = false;
binaryImage(73:92, 2) = false;
binaryImage(23:52, 3) = false;
binaryImage(63:86, 3) = false;
binaryImage(43:74, 4) = false;
binaryImage(81:100, 4) = false;
% Display it in the command window:
binaryImage
% Create an output image
output = true(size(binaryImage))
%=======================================
% Now, finally, we have our sample data and we can begin.
for column = 1 : size(binaryImage, 2)
% Find the zeros.
% This is a map that is true where there is a 0 (false)
zeroLocations = ~binaryImage(:, column);
% Get rid of stretches 19 or less
zeroLocations = bwareaopen(zeroLocations, 20);
% Find the first zero of the first 20+ long stretch
% of zeros in this column.
firstZeroRow = find(zeroLocations, 1, 'first')
% Set that one single pixel to 0 in the output image.
output(firstZeroRow, column);
end
% Display it in the command window:
output
% It will be all true (1's) except for pixel 3, 13, 23, and 43
% in columns 1, 2, 3, and 4 respectively.

11 Comments

I get this message from this code.
??? Undefined function or method 'output' for input arguments of type 'double'.
Error in ==> at 74 output(firstZeroRow, column);
now I get a grey picture for this too.
You didn't copy and paste my code - I know that much. You'd have to show your modifications for me to know how you broke it. For example, you're not using a true binary (logical) image but instead are using your own image which is of type double.
You're right, it's not a binary image, it's an 8-bit image and I ran it through a threshold function to turn all values into 1's and 0's and then inverted the image.
OK, let me change my code to reflect your non-binary image. It is below:
clc;
format compact
%==============================================
% Make sample data.
% Make a 100 row by 4 columns image
binaryImage = ones(100, 4, 'uint8');
% Place 30 random zeros around in it.
randomLocations = randperm(numel(binaryImage));
binaryImage(randomLocations(1:30)) = 0;
% Put 2 stretches of zeros at least 20 long in each column
binaryImage(3:22, 1) = 0;
binaryImage(33:62, 1) = 0;
binaryImage(13:33, 2) = 0;
binaryImage(73:92, 2) = 0;
binaryImage(23:52, 3) = 0;
binaryImage(63:86, 3) = 0;
binaryImage(43:74, 4) = 0;
binaryImage(81:100, 4) = 0;
% Display it in the command window:
binaryImage
% Create an output image
output = ones(size(binaryImage), 'uint8')
%=======================================
% Now, finally, we have our sample data and we can begin.
for column = 1 : size(binaryImage, 2)
% Find the zeros.
% This is a map that is 1 where there is a 0
zeroLocations = ~binaryImage(:, column);
% Get rid of stretches 19 or less
zeroLocations = bwareaopen(zeroLocations, 20);
% Find the first zero of the first 20+ long stretch
% of zeros in this column.
firstZeroRow = find(zeroLocations, 1, 'first')
% Set that one single pixel to 0 in the output image.
output(firstZeroRow, column) = 0;
end
% Display it in the command window:
output
% It will be all 1's except for pixel 3, 13, 23, and 43
% in columns 1, 2, 3, and 4 respectively.
Why do you want to do this somewhat unusual thing anyway?
My "image" was from a sonar. So the "line" I was making was a 2D picture of the ocean floor while trying to get rid of all the noise.
Do you think it could be even better by using the fact that adjacent columns may be correlated?
That is true. But for my purposes at the moment, i didn't have to worry too much about that.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!