Skip to content

Instantly share code, notes, and snippets.

@petrblahos
Created January 5, 2018 14:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petrblahos/ed8d3b438fd1999db21e1858cbbeacfb to your computer and use it in GitHub Desktop.
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/
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