Created
January 5, 2018 14:56
-
-
Save petrblahos/ed8d3b438fd1999db21e1858cbbeacfb to your computer and use it in GitHub Desktop.
Another shape interpolation, as described in http://petr.blahos.com/blog/shape-warping-02/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cv2 | |
import numpy as np | |
def get_interpolated_points(c1, c2, step, scale): | |
dif = c2 - c1 | |
return np.array(c1 + dif*step/scale, dtype=np.int32) | |
def get_line_list(img, height, simplified): | |
if 3 == len(img.shape): | |
img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) | |
thr = cv2.threshold(img, 0, 255, | |
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] | |
cnts = cv2.findContours(thr, cv2.RETR_LIST, | |
cv2.CHAIN_APPROX_SIMPLE)[1] | |
ret = [] | |
for cnt in cnts: | |
if simplified: | |
cnt = cv2.approxPolyDP(cnt, height/200, True) | |
for i in range(len(cnt)-1): | |
ret.append((cnt[i][0], cnt[i+1][0])) | |
ret.append((cnt[len(cnt)-1][0], cnt[0][0])) | |
return np.array(ret) | |
def enlarge_line_list(c1, point_count): | |
src_points_count = c1.shape[0] | |
smaller = point_count // src_points_count | |
rep_schema = np.full([src_points_count], smaller) | |
rep_schema[0:src_points_count-(smaller+1)*src_points_count+point_count] = smaller+1 | |
return np.repeat(c1, rep_schema, axis=0) | |
def determine_font_scale(img_size): | |
""" | |
Returns about the biggest font scale to fit a single character | |
into the supplied img_size. | |
""" | |
scale = 1.0 | |
for i in range(10): | |
(sz, baseline) = cv2.getTextSize("M", cv2.FONT_HERSHEY_SIMPLEX, scale, 4) | |
if sz[1] + baseline < img_size[0]*0.9: | |
scale *= (img_size[0]*0.9)/(sz[1]+baseline) | |
elif sz[1] + baseline > img_size[0]*0.95: | |
scale *= (img_size[0]*0.9)/(sz[1]+baseline) | |
else: | |
break | |
return (scale, baseline) | |
def gen_char(img_size, c, scale, baseline): | |
""" | |
Creates an image containing a centered character c. | |
""" | |
img = np.zeros(img_size, dtype=np.uint8) | |
(sz, _baseline) = cv2.getTextSize(c, cv2.FONT_HERSHEY_SIMPLEX, | |
scale, 4) | |
cv2.putText(img, c, ((img_size[1]-sz[0])//2, img_size[0] - baseline), | |
cv2.FONT_HERSHEY_SIMPLEX, scale, 40, cv2.LINE_AA) | |
return img | |
def interpolate_shapes(img_size, i0, i1): | |
SIMPLIFIED = False | |
SHUFFLED = True | |
c1 = get_line_list(i0, img_size[1], simplified=SIMPLIFIED) | |
c2 = get_line_list(i1, img_size[1], simplified=SIMPLIFIED) | |
if c1.shape[0] < c2.shape[0]: | |
c1 = enlarge_line_list(c1, c2.shape[0]) | |
elif c2.shape[0] < c1.shape[0]: | |
c2 = enlarge_line_list(c2, c1.shape[0]) | |
if SHUFFLED: | |
np.random.shuffle(c2) | |
SCALE = 100 | |
for j in range(SCALE + 1): | |
img = np.zeros((img_size[0], img_size[1], 3), dtype=np.uint8) | |
cc = get_interpolated_points(c1, c2, j, SCALE) | |
for i in cc: | |
cv2.line(img, tuple(i[0]), tuple(i[1]), (255, 255, 0), 2) | |
cv2.imshow("A", img) | |
cv2.waitKey(1) | |
return img | |
if "__main__" == __name__: | |
img_size = (400, 400) | |
(scale, baseline) = determine_font_scale(img_size) | |
i0 = gen_char(img_size, '-', scale, baseline) | |
for i in "abcdefghijklmnopqrstuvwxyz": | |
i = ord(i) | |
img = gen_char(img_size, chr(i), scale, baseline) | |
out_img = interpolate_shapes(img_size, i0, img) | |
i0 = img | |
cv2.waitKey(300) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment