Velvet Star Monitor

Standout celebrity highlights with iconic style.

news

Inpainting missing curved segment in an image

Writer Matthew Barrera

I have few images (very low resolution), but due to the inconsistency in data collection, the images sometimes have a missing segment which can be identified by checking for horizontal lines from bottom (atleast that is what I do). I want to fix the missing segment with a reasonable curve in real-time. For example-
enter image description hereenter image description here
Unfortunately, I cannot upload the image in it's actual size, but if you want to experiment you can comment and then I will try to send few data as numpy arrays.

What have I tried?
I have tried fixing the segments using Bezier curves. My Idea was to take the extremes of the horizontal segment as P0 and P3 and then calculate the intersection point P1 as shown in my code below:

public static Coordinate<Integer> pointofIntersection(List<Coordinate<Integer>> line1, List<Coordinate<Integer>> line2) { var m1 = (line1.get(1).row - line1.get(0).row) / (line1.get(1).col - line1.get(0).col); var m2 = (line2.get(1).row - line2.get(0).row) / (line2.get(1).col - line2.get(0).col); var c1 = line1.get(0).row - m1 * line1.get(0).col; var c2 = line2.get(0).row - m2 * line2.get(0).col; m2 = m2==0?-1:m2; m1 = m1==0?1:m1; var slope_diff = (m1 - m2)==0?1:(m1-m2); var x = (c2 - c1) / slope_diff; var y = m1 * x + c1; var slope_ratio = Math.abs((float)m1/(float)m2)>1?Math.pow(Math.abs((float)m1/(float)m2),0.5):Math.pow(Math.abs((float)m1/(float)m2),2); x = (int) (x/ slope_ratio); return new Coordinate<Integer>(y, x);
}

Finally after getting P1, I estimate the fourth control point P2 for Bezier curve as the center point of the line joining P3 and P1 and then I put P2.y = P1.y
After Calculating the four control points, I calculate the Bezier curve as follows:

public List<Coordinate<Integer>> generateBezierPath4Points(ArrayList<Coordinate<Integer>> controlPoints, int segments) { ArrayList<Coordinate<Integer>> pointsForReturn = new ArrayList<Coordinate<Integer>>(); float t = 0; for (int i = 0; i < segments; i++) { Coordinate p = new Coordinate(-1,-1); var x = ((1-t)*(1-t)*(1-t)* controlPoints.get(0).col)+ (3*(1-t)*(1-t)*t*controlPoints.get(1).col) + (3*(1-t)*t*t*controlPoints.get(2).col) + (t*t*t*controlPoints.get(3).col); var y = ((1-t)*(1-t)*(1-t)* controlPoints.get(0).row)+ (3*(1-t)*(1-t)*t*controlPoints.get(1).row) + (3*(1-t)*t*t*controlPoints.get(2).row) + (t*t*t*controlPoints.get(3).row); Double r = Math.ceil(y); Double c = Math.ceil(x); p.row = r.intValue(); p.col = c.intValue(); t += 1.0f / segments; pointsForReturn.add(p); } return pointsForReturn;
}

My Results
enter image description here enter image description here

What do I expect?
As you can clearly see that my estimations are sometimes more convex than expected. I want to fill the missing segment such that it appears more natural as I have tried to plot with inkscape (filled in red), where I can visually control the curve. see below:
enter image description here

1

1 Answer

If you use a quadratic or cubic Bezier, you can rely on the fact that the control point(s) define(s) the tangent at the start and end points.

Find your "cutoff" row, and then walk up the shape (with whatever visual processing library you're already using) on the left and right a little to pick the curve's start and end points. The first control point then lies somewhere on a line from the start point along the contour, with the same being true for the end point:

enter image description here

The simplest Bezier-based infill would be a quadratic curve, with the single control point at the intersection of those two lines. If you don't have quadratic primitives but you do have cubic primitives, you can get the exact same curve by creating control points by linear interpolation of the start+intersection and intersection+end pairs (See the second paragraph in ).

Or you could reconstruct the "perfect" cubic by reversing de Casteljau's procedure (see ) but I strongly doubt that's worth the effort.

6

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.