Splitting a binary image into 2 parts

조회 수: 1 (최근 30일)
Ankit Sahay
Ankit Sahay 2020년 9월 14일
댓글: Ankit Sahay 2020년 9월 20일
HI everybody! I have a binary image matrix uploaded as A.mat:
White pixels correspond to 1, black regions correspond to 0. I would like to split the curve into left and right parts, something like the following:
and
Initially, I thought of finding the indices of midponts of elements having 1 at their positions, at each row. Using the indices, I can substitute ones on the left (and right) of the midpoints (at each row) using relational operators. Maybe there might be a better way to do this, but this method comes to my mind right now.
So I start from the bottommost row, and I keep on moving upwards. As evident from the A.mat figure (first figure), a row can have more than 2 cells having values one. To choose the appropriate cells for calculating midpoints at row "r", I compare the number of elements having one on left and right side of midpoint at row "r+1". I am attaching the code below:
clc;
clearvars;
load('A.mat');
[m,n] = size(A);
midpoint = zeros(m,n);
midpt_idx = zeros(m,1);
%%
A_sep = A;
for r = m:-1:1
k = find(A(r,:));
if size(k,2)==2
midpt_idx(r) = ceil((k(1)+k(2))*0.5);
elseif sum(A(r,1:midpt_idx(r+1))) < sum(A(r,midpt_idx(r+1)+1:end))
midpt_idx(r) = ceil((k(1)+k(2))/2);
elseif sum(A(r,1:midpt_idx(r+1))) > sum(A(r,midpt_idx(r+1)+1:end))
midpt_idx(r) = ceil((k(end-1)+k(end))/2);
elseif sum(A(r,1:midpt_idx(r+1))) == sum(A(r,midpt_idx(r+1)+1:end))
midpt_idx(r) = ceil((k(size(k,2)/2)+k((size(k,2)/2)+1))*0.5);
end
A_sep(r,midpt_idx(r)) = 2; % Midpoints have value 2 in their cells, I change this to 1 for checking solution by using imshow(A_sep)
end
An error is dispayed when execution comes at row 64. There is only one cell having 1 in row 64. For now, this error can be ignored (I think!).
This code runs correctly for some parts, but fails at other parts:
If you run the code along with A.mat file, starting from row 416, it gives correct results till row 278. At row 277, the code fails because there are a larger number of points adjacent to each other on right side, compared to left side of the midpoint index at row 279.
So, basically my method fails in these situations. Can you please help me with this? Maybe an advice for my code, or some other method which is better than what I am doing right now.
Thanks!

채택된 답변

Matt J
Matt J 2020년 9월 14일
편집: Matt J 2020년 9월 14일
There is a small break in the curve which I assumed was supposed to indicate the desired dividing point between the right and left sides.
Under that assumption, I propose the following:
load A
[I,J]=find(A);
B=[I,J];
[b,j]=sortrows(B,[+1,-2]);
j=j(end);
C=regionprops(A,'PixelList');
for i=1:numel(C)
if ismember(flip(B(j,:)),C(i).PixelList,'rows')
C=fliplr(C(i).PixelList); break
end
end
Left=accumarray(C,1,size(A)); %the resultant images
Right=A&~Left;
  댓글 수: 4
Matt J
Matt J 2020년 9월 19일
편집: Matt J 2020년 9월 19일
I used your code for my data, and it worked perfectly except for a few cases. I am attaching a screenshot of a case where things go wrong:
I'm not sure how it could have "worked perfectly", if you say the dividing point is supposed to be the "highest point". My code definitely doesn't give that, even in the first data set that you presented to us.
The reason my code is confounded is that your curves are not fully connected. They have multiple breaks which, as you have now updated us, do not represent the desired breaking point between "left" and "right". If you can find a way to seal the breaks between the connected pixels (except for the breaks where you want the left/right division to occur), then my code should work fine for you.
If you cannot seal the breaks, then your problem is simply ill-defined. There is no way to unambiguously define "left" and "right", if your curve has 3 or more disconnected parts. Imagine, for example, if you had the simple 10x10 image below. To which side do the ones in the 5th column belong? I could argue they could be assigned either to the left or right section.
A =
0 0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 1 0 1 0 1 1 0 0
0 0 1 0 1 0 0 1 0 0
0 0 1 0 0 0 0 1 0 0
0 0 1 0 0 0 0 1 0 0
0 0 1 0 0 0 0 1 0 0
0 0 1 0 0 0 0 1 0 0
0 0 1 0 0 0 0 1 0 0
0 0 1 0 0 0 0 1 0 0
Ankit Sahay
Ankit Sahay 2020년 9월 19일
Yeah, I get it now. I did not anticipate such a situation when I started the analysis. It is only after analysing a few more data did I come across a situation where the code failed. Let me reformulate the question such that no ambiguities arise I will take help from the 10X10 matrix that you have provided. Thanks for your input.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Image Analyst
Image Analyst 2020년 9월 19일
Why not simply scan your image column by column with find() finding the topmost and bottommost row?
  댓글 수: 11
Image Analyst
Image Analyst 2020년 9월 20일
No it doesn't. It's not a complete program. It gives this:
>> flame_edge_code
Unrecognized function or variable 'fb2'.
Error in flame_edge_code (line 2)
fb2_l = fb2(:,1:end/2);
Please delay us (and you) no longer and give us a program that runs.
Ankit Sahay
Ankit Sahay 2020년 9월 20일
I apologize profusely for this mistake. I should have been more careful. I have attached the complete program along with the .mat file that the programs needs to run. Again, I am really sorry for wasting your time.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Images에 대해 자세히 알아보기

제품


릴리스

R2019a

Community Treasure Hunt

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

Start Hunting!

Translated by