def _center_viewport(self, paths): (xmin, xmax, ymin, ymax) = paths2svg.big_bounding_box(paths) width = xmax - xmin height = ymax - ymin svg_attributes = {} svg_attributes['viewBox'] = ' '.join( map(self._format_float, (xmin, ymin, width, height))) return svg_attributes
def align_components(eyes, nose, mouth, height): padding = 0.5 nose_min, nose_max, _, _ = big_bounding_box(nose) eyes_min, eyes_max, _, _ = big_bounding_box(eyes) _, mouth_max, _, _ = big_bounding_box(mouth) nose_height = nose_max - nose_min nose_top = ((height + nose_height) / 2) + 3.5 nose_delta = nose_top - nose_max eyes_height = eyes_max - eyes_min eyes_top = nose_top + eyes_height + padding eyes_delta = eyes_top - eyes_max mouth_top = nose_top - nose_height - padding mouth_delta = mouth_top - mouth_max face = [] list(map(lambda path: face.append(path.translated(complex(nose_delta, 0))), nose)) list(map(lambda path: face.append(path.translated(complex(eyes_delta, 0))), eyes)) list(map(lambda path: face.append(path.translated(complex(mouth_delta, 0))), mouth)) return face
# 6. export as new file pages = glob.glob("./images/*.jpg") cutouts = glob.glob("./ground-truth/locations/*.svg") pages.sort() cutouts.sort() for page, cutout in zip(pages, cutouts): page_number = os.path.splitext(os.path.basename(page))[0] paths, attributes, svg_attributes = svg2paths2(cutout) scan = cv2.imread(page, cv2.IMREAD_GRAYSCALE) #directly read in as grayscale for path, attribute in zip(paths, attributes): #paths, attributes, svg_attributes = svg2paths2('270.svg') code = attribute['id'] #https://github.com/mathandy/svgpathtools/blob/master/svgpathtools/paths2svg.py bbox = paths2svg.big_bounding_box( path) #returns (xmin, xmax, ymin, ymax) bbox = tuple(map(int, bbox)) #cast to int and convert back to tuple scan_crop = scan[bbox[2]:bbox[3], bbox[0]:bbox[1]] #binarize tresh = threshold_otsu( scan_crop ) #https://scikit-image.org/docs/stable/api/skimage.filters.html#skimage.filters.threshold_otsu scan_crop_logic = scan_crop < tresh #create mask height = int(bbox[3] - bbox[2]) width = int(bbox[1] - bbox[0]) mask = Image.new('1', (width, height), "black") mask_draw = ImageDraw.Draw(mask)
def draw_glyph(font, char, ctx, offset=(0, 0), color=(0.6, 0.6, 0.6)): try: face = Face('data/ttfs/{}.ttf'.format(font)) except: face = Face('data/ttfs/{}.otf'.format(font)) face.set_char_size(48*64) face.load_char(char) outline = face.glyph.outline contours = [-1] + outline.contours segment = [] segments = [] paths = [] for i in range(len(outline.points)): segment.append(complex(*outline.points[i]).conjugate()) tag = int(bin(outline.tags[i])[2]) try: j = contours.index(i) if tag == 0: segment.append(complex(*outline.points[contours[j-1]+1]).conjugate()) tag = 2 else: tag = 3 except ValueError: pass if tag > 0: if len(segment) == 1: pass elif len(segment) == 2: segments.append(Line(*segment)) elif len(segment) == 3: segments.append(QuadraticBezier(*segment)) elif len(segment) == 4: segments.append(CubicBezier(*segment)) else: for k in range(len(segment)-1): A, C = segment[k:k+2] B = (A+C) / 2 segments.append(QuadraticBezier(A, B, C)) if tag == 1: segment = [complex(*outline.points[i]).conjugate()] elif tag == 2: paths.append(Path(*segments)) segments = [] segment = [] else: segments.append(Line(segment[-1], complex(*outline.points[contours[j-1]+1]).conjugate())) paths.append(Path(*segments)) segments = [] segment = [] xmin, xmax, ymin, ymax = paths2svg.big_bounding_box(paths) factor = 0.8 / max(xmax-xmin, ymax-ymin) for i, path in enumerate(paths): paths[i] = path.translated(complex(-xmin, -ymin)).scaled(factor) xmin, xmax, ymin, ymax = paths2svg.big_bounding_box(paths) xmargin = (1 - (xmax-xmin)) / 2 ymargin = (1 - (ymax-ymin)) / 2 for i, path in enumerate(paths): paths[i] = path.translated(complex(xmargin, ymargin)) ctx.set_source_rgb(*color) ctx.new_path() ctx.set_line_width(0.02) x, y = offset for path in paths: ctx.move_to(path[0].bpoints()[0].real + x, path[0].bpoints()[0].imag + y) for seg in path: bpoints = seg.bpoints() if len(bpoints) == 2: ctx.line_to(bpoints[1].real + x, bpoints[1].imag + y) elif len(bpoints) == 3: ctx.curve_to(bpoints[0].real * 1/3 + bpoints[1].real * 2/3 + x, bpoints[0].imag * 1/3 + bpoints[1].imag * 2/3 + y, bpoints[1].real * 2/3 + bpoints[2].real * 1/3 + x, bpoints[1].imag * 2/3 + bpoints[2].imag * 1/3 + y, bpoints[2].real + x, bpoints[2].imag + y) elif len(bpoints) == 4: ctx.curve_to(bpoints[1].real + x, bpoints[1].imag + y, bpoints[2].real + x, bpoints[2].imag + y, bpoints[3].real + x, bpoints[3].imag + y) ctx.fill()
def process_letter(font_char): try: font, char = font_char name = "{}_{}".format(char, os.path.splitext(font)[0]) face = Face('data/fonts/ttfs/{}'.format(font)) face.set_char_size(48 * 64) face.load_char(char) outline = face.glyph.outline contours = [-1] + outline.contours segment = [] segments = [] paths = [] for i in range(len(outline.points)): segment.append(complex(*outline.points[i]).conjugate()) tag = int(bin(outline.tags[i])[2]) try: j = contours.index(i) if tag == 0: segment.append( complex(*outline.points[contours[j - 1] + 1]).conjugate()) tag = 2 else: tag = 3 except ValueError: pass if tag > 0: if len(segment) == 1: pass elif len(segment) == 2: segments.append(Line(*segment)) elif len(segment) == 3: segments.append(QuadraticBezier(*segment)) elif len(segment) == 4: segments.append(CubicBezier(*segment)) else: for k in range(len(segment) - 1): A, C = segment[k:k + 2] B = (A + C) / 2 segments.append(QuadraticBezier(A, B, C)) if tag == 1: segment = [complex(*outline.points[i]).conjugate()] elif tag == 2: paths.append(Path(*segments)) segments = [] segment = [] else: segments.append( Line( segment[-1], complex(*outline.points[contours[j - 1] + 1]).conjugate())) paths.append(Path(*segments)) segments = [] segment = [] xmin, xmax, ymin, ymax = paths2svg.big_bounding_box(paths) factor = 0.8 / max(xmax - xmin, ymax - ymin) for i, path in enumerate(paths): paths[i] = path.translated(complex(-xmin, -ymin)).scaled(factor) xmin, xmax, ymin, ymax = paths2svg.big_bounding_box(paths) xmargin = (1 - (xmax - xmin)) / 2 ymargin = (1 - (ymax - ymin)) / 2 for i, path in enumerate(paths): paths[i] = path.translated(complex(xmargin, ymargin)) points = [] surface = cairo.ImageSurface(cairo.Format.RGB24, opt.img_size, opt.img_size) ctx = cairo.Context(surface) ctx.scale(opt.img_size, opt.img_size) ctx.set_source_rgba(1, 1, 1) ctx.rectangle(0, 0, 1, 1) ctx.fill() ctx.set_source_rgb(0, 0, 0) ctx.new_path() ctx.set_line_width(0.02) for path in paths: ctx.move_to(path[0].bpoints()[0].real, path[0].bpoints()[0].imag) for seg in path: bpoints = seg.bpoints() if len(bpoints) == 2: ctx.line_to(bpoints[1].real, bpoints[1].imag) elif len(bpoints) == 3: ctx.curve_to( bpoints[0].real * 1 / 3 + bpoints[1].real * 2 / 3, bpoints[0].imag * 1 / 3 + bpoints[1].imag * 2 / 3, bpoints[1].real * 2 / 3 + bpoints[2].real * 1 / 3, bpoints[1].imag * 2 / 3 + bpoints[2].imag * 1 / 3, bpoints[2].real, bpoints[2].imag) elif len(bpoints) == 4: ctx.curve_to(bpoints[1].real, bpoints[1].imag, bpoints[2].real, bpoints[2].imag, bpoints[3].real, bpoints[3].imag) for t in np.linspace(0, 1, num=opt.n_points_sampled // len(paths) + 1): points.append(path.point(t)) ctx.fill() n_points = len(points) points = np.array(points, dtype=np.complex64).view(np.float32).reshape([-1, 2]) np.random.shuffle(points) np.save('data/fonts/points/{}.npy'.format(name), points) grid = np.mgrid[-0.25:1.25:opt.img_size * 1.5j, -0.25:1.25:opt.img_size * 1.5j].T[:, :, None, :] distances = np.empty((grid.shape[0], grid.shape[1])) for i in range(grid.shape[0]): for j in range(grid.shape[0]): distances[i, j] = np.amin( np.linalg.norm(grid[i, j] - points, axis=1)) if not np.isnan(distances).any(): np.save('data/fonts/distances/{}.npy'.format(name), distances) surface.write_to_png('data/fonts/pngs/{}.png'.format(name)) else: return e except Exception as e: return e return None
def boundsRectangle(paths): xmin, xmax, ymin, ymax = big_bounding_box(paths) return PathUtilities.GTBoundsRectangle((xmin, ymin), (xmax, ymax))
svg_logout = f"""<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="{h}px" viewBox="0 0 24 24" width="{h}px" fill="{color}"><g><path d="M0,0h24v24H0V0z" fill="none"/></g><g><path d="M17,8l-1.41,1.41L17.17,11H9v2h8.17l-1.58,1.58L17,16l4-4L17,8z M5,5h7V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h7v-2H5V5z"/></g></svg>""" h=45 svg_subject = f"""<svg xmlns="http://www.w3.org/2000/svg" height="{h}px" viewBox="0 0 24 24" width="{h}px" fill="{color}"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M14 17H4v2h10v-2zm6-8H4v2h16V9zM4 15h16v-2H4v2zM4 5v2h16V5H4z"/></svg>""" svg_notif = f"""<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="{h}px" viewBox="0 0 24 24" width="{h}px" fill="{color}"><g><path d="M0,0h24v24H0V0z" fill="none"/></g><g><path d="M12,18.5c0.83,0,1.5-0.67,1.5-1.5h-3C10.5,17.83,11.17,18.5,12,18.5z M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10 c5.52,0,10-4.48,10-10S17.52,2,12,2z M12,20c-4.41,0-8-3.59-8-8s3.59-8,8-8c4.41,0,8,3.59,8,8S16.41,20,12,20z M16,11.39 c0-2.11-1.03-3.92-3-4.39V6.5c0-0.57-0.43-1-1-1s-1,0.43-1,1V7c-1.97,0.47-3,2.27-3,4.39V14H7v2h10v-2h-1V11.39z M14,14h-4v-3 c0-1.1,0.9-2,2-2s2,0.9,2,2V14z"/></g></svg>""" svg_mediation = f"""<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="{h}px" viewBox="0 0 24 24" width="{h}px" fill="{color}"><g><rect fill="none" height="24" width="24"/><path d="M18,16l4-4l-4-4v3h-5.06c-0.34-3.1-2.26-5.72-4.94-7.05C7.96,2.31,6.64,1,5,1C3.34,1,2,2.34,2,4s1.34,3,3,3 c0.95,0,1.78-0.45,2.33-1.14C9.23,6.9,10.6,8.77,10.92,11h-3.1C7.4,9.84,6.3,9,5,9c-1.66,0-3,1.34-3,3s1.34,3,3,3 c1.3,0,2.4-0.84,2.82-2h3.1c-0.32,2.23-1.69,4.1-3.58,5.14C6.78,17.45,5.95,17,5,17c-1.66,0-3,1.34-3,3s1.34,3,3,3 c1.64,0,2.96-1.31,2.99-2.95c2.68-1.33,4.6-3.95,4.94-7.05H18V16z"/></g></svg>""" svg_pivot = f""" <svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="{h}px" viewBox="0 0 24 24" width="{h}px" fill="{color}"><g><path d="M0,0h24v24H0V0z" fill="none"/></g><g><path d="M21,5c0-1.1-0.9-2-2-2h-9v5h11V5z M3,19c0,1.1,0.9,2,2,2h3V10H3V19z M3,5v3h5V3H5C3.9,3,3,3.9,3,5z M18,8.99L14,13 l1.41,1.41l1.59-1.6V15c0,1.1-0.9,2-2,2h-2.17l1.59-1.59L13,14l-4,4l4,4l1.41-1.41L12.83,19H15c2.21,0,4-1.79,4-4v-2.18l1.59,1.6 L22,13L18,8.99z"/></g></svg>""" svg_tune = f""" <svg xmlns="http://www.w3.org/2000/svg" height="{h}px" viewBox="0 0 24 24" width="{h}px" fill="{color}"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v10c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16V6H5V2zM4 17c-.55 0-1-.45-1-1v-2h2v2c0 .55-.45 1-1 1zm-1-5V8h2v4H3zM13 2c0-.55-.45-1-1-1s-1 .45-1 1v4H9v10c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.42 2-1.52 2-2.82V6h-2V2zm-1 15c-.55 0-1-.45-1-1v-2h2v2c0 .55-.45 1-1 1zm-1-5V8h2v4h-2zm10-6V2c0-.55-.45-1-1-1s-1 .45-1 1v4h-2v10c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.42 2-1.52 2-2.82V6h-2zm-1 11c-.55 0-1-.45-1-1v-2h2v2c0 .55-.45 1-1 1zm-1-5V8h2v4h-2z"/></svg>""" #%% from svgelements import * import svgelements st = SVGText(svg_tune) SVG.()s #%% from svg.path import parse_path #%% from svgutils.compose import * Figure("16cm", "6.5cm", Element(svg_subject), Element(svg_settings)).save("fig_final_compose.svg") #%%% from svgpathtools import Path from svgpathtools.paths2svg import big_bounding_box svg_path = Path(svg_tune) xmin, xmax, ymin, ymax = big_bounding_box([svg_path]) #%% from svgpathtools import svg2paths, wsvg paths, attributes = svg2paths(svg_tune)
def sample_points_from_font(font, char): try: face = Face('data/ttfs/{}.ttf'.format(font)) except: face = Face('data/ttfs/{}.otf'.format(font)) face.set_char_size(48 * 64) face.load_char(char) outline = face.glyph.outline contours = [-1] + outline.contours segment = [] segments = [] paths = [] for i in range(len(outline.points)): segment.append(complex(*outline.points[i]).conjugate()) tag = int(bin(outline.tags[i])[2]) try: j = contours.index(i) if tag == 0: segment.append( complex(*outline.points[contours[j - 1] + 1]).conjugate()) tag = 2 else: tag = 3 except ValueError: pass if tag > 0: if len(segment) == 1: pass elif len(segment) == 2: segments.append(Line(*segment)) elif len(segment) == 3: segments.append(QuadraticBezier(*segment)) elif len(segment) == 4: segments.append(CubicBezier(*segment)) else: for k in range(len(segment) - 1): A, C = segment[k:k + 2] B = (A + C) / 2 segments.append(QuadraticBezier(A, B, C)) if tag == 1: segment = [complex(*outline.points[i]).conjugate()] elif tag == 2: paths.append(Path(*segments)) segments = [] segment = [] else: segments.append( Line( segment[-1], complex(*outline.points[contours[j - 1] + 1]).conjugate())) paths.append(Path(*segments)) segments = [] segment = [] xmin, xmax, ymin, ymax = paths2svg.big_bounding_box(paths) factor = 0.8 / max(xmax - xmin, ymax - ymin) for i, path in enumerate(paths): paths[i] = path.translated(complex(-xmin, -ymin)).scaled(factor) xmin, xmax, ymin, ymax = paths2svg.big_bounding_box(paths) xmargin = (1 - (xmax - xmin)) / 2 ymargin = (1 - (ymax - ymin)) / 2 for i, path in enumerate(paths): paths[i] = path.translated(complex(xmargin, ymargin)) points = [] for path in paths: for seg in path: length = seg.length() for a in np.linspace(0, 1, num=length * n_points_per_unit_length): points.append(seg.point(seg.ilength(a * length))) return [(p.real, p.imag) for p in points]