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
def render_hausdorff_distance(shape_distance_id): Glyph1 = Glyph.alias() Glyph2 = Glyph.alias() query = (ShapeDistance .select() .join(Glyph1, on=ShapeDistance.glyph1) .switch(ShapeDistance) .join(Glyph2, on=ShapeDistance.glyph2) .where( ShapeDistance.id == shape_distance_id)) result = query[0] points1 = json.loads(result.points1) points2 = json.loads(result.points2) bitmap1 = result.glyph1.bitmap bitmap2 = result.glyph2.bitmap bitmap = visualization.render_distance_overlay( result.glyph1.character, result.glyph2.character, bitmap1, bitmap2, points1, points2, result.distance, result.distance) return bitmap
def test_preprocess_sample(self): raw_dict, prep_dict = np.array(list(raw_glyphs_dict(mapping))), preprocessed_glyphs_dict(mapping) zipped_dicts = list(zip(raw_dict, prep_dict)) zipped_dicts = random.sample(list(zipped_dicts), 50) raw_sample = [Glyph(**pair[0]) for pair in zipped_dicts] prep_sample = [Glyph(**pair[1]) for pair in zipped_dicts] plt.figure(figsize=(14, 10)) zipped = [] for i in range(len(raw_sample)): zipped.append(raw_sample[i]) zipped.append(prep_sample[i]) draw_chars(zipped)
def get_correlation(glyph_set_id, sound_metric, shape_metric): # Fetch from db if it's already calculated query = (Correlation.select().where( (Correlation.glyph_set_id == glyph_set_id) & (Correlation.sound_metric == sound_metric) & (Correlation.shape_metric == shape_metric))) if len(query) > 0: return query.first() sound_query = (SoundDistance.select().where( SoundDistance.metric == sound_metric).order_by(SoundDistance.char1, SoundDistance.char2)) Glyph1 = Glyph.alias() Glyph2 = Glyph.alias() shape_query = (ShapeDistance.select().join( Glyph1, on=ShapeDistance.glyph1).switch(ShapeDistance).join( Glyph2, on=ShapeDistance.glyph2).where( (Glyph1.glyph_set_id == glyph_set_id) & (Glyph2.glyph_set_id == glyph_set_id) & (ShapeDistance.metric == shape_metric)).order_by( Glyph1.character, Glyph2.character)) sound_distances = [s.distance for s in sound_query] shape_distances = [s.distance for s in shape_query] if (len(sound_distances) != len(shape_distances)): raise Exception( "Numer of shape ({0}) and sound ({1}) distances are not equal for glyph set {2}, sound metric {3}, shape metric {4}" .format(len(shape_distances), len(sound_distances), glyph_set_id, sound_metric, shape_metric)) if np.std(shape_distances) == 0: raise Exception( "Unable to calculate correlation for glyph set {0}: standard deviation of shape distances is zero." .format(glyph_set_id)) corr_value = pearsonr(shape_distances, sound_distances) correlation = Correlation(glyph_set=glyph_set_id, shape_metric=shape_metric, sound_metric=sound_metric, r_value=corr_value[0], p_value=corr_value[1]) correlation.save() return correlation
def test_compare_rotation(self): character_ids = ['I', 'H', 'c'] rotation_sequence = [] raw_sequence = [] for character_id in character_ids: glyph = test_glyphs[character_id] raw_char = Glyph(character_id, "test_sample_123" + character_id, [np.array(stroke) for stroke in glyph['strokes']]) centre_of_mass = _centre_of_mass(raw_char.strokes) slant = _calculate_glyph_slant(raw_char.strokes) rotated_strokes = _rotate_strokes(raw_char.strokes, centre_of_mass, slant) glyph = Glyph(character_id, "rotated_sample_123" + character_id, [np.array(stroke) for stroke in rotated_strokes]) raw_sequence.append(raw_char) rotation_sequence.append(glyph) draw_chars(raw_sequence + rotation_sequence, 3)
def test_slant_correction(self): character_id = 'a' character_id = 'h' glyph = test_glyphs[character_id] raw_char = Glyph(character_id, "test_sample_123", [np.array(stroke) for stroke in glyph['strokes']]) rotation_sequence = [raw_char] for i in range(9): centre_of_mass = _centre_of_mass(raw_char.strokes) slant = _calculate_glyph_slant(raw_char.strokes) rotated_strokes = _rotate_strokes(raw_char.strokes, centre_of_mass, slant) rotated_char = Glyph(character_id, "rotated_sample_123", [np.array(stroke) for stroke in rotated_strokes]) rotation_sequence.append(rotated_char) # draw_chars(rotation_sequence, 10) np.testing.assert_array_equal(rotation_sequence[1].strokes[0], rotation_sequence[-1].strokes[0]) np.testing.assert_array_equal(rotation_sequence[1].strokes[1], rotation_sequence[-1].strokes[1])
def get_and_save_shape_distances(glyph_set_id): glyph_query = Glyph.select().where(Glyph.glyph_set_id == glyph_set_id) glyphs = [glyph for glyph in glyph_query] # Get existing glyph distances Glyph1 = Glyph.alias() Glyph2 = Glyph.alias() shape_query = (ShapeDistance.select().join( Glyph1, on=ShapeDistance.glyph1).switch(ShapeDistance).join( Glyph2, on=ShapeDistance.glyph2).where( (Glyph1.glyph_set_id == glyph_set_id) & (Glyph2.glyph_set_id == glyph_set_id))) if len(shape_query) > 0: # distances already calculated, return existing values return [s for s in shape_query] shape_distances = get_shape_distances(glyphs) with data.db.atomic(): ShapeDistance.bulk_create(shape_distances, batch_size=100) return shape_distances
def create_normalized_path(raw_char: Glyph): strokes_number = len(raw_char.strokes) normalized_path = [[] for _ in range(strokes_number)] section_length = _compute_section_length(strokes_number, raw_char.strokes) for i in range(strokes_number): stroke = raw_char.strokes[i] prev_point = stroke[0] normalized_path[i].append(prev_point) j = 1 while j < len(stroke): prev_point = normalized_path[i][-1] point = stroke[j] prev_distance = 0 points_distance = _distance(prev_point, point) k = j while points_distance < section_length and k + 1 < len(stroke): prev_point = stroke[k] point = stroke[k + 1] prev_distance = points_distance points_distance += points_distance(prev_point, point) k += 1 utvec = [point[0] - prev_point[0], point[1] - prev_point[1]] norm = points_distance(point, prev_point) j = k if k != j else j + 1 if norm == 0 or j == len(stroke): continue utvec = [utvec[0] / norm, utvec[1] / norm] path_point = (round(prev_point[0] + utvec[0] * (section_length - prev_distance)), round(prev_point[1] + utvec[1] * (section_length - prev_distance))) normalized_path[i].append(path_point) length = 0 for i in range(strokes_number): length += len(normalized_path[i]) raw_char.strokes = normalized_path
def setUpClass(cls): prep_dict = np.array(preprocessed_glyphs_dict(mapping)) prep_sample = [Glyph(**g) for g in prep_dict] cls.prep_sample = random.sample(prep_sample, 50)