def default_systematicity(chars, fonts, font_sizes):
    for font in fonts:
        for font_size in font_sizes:
            with data.db.atomic():
                experiment_name = "Default: {0} size {1}.".format(
                    font.name, font_size)
                experiment = Experiment(
                    name=experiment_name,
                    method=ExperimentType.DefaultSystematicity,
                    start_time=datetime.now(),
                    hyperparameters=None)
                experiment.save()
                print(experiment_name)

                renderer = shapes.GlyphRenderer(io.BytesIO(font.font_file))
                defaults = [axis.default for axis in renderer._axes]

                try:
                    result = systematicity.evaluate(chars,
                                                    font,
                                                    font_size,
                                                    coords=None)
                except systematicity.FailedRenderException:
                    print(
                        "Unable to determine systematicity for {0} pt {1} because at least one glyph failed to render."
                        .format(font_size, font.name))
                    continue

                save_result(experiment.id, result)

                print("Corr: {0:.4f} for {1} pt {2}.".format(
                    result.edit_correlation, font_size, font.name))

                experiment.end_time = datetime.now()
                experiment.save()
Esempio n. 2
0
def get_glyphs(chars, font, size, coords=None):
    coords_serial = None if (coords is None
                             or len(coords) == 0) else json.dumps(coords)
    chars_serial = json.dumps(chars)

    # Check if glyphs already exist
    glyph_sets = (GlyphSet.select().where(
        GlyphSet.font_id == font.id, GlyphSet.size == size,
        GlyphSet.coords == coords_serial,
        GlyphSet.chars == chars_serial).execute())
    if len(glyph_sets) > 0:
        return glyph_sets[0].id

    renderer = shapes.GlyphRenderer(io.BytesIO(font.font_file))
    bitmaps = renderer.bitmaps(chars, size, coords)

    glyph_set = GlyphSet(font=font,
                         size=size,
                         coords=coords_serial,
                         chars=chars_serial)
    glyph_set.save()

    glyphs = []
    for i in range(len(chars)):
        glyph = Glyph(glyph_set_id=glyph_set.id,
                      character=chars[i],
                      bitmap=bitmaps[i])
        glyphs.append(glyph)

    with data.db.atomic():
        Glyph.bulk_create(glyphs, batch_size=100)

    return glyph_set.id
Esempio n. 3
0
def get_chinese_distances():
    chars = ["耳","目","口","手","足","日","月","水","火","山","石","田","禾","兔","鸟","竹","羊","木","网","刀","尺","心","雨","又","云","女","小","少"]
    fonts = Font.select().where(
        (Font.name == "simfang") |
        (Font.name == "simkai")
    )
    
    for font in fonts:
        renderer = shapes.GlyphRenderer(io.BytesIO(font.font_file))
        glyph_set_id = systematicity.get_glyphs(chars, font, 96)
        distances = systematicity.get_shape_distances(glyph_set_id)
def grid_search(chars, fonts, font_sizes, grid_count):
    for font in fonts:
        for font_size in font_sizes:
            experiment_name = "Grid: {0} size {1}, {2} facets.".format(
                font.name, font_size, grid_count)
            experiment = Experiment(name=experiment_name,
                                    method=ExperimentType.GridSearch,
                                    start_time=datetime.now(),
                                    hyperparameters=json.dumps(
                                        {"facets": grid_count}))
            experiment.save()
            print(experiment_name)

            random.seed(random_seed)

            renderer = shapes.GlyphRenderer(io.BytesIO(font.font_file))
            defaults = [axis.default for axis in renderer._axes]
            best_corr = 0.0

            for index in range(len(renderer._axes)):
                axis = renderer._axes[index]
                vals = get_grid_coords(axis.minimum, axis.maximum, grid_count)
                best_axis_corr = 0.0

                for idx, val in enumerate(vals):
                    coords = defaults.copy()
                    coords[index] = val

                    try:
                        result = systematicity.evaluate(
                            chars, font, font_size, coords)
                    except systematicity.FailedRenderException:
                        # ignore failed render and carry on
                        print("Failed render at point {0}".format(coords))
                        continue

                    save_result(experiment.id, result)

                    print("Corr {0:.4f} for {1} pt {2} for {3} value of {4}".
                          format(result.edit_correlation, font_size, font.name,
                                 axis.name, val))
                    if result.edit_correlation > best_axis_corr:
                        best_axis_corr = result.edit_correlation
                    if result.edit_correlation > best_corr:
                        best_corr = result.edit_correlation

                print("Best corr: {0:.4f} for axis {1}".format(
                    best_axis_corr, axis.name))

            print("Best corr: {0:.4f}".format(best_corr))
            experiment.end_time = datetime.now()
            experiment.save()
def random_search(chars, fonts, font_sizes, num_points):
    for font in fonts:
        for font_size in font_sizes:
            experiment_name = "Random: {0} size {1}, {2} points.".format(
                font.name, font_size, num_points)
            experiment = Experiment(name=experiment_name,
                                    method=ExperimentType.RandomSearch,
                                    start_time=datetime.now(),
                                    hyperparameters=json.dumps(
                                        {"points": num_points}))
            experiment.save()
            print(experiment_name)

            random.seed(random_seed)

            renderer = shapes.GlyphRenderer(io.BytesIO(font.font_file))

            points = get_random_coords(renderer._axes, num_points)
            # Include min and max
            points.insert(0, [axis.minimum for axis in renderer._axes])
            points.append([axis.maximum for axis in renderer._axes])

            best_corr = 0.0

            iteration = 1
            for point in points:
                try:
                    result = systematicity.evaluate(chars, font, font_size,
                                                    point)
                except systematicity.FailedRenderException:
                    # ignore failed render and carry on to next point
                    print("{0} Failed render at point {1}".format(
                        iteration, point))
                    continue
                save_result(experiment.id, result)

                print("{0} Corr: {1:.4f} for {2} pt {3} with coords {4}...".
                      format(iteration, result.edit_correlation, font_size,
                             font.name, point))
                if result.edit_correlation > best_corr:
                    best_corr = result.edit_correlation

                iteration += 1
            print("Best corr: {0:.4f}".format(best_corr))

            experiment.end_time = datetime.now()
            experiment.save()
Esempio n. 6
0
def load_fonts(font_dir):
    # Only use OpenType and TrueType font files
    font_files = [_ for _ in Path(font_dir).glob("**/*.otf")]
    font_files += [_ for _ in Path(font_dir).glob("**/*.ttf")]

    data.db.connect()
    for file_path in font_files:
        print("Importing {0}".format(file_path))
        file_name = os.path.basename(file_path)
        font_name = os.path.splitext(file_name)[0]
        
        with open(os.path.join(file_path), mode='rb') as font_file:
            font_blob = font_file.read()
            font = data.Font(name=font_name, file_name=file_name, font_file=font_blob)

            file_stream = io.BytesIO(font_blob)
            
            # Add data for OpenType variation fonts
            renderer = shapes.GlyphRenderer(file_stream)
            if len(renderer._axes) > 0:
                axes = []
                for axis in renderer._axes:
                    obj = {
                        'name': axis.name, 
                        'default':axis.default,
                        'minimum':axis.minimum,
                        'maximum':axis.maximum
                    }
                    axes.append(obj)                
                
                font.is_variable = True
                font.axes = json.dumps({"axes":axes})

            font.save()

    data.db.close()
def simulated_annealing(chars,
                        fonts,
                        font_sizes,
                        init_temp,
                        time,
                        alter_type="gaussian",
                        alter_range="0.1",
                        method=ExperimentType.SimulatedAnnealing):
    if method not in [
            ExperimentType.SimulatedAnnealing,
            ExperimentType.SimulatedAnnealingMin
    ]:
        raise ("Method must be one of the simulated annealing types")

    for font in fonts:
        for font_size in font_sizes:
            experiment_name = "Simulated Annealing: {0} size {1}, initial temp {2}, {3} iterations.".format(
                font.name, font_size, init_temp, time)
            experiment = Experiment(name=experiment_name,
                                    method=method,
                                    start_time=datetime.now(),
                                    hyperparameters=json.dumps({
                                        "temp":
                                        init_temp,
                                        "iterations":
                                        time,
                                        "alteration_type":
                                        alter_type,
                                        "alteration_range":
                                        alter_range
                                    }))
            experiment.save()

            random.seed(random_seed)

            print(experiment_name)
            temperature = init_temp
            renderer = shapes.GlyphRenderer(io.BytesIO(font.font_file))
            #candidate = get_random_coords(renderer._axes, 1)[0]
            candidate = [axis.default for axis in renderer._axes]

            result = systematicity.evaluate(chars, font, font_size, candidate)
            save_result(experiment.id, result)
            corr = result.edit_correlation

            iteration = 1

            best_candidate = candidate
            best_corr = corr
            best_iteration = iteration

            print("Starting at {0}, {1}".format(best_candidate, best_corr))

            while iteration < time and temperature > 0:
                if alter_type == "gaussian":
                    new_candidate = alter_gaussian(candidate, renderer._axes,
                                                   alter_range)
                else:
                    new_candidate = alter_uniform(candidate, renderer._axes,
                                                  alter_range)

                try:
                    result = systematicity.evaluate(chars, font, font_size,
                                                    new_candidate)
                except systematicity.FailedRenderException:
                    # ignore failed render and carry on to a new candidate
                    continue

                save_result(experiment.id, result)
                new_corr = result.edit_correlation

                delta = new_corr - corr
                if method == ExperimentType.SimulatedAnnealingMin:
                    delta = -(delta)

                p = random.uniform(0.0, 1.0)

                if math.exp(delta / temperature) > p:
                    print(
                        "{0:3d} MOVE: {1:.4f}, {2:.4f} > {3:.4f}, temp: {4:.4f}, {5}"
                        .format(iteration, new_corr,
                                math.exp(delta / temperature), p, temperature,
                                new_candidate))

                    candidate = new_candidate
                    corr = new_corr
                else:
                    print(
                        "{0:3d} STAY: {1:.4f}, {2:.4f} <= {3:.4f}, temp: {4:.4f}, {5}"
                        .format(iteration, new_corr,
                                math.exp(delta / temperature), p, temperature,
                                new_candidate))

                if ((method == ExperimentType.SimulatedAnnealing
                     and corr > best_corr)
                        or (method == ExperimentType.SimulatedAnnealingMin
                            and corr < best_corr)):
                    best_corr = corr
                    best_candidate = candidate
                    best_iteration = iteration

                iteration += 1
                temperature = init_temp * (1 - iteration / time)

            print(
                "Best candidate for {0} size {1} in iteration {2}: {3:.4f}, {4}"
                .format(font.name, font_size, best_iteration, best_corr,
                        best_candidate))

            experiment.end_time = datetime.now()
            experiment.save()
        variance = axis_range * var_range

        while True:
            new_coord = round(coord + random.gauss(0, variance), 4)
            if new_coord >= axis.minimum and new_coord <= axis.maximum:
                break

        new_coords.append(new_coord)

    return new_coords


def save_result(experiment_id, systematicity_result):
    join = (ExperimentGlyphSet.select().where(
        (ExperimentGlyphSet.experiment_id == experiment_id)
        & (ExperimentGlyphSet.glyph_set_id == systematicity_result.glyph_set_id
           )).first())

    # Don't duplicate if we're using cached result
    if join is not None:
        return

    join = ExperimentGlyphSet(experiment_id=experiment_id,
                              glyph_set_id=systematicity_result.glyph_set_id)
    join.save()


if __name__ == "__main__":
    font = Font.select().where(Font.name == 'amstelvar-roman').first()
    renderer = shapes.GlyphRenderer(font.font_file)