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

 Respuesta aceptada

Andrei Bobrov
Andrei Bobrov el 14 de Oct. de 2012
Editada: Andrei Bobrov el 14 de Oct. de 2012
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 comentarios

Matthew
Matthew el 14 de Oct. de 2012
Thank you very much, that worked!!
Matthew
Matthew el 14 de Oct. de 2012
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"???
Matthew
Matthew el 14 de Oct. de 2012
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.
see ADD in my answer
Matthew
Matthew el 14 de Oct. de 2012
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;
corrected
Matthew
Matthew el 14 de Oct. de 2012
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;
corrected
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).
Matthew
Matthew el 14 de Oct. de 2012
Now I just get a grey image.
Matthew
Matthew el 14 de Oct. de 2012
I tried the second one without the region props and that worked

Iniciar sesión para comentar.

Más respuestas (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 comentarios

Matthew
Matthew el 14 de Oct. de 2012
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);
Matthew
Matthew el 14 de Oct. de 2012
oh sorry, one sec
Matthew
Matthew el 14 de Oct. de 2012
now I get a grey picture for this too.
Image Analyst
Image Analyst el 14 de Oct. de 2012
Editada: Image Analyst el 14 de Oct. de 2012
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.
Matthew
Matthew el 14 de Oct. de 2012
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.
Matthew
Matthew el 14 de Oct. de 2012
that worked
Why do you want to do this somewhat unusual thing anyway?
Matthew
Matthew el 14 de Oct. de 2012
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?
Matthew
Matthew el 15 de Oct. de 2012
That is true. But for my purposes at the moment, i didn't have to worry too much about that.

Iniciar sesión para comentar.

Preguntada:

el 14 de Oct. de 2012

Community Treasure Hunt

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

Start Hunting!

Translated by