Removing Short Runs from Binary Data
1 Ansicht (letzte 30 Tage)
Ältere Kommentare anzeigen
Jim McIntyre
am 19 Feb. 2020
Bearbeitet: Image Analyst
am 20 Feb. 2020
I have a large string of binary data of the form:
A = [0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0]
Within the data, if I have a group of 0s with an occasional 1, I want to convert that 1 to a zero. Similarly for a group of 1s with an occasional 0.
As a rule, I want to reset runs of 1s or 0s that are shorter than 3 consecutive values in length to the value of the surrounding elements.
So 0,0,0,1,0,0,0 would become 0,0,0,0,0,0,0
I'd also like to convert something like 1,1,1,0,0,1,0,1,1 to all 1s.
Any suggestions on how to do this? Thanks in advance.
2 Kommentare
Jacob Wood
am 19 Feb. 2020
How important is speed here? Would you prefer a readable for-loop solution or a one-liner?
Guillaume
am 19 Feb. 2020
Jim McIntyre's comment mistakenly posted as an answer moved here:
Obviously a one-liner would be better, but a for-loop solution is probably okay.
Akzeptierte Antwort
Image Analyst
am 19 Feb. 2020
Bearbeitet: Image Analyst
am 20 Feb. 2020
There is a built-in function for this, if you have the Image Processing Toolbox. Two functions actually. You can use bwareafilt() or bwareaopen(). Try it.
[EDIT]: OK, here is the code:
A = [0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0]
% Case 1: Get rid of stretches of 1's shorter than 3.
A2 = bwareaopen(A, 3)
% Case 2: Get rid of stretches of 0's shorter than 3.
A = [1,1,1,0,0,1,0,1,1]
A3 = ~bwareaopen(~A, 3)
For Case 3: Both cases: get rid of stretches of 1's shorter than 3 AND runs of 0's shorter than 3, it depends on the order in which you do the operations. For example, what does [1, 1, 0, 1, 1 , 0, 0, 1, 1] become? All 1's or all zeros?
0 Kommentare
Weitere Antworten (2)
Guillaume
am 19 Feb. 2020
The desired one-liner:
%demo data
A = [1 1 1 0 0 1 1 1 1 0 0 0 0 1 1 0 0 0 1 0 0 0]
%should result in
% [1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0]
double(regexprep(char(A), '(.)((??@char(1-$1)){1,2})\1', '$1${char(1-$2)}$1')) %replace a run of one to twp 0 or 1 surrounded by the opposite by a run of the opposite
However, note that behaviour may not be as you expect when you've got consecutive runs of 0s and 1s both less than 3 characters, as in your 2nd example [1,1,1,0,0,1,0,1,1]. Why is it the 0s that are replaced by 1s rather than the single 1 replaced by a 0?
Jacob Wood
am 19 Feb. 2020
I've got a silly one-liner:
A = [0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0];
A_converted = replace(sprintf('%d', A),{'010','0110','01110','101','1001','10001'},{'000','0000','00000','111','1111','11111'}) - '0';
1 Kommentar
Guillaume
am 19 Feb. 2020
Bearbeitet: Guillaume
am 19 Feb. 2020
You could just do char(A + '0') to construct the char vector instead of using sprintf.
This is arguably clearer than my regexprep solution. However, the regexprep expression can easily be extended to any arbitrary length of runs (simply replace the 2 in {1, 2} by whatever max run length is desired) whereas the replace would get a bit unwieldy.
Siehe auch
Kategorien
Mehr zu Get Started with MATLAB finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!