Dear all,
I have an image like the one attached. I have it in binary format.
How do I complete the white lines so the first lines crosses x=0 point, and the remaining lines are finished until they cross each other?
This script should be flexible enough so the number of lines may change (more gaps) and they don't necessarily are lines. They may also be curves.
Here is another example where there are more gaps in data.
Thank you for your help!

5 Comments

Are you want to link those white lines?
Yes, I want to connect these lines
I want that there is continuous white line from x=0 point till the last x value = over the entire graph
Mateusz Matysiak's comment moved here:
The lines should look like below. Initially I was looking into creating multiple linear fit lines. Then, I create the complete lines based on the fits and cross points between the fits.
The picture below shows how it should look like. I finished the lines by hand. The script should do the same.
Matt J
Matt J on 20 Sep 2019
Edited: Matt J on 20 Sep 2019
This script should be flexible enough so the number of lines may change (more gaps) and they don't necessarily are lines. They may also be curves.
You mentioned here that the pieces might be curved (not lines) and so naive line-fitting wouldn't work. Please show an example of this more complicated case and how you want the curves extended.

Sign in to comment.

 Accepted Answer

Matt J
Matt J on 18 Sep 2019
Edited: Matt J on 18 Sep 2019
Here is another method based on interpolation, and faster than dilating with large strels.
[m,n]=size(A);
[I,J]=find(bwskel(A));
IJ=sortrows([I,J],2);
[I,J]=deal(IJ(:,1),IJ(:,2));
Jw=(J(1):J(end)).';
Iw=round(interp1(J,I,Jw));
B=imdilate( accumarray([Iw,Jw],1,[m,n]) , strel('sphere',1));
imshow(B)

6 Comments

Matt
Using your last suggestion I get the error
Error using griddedInterpolant
The grid vectors must contain unique points.
Error in interp1 (line 151)
F = griddedInterpolant(X,V,method);
Try this,
[m,n]=size(A);
[I,J]=find(bwskel(A));
[J,idx]=unique(J);
I=I(idx);
Jw=(J(1):J(end)).';
Iw=round(interp1(J,I,Jw));
B=imdilate( accumarray([Iw,Jw],1,[m,n]) , strel('sphere',1));
imshow(B)
I think I prefer your first suggestion even slower. This one I tried, and although it is faster indeed but I loose substantial information of my image.
Here's a 3rd iteration of the interpolation based method (Method 2).
[m,n]=size(A);
[I,J]=find(A);
[G,J]=findgroups(J);
I=splitapply(@median, I,G);
Jw=(J(1):J(end)).';
Iw=round(interp1(J,I,Jw));
B=imdilate( accumarray([Iw,Jw],1,[m,n]) , strel('sphere',1));
When I test this on lines2.mat, I get a much better completion than my original slower method.
Method 1:
image1.png
Method 2:
image2.png
Still I struggle to get the correct results. Though I will stick to your first suggestion that works very good for me. Thanks Matt.
You are welcome, but please Accept-click an answer if you have found one that works for you.

Sign in to comment.

More Answers (2)

Perhaps as follows,
gapsize=36;
A=imcrop(rgb2gray(imread('image.png')));
B=(imdilate(A,strel('sphere',ceil(gapsize/2)))>0);
C=imdilate(bwskel(B),strel('sphere',1))|A;
imshow(C)
Capture.PNG

12 Comments

+1 Nice one sir
I use exactly the same example but it stucks on running and I needed to pause it. Do you know if this take a lot of time to compute?
Matt J
Matt J on 17 Sep 2019
Edited: Matt J on 17 Sep 2019
I'm guessing imcrop is wating for you to drag a cropping window across the image.
I'm not using the imcrop line. I use those lines
x = imread('1pp.bmp');
>> gapsize=36;
B=(imdilate(x,strel('sphere',ceil(gapsize/2)))>0);
C=imdilate(bwskel(B),strel('sphere',1))|x;
imshow(C)
But it stucks and still I have to shut it down
It just stopped, providing a very nice result. However, the big gap in my curve still exist, although smaller gaps were filled and connected. The bigger the gapsize I will assign, the bigger gaps will be connected?
Yes.
Yes it's perfect. Thanks a ton Matt. It is exactly what I needed. Although it takes more than 2 minutes in my case and I don't know the reason it does take so long.
Matt J
Matt J on 18 Sep 2019
Edited: Matt J on 18 Sep 2019
You could replace the dilation step with fft-based convolution for faster speed. This would make sense if you are using very large gap sizes.
Or use traditional edge linking baed on linking closest endpoints, which should be even faster.
Can you please give an example Image Analyst?
Matt how your code can be used in my image linking the first white pixel lines from the bottom of the image or the last white pixel lines (lines that look like dots) as you see the image from top to bottom.
I attach the image
I don't understand how the linking is supposed to work. I suspect, in any case, that it will require a very different method, since it is a very different kind of image. A new thread may be a good idea.

Sign in to comment.

Image Analyst
Image Analyst on 18 Sep 2019
You might look to the "edge linking" link to the right for alternative methods. The method I like, which may be faster than dilation followed by skeletonization is to call bwmorph(bw, 'endpoints') and then use imline() to draw a line connecting endpoints closer than some distance that you specify.

1 Comment

Image Analyst,
Please explain the imline part. Please give an example.
Thank you

Sign in to comment.

Categories

Asked:

on 16 Sep 2019

Commented:

on 27 Sep 2019

Community Treasure Hunt

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

Start Hunting!