def fine_dewarp(im, lines): im_h, im_w = im.shape[:2] debug = cv2.cvtColor(im, cv2.COLOR_GRAY2BGR) points = [] y_offsets = [] for line in lines: if len(line) < 10 or abs(line.fit_line().angle()) > 0.001: continue line.fit_line().draw(debug, thickness=1) base_points = np.array([letter.base_point() for letter in line.inliers()]) median_y = np.median(base_points[:, 1]) y_offsets.append(median_y - base_points[:, 1]) points.append(base_points) for underline in line.underlines: mid_contour = (underline.top_contour() + underline.bottom_contour()) / 2 all_mid_points = np.stack([ underline.x + np.arange(underline.w), mid_contour, ]) mid_points = all_mid_points[:, ::4] points.append(mid_points) for p in base_points: pt = tuple(np.round(p).astype(int)) cv2.circle(debug, (pt[0], int(median_y)), 2, lib.RED, -1) cv2.circle(debug, pt, 2, lib.GREEN, -1) cv2.imwrite('points.png', debug) points = np.concatenate(points) y_offsets = np.concatenate(y_offsets) mesh = np.mgrid[:im_w, :im_h].astype(np.float32) xmesh, ymesh = mesh # y_offset_interp = interpolate.griddata(points, y_offsets, xmesh, ymesh, method='nearest') # y_offset_interp = y_offset_interp.clip(-5, 5) # mesh[1] += y_offset_interp # (mesh[0], mesh[1], grid=False) y_offset_interp = interpolate.SmoothBivariateSpline( points[:, 0], points[:, 1], y_offsets.clip(-3, 3), s=4 * points.shape[0] ) ymesh -= y_offset_interp(xmesh, ymesh, grid=False).clip(-3, 3) conv_xmesh, conv_ymesh = cv2.convertMaps(xmesh, ymesh, cv2.CV_16SC2) out = cv2.remap(im, conv_xmesh, conv_ymesh, interpolation=cv2.INTER_LINEAR, borderValue=np.median(im)).T cv2.imwrite('corrected.png', out) debug = cv2.cvtColor(out, cv2.COLOR_GRAY2BGR) for line in lines: base_points = np.array([letter.base_point() for letter in line.inliers()[1:-1]]) base_points[:, 1] -= y_offset_interp(base_points[:, 0], base_points[:, 1], grid=False) Line.fit(base_points).draw(debug, thickness=1) cv2.imwrite('corrected_line.png', debug) return out
def fit_line(self): if self.model_line is None: if len(self) <= 3: self.model_line = Line.fit(self.base_points()) else: model, inliers = ransac(self.base_points(), TextLine.LineModel, 3, 4) self.model_line = model.params self._line_inliers = list( itertools.compress(self.letters, inliers)) return self.model_line
def vanishing_point(lines, v0, O): C0 = lines[-1] if v0[1] < 0 else lines[0] others = lines[:-1] if v0[1] < 0 else lines[1:] domain = np.linspace(C0.left(), C0.right(), N_LONGS + 2)[1:-1] C0_points = np.array([domain, C0.model(domain)]).T longitudes = [Line.from_points(v0, p) for p in C0_points] lefts = [longitudes[0].text_line_intersect(line)[0] for line in others] rights = [longitudes[-1].text_line_intersect(line)[0] for line in others] valid_mask = [line.left() <= L and R < line.right() \ for line, L, R in zip(others, lefts, rights)] valid_lines = [C0] + compress(others, valid_mask) derivs = [line.model.deriv() for line in valid_lines] print('valid lines:', len(others)) convergences = [] for longitude in longitudes: intersects = [ longitude.text_line_intersect(line) for line in valid_lines ] tangents = [Line.from_point_slope(p, d(p[0])) \ for p, d in zip(intersects, derivs)] convergences.append(Line.best_intersection(tangents)) # x vx + y vy + f^2 = 0 # m = -vx / vy # b = -f^2 / vy L = Line.fit(convergences) # shift into O-origin coords L_O = L.offset(-O) vy = -(f**2) / L_O.b vx = -vy * L_O.m v = np.array((vx, vy)) + O debug = cv2.cvtColor(bw, cv2.COLOR_GRAY2BGR) for t in tangents: t.draw(debug, color=RED) for longitude in longitudes: longitude.draw(debug) L.draw(debug, color=GREEN) lib.debug_imwrite('vanish.png', debug) return v, f, L
def estimate(self, data): self.params = Line.fit(data) return True