Reputation: 777
In MATLAB, there is the bwlabel
function, that given a binary vector, for instance x=[1 1 0 0 0 1 1 0 0 1 1 1 0]
gives (bwlabel(x)
):
[1 1 0 0 0 2 2 0 0 3 3 3 0]
but what I want to obtain is
[1 1 2 2 2 3 3 4 4 5 5 5 6]
I know I can negate x
to obtain (bwlabel(~x)
)
[0 0 1 1 1 0 0 2 2 0 0 0 3]
But how can I combine them?
Upvotes: 2
Views: 146
Reputation: 777
I found this function that does exactly what i wanted:
https://github.com/davidstutz/matlab-multi-label-connected-components
So, clone the repository and compile in matlab using mex
:
mex sp_fast_connected_relabel.cpp
Then,
labels = sp_fast_connected_relabel(x);
Upvotes: -1
Reputation: 125854
You can still do it using bwlabel
by vertically concatenating x
and ~x
, using 4-connected components for the labeling, then taking the maximum down each column:
>> max(bwlabel([x; ~x], 4))
ans =
1 1 2 2 2 3 3 4 4 5 5 5 6
However, the solution from Bentoy13 is probably a bit faster.
Upvotes: 3
Reputation: 18177
x=[1 1 0 0 0 1 1 0 0 1 1 1 0];
A = bwlabel(x);
B = bwlabel(~x);
if x(1)==1
tmp = A>0;
A(tmp) = 2*A(tmp)-1;
tmp = B>0;
B(tmp) = 2*B(tmp);
C = A+B
elseif x(1)==0
tmp = A>0;
A(tmp) = 2*A(tmp);
tmp = B>1;
B(tmp) = 2*B(tmp)-1;
C = A+B
end
C =
1 1 2 2 2 3 3 4 4 5 5 5 6
You know the first index should remain 1
, but the second index should go from 1
to 2
, the third from 2
to 3
etc; thus even indices should be doubled and odd indices should double minus one. This is given by A+A-1
for odd entries, and B+B
for even entries. So a simple check for whether A
or B
contains the even points is sufficient, and then simply add the two arrays.
Upvotes: 1
Reputation: 4956
All in one line:
y = cumsum([1,abs(diff(x))])
Namely, abs(diff(x))
spots changes in the binary vector, and you gain the output with the cumulative sum.
Upvotes: 6