3

I have this Binary image bw:

enter image description here

edges of an object to carry out some measurements. But firstly I have to do curve fitting for both edges. The result should be two smooth curves representing edges.

I have the indices for each edge but I can not use them in making x-y data to be input data to a fitting function. I mean they are not x and f(x), actually, they all have the same value (1) with different positions. It is not right to say [x y]=find(BW) ; y here is not the value at x, but for sure there should be a way to use them to some kind of scale the binary image. I seem confused and I'm stuck here.

Any recommendations?

Shai
  • 111,146
  • 38
  • 238
  • 371
Mohamed Sayed
  • 93
  • 1
  • 3
  • 10
  • You want to get the `(x,y)` coordinates of each pixel belonging to a line, and then fit a function `[x;y]=f(t)` – Jonas Apr 11 '16 at 06:54

1 Answers1

4

Why not use polyfit?

[y x] = find( bw );  %// get x y coordinates of all curve points

There are two small "tricks" you need to use here:

  1. You have two curves, thus you need to split your data points to the left and right curves

    right = x<300;
    xr = x(right);
    yr = y(right);
    xl = x(~right);
    yl = y(~right);
    
  2. Since your curves are close to vertical, it would be better to fit x=f(y) rather than the "classic" y=f(x):

    pr = polyfit( yr, xr, 3 );  %// fit 3rd deg poly
    pl = polyfit( yl, xl, 3 ); 
    

Now you can plot them

yy = linspace( 1, size(bw,1), 50 );

figure; imshow(bw, 'border', 'tight' );
hold all
plot( polyval( pr, yy ), yy, '.-', 'LineWidth', 1 );
plot( polyval( pl, yy ), yy, '.-', 'LineWidth', 1 );

And you get:

enter image description here

If you want to create a new refined mask from the estimated curves, you can do the following:

yy = 1:size(bw,1);  %// single value per row
xxr=polyval(pr,yy); %// corresponding column values
xxl=polyval(pl,yy);

Set a new mask of the same size

nbw = false(size(bw)); 
nbw( sub2ind(size(bw),yy,round(xxr)) )=true;
nbw( sub2ind(size(bw), yy, round(xxl) )) = true; 

And the result

figure;imshow(nbw,'border','tight');

enter image description here

Shai
  • 111,146
  • 38
  • 238
  • 371
  • It worked but just for plotting, I actually need to make the new curves indices "logical"(Ones) in the binary image itself ,not just a plot. I've tried but it seems I'm missing something, would you help me in this final step ? – Mohamed Sayed Apr 11 '16 at 16:22
  • @MohamedSayed you can get column value (X) for each row value (y), then round the X values to get indices – Shai Apr 11 '16 at 16:28
  • I appreciate your help, but to be honest, after my trials I still can't do it. And i think the points will be discrete or separate in the binary image not smooth "continuous" curve ! – Mohamed Sayed Apr 11 '16 at 17:35
  • @MohamedSayed the points in the binary image are, by definition, discrete. You cannot have pixels set in non integer locations – Shai Apr 11 '16 at 17:37
  • I know , I didn't mean that. I mean that I need to have a "logical one" for each row .In other words, there should be no gaps in the curve ...Anyways, when I tried your suggestion, the same old edges came out because for each row there're multiple column values not just one. – Mohamed Sayed Apr 11 '16 at 17:47