def simplify_anchor_points(line: Line, max_distance: int = 25, min_distance: int = 10, min_degree_to_keep_points: float = 0.2): new_line = [] def distance(p1: Point, p2: Point): return p2.x - p1.x prev_point: Point = None for point_ind, point in enumerate(line): if prev_point is not None: point_distance = distance(prev_point, point) else: point_distance = min_distance + 1 if point_distance > max_distance: new_line.append( Point(prev_point.x + (point.x - prev_point.x) / 2, point.y) ) # [point[0], prev_point[1] + (point[1] - prev_point[1])/2]) if point_distance < min_distance: if angle_difference_of_points( prev_point, point ) > min_degree_to_keep_points or point_ind == len(line) - 1: new_line.append(point) else: new_line.append(point) prev_point = point return Line(new_line)
def polyline_simplification( staff_list: List[System], algorithm: LineSimplificationAlgorithm = LineSimplificationAlgorithm. VISVALINGAM_WHYATT, max_points_vw: int = 30, ramer_dougler_dist: float = 0.5) -> List[System]: new_staff_list = [] for system in staff_list: new_system = [] for line in system: x, y = line.get_xy() line_list = list(zip(x, y)) line_array = np.asarray(line_list, dtype=np.float64) simplified = line_list if algorithm is LineSimplificationAlgorithm.VISVALINGAM_WHYATT: simplifier = VWSimplifier(line_array) simplified = simplifier.from_number(max_points_vw) elif algorithm is LineSimplificationAlgorithm.RAMER_DOUGLER_PEUCKLER: simplified = ramerdouglas(line_list, dist=ramer_dougler_dist) simplified = [Point(x, y) for x, y in simplified] new_system.append(Line(simplified)) new_staff_list.append(System(new_system)) return new_staff_list
def smooth_lines_advanced(self, staff_lines: List[System]) -> List[System]: new_staff_lines = [] for system in staff_lines: new_system = [] for line in system: x, y = line.get_xy() if len(x) < 2: continue x, y = interpolate_sequence(x, y) append_start = [y[0] for x in range(10)] append_end = [y[-1] for x in range(10)] m_y = append_start + y + append_end remove_hill(m_y, self.settings.smooth_value_adv) line = Line([Point(x, y) for x, y in zip(x, m_y[10:-10])]) new_system.append(line) new_staff_lines.append(System(new_system)) if self.settings.smooth_lines_adv_debug: f, ax = plt.subplots(1, 2, True, True) cmap = plt.get_cmap('jet') colors = cmap(np.linspace(0, 1.0, len(new_staff_lines))) for system, color in zip(staff_lines, colors): for staff in system: x, y = staff.get_xy() ax[0].plot(x, y, color=color) for system, color in zip(new_staff_lines, colors): for staff in system: x, y = staff.get_xy() ax[1].plot(x, y, color=color) plt.show() return new_staff_lines
def prune_small_lines(line_list: List[Line], staff_space_height: int) -> List[Line]: line_list = [ l for l in line_list if l.get_end_point().x - l.get_start_point().x > staff_space_height * 3 ] mean_line_height_list = [ line.get_average_line_height() for line in line_list ] line_list_copy = line_list.copy() while True: prev_line_height = 0 for line_ind, line_height in enumerate(mean_line_height_list): if (abs(prev_line_height - line_height) < staff_space_height / 3.0) and prev_line_height != 0: p1a = line_list_copy[line_ind - 1].get_start_point() p1e = line_list_copy[line_ind - 1].get_end_point() p2a = line_list_copy[line_ind].get_start_point() p2e = line_list_copy[line_ind].get_end_point() if p2e.x >= p1e.x and p2a.x <= p1a.x: del line_list_copy[line_ind - 1] del mean_line_height_list[line_ind - 1] break if p2e.x <= p1e.x and p2a.x >= p1a.x: del line_list_copy[line_ind] del mean_line_height_list[line_ind] break if p2e.x >= p1e.x and p2a.x >= p1a.x: line_list_copy[line_ind - 1] = Line(line_list_copy[line_ind - 1] + line_list_copy[line_ind]) del line_list_copy[line_ind] del mean_line_height_list[line_ind] break if p2e.x <= p1e.x and p1a.x >= p2e.x: line_list_copy[line_ind - 1] = Line(line_list_copy[line_ind] + line_list_copy[line_ind - 1]) del line_list_copy[line_ind] del mean_line_height_list[line_ind] break prev_line_height = line_height else: break return line_list_copy
def extract_ccs(img: np.ndarray) -> List[Line]: cc_list = extract_connected_components(img) cc_list = normalize_connected_components(cc_list) cc_list_new = [] for cc in cc_list: cc_new = [] for y, x in cc: cc_new.append(Point(x, y)) cc_list_new.append(Line(cc_new)) return cc_list_new
def get_blackness_of_line(line: Line, image: np.ndarray) -> int: x_list, y_list = line.get_xy() func = interpolate.interp1d(x_list, y_list) x_start, x_end = int(x_list[0]), int(x_list[-1]) x_list_new = np.arange(x_start, x_end - 1) y_new = func(x_list_new) y_new[y_new > image.shape[0] - 1] = image.shape[0] - 1 y_new_int = np.floor(y_new + 0.5).astype(int) indexes = (np.array(y_new_int), np.array(x_list_new)) blackness = np.mean(image[indexes]) return blackness
def smooth_lines(self, staff_lines: List[System]) -> List[System]: new_staff_lines = [] for system in staff_lines: new_system = [] for line in system: x, y = line.get_xy() y = smooth_array(list(y), self.settings.smooth_value_low_pass) line = Line([Point(x, y) for x, y in zip(x, y)]) new_system.append(line) new_staff_lines.append(System(new_system)) return new_staff_lines
def approximate_blackness_of_line(line: Line, image: np.ndarray) -> int: image = image x_list, y_list = line.get_xy() func = interpolate.interp1d(x_list, y_list) x_start, x_end = x_list[0], x_list[-1] spaced_numbers = np.linspace(x_start, x_end, num=int(abs(x_list[0] - x_list[-1]) * 1 / 5), endpoint=True) y_new = func(spaced_numbers) blackness = 0 for ind, number in enumerate(y_new): if image[int(number)][int(spaced_numbers[ind])] == 255: blackness += 1 return blackness
def best_line_fit(img: np.array, line: Line, line_thickness: int = 3, max_iterations: int = 30, scale: float = 1.0, skip_startend_points: bool = False) -> Line: current_blackness = get_blackness_of_line(line, img) best_line = line.__copy__() change = True iterations = 0 while change: if iterations > max_iterations: break change = False for point_ind, point in enumerate(best_line): if skip_startend_points: if point_ind == 0 or point_ind == len(best_line): continue y, x = point.y, point.x scaled_line_thickness = line_thickness * np.ceil(scale).astype(int) for i in range(1, scaled_line_thickness + 1): if y + i < line[point_ind].y + scaled_line_thickness: test_line = best_line.__copy__() test_line[point_ind] = Point(x, y + i) blackness = get_blackness_of_line(test_line, img) if blackness < current_blackness: change = True current_blackness = blackness best_line[point_ind] = Point(x, y + i) if y - i > line[point_ind].y - scaled_line_thickness: test_line[point_ind] = Point(x, y - i) blackness = get_blackness_of_line(test_line, img) if blackness < current_blackness: change = True current_blackness = blackness best_line[point_ind] = Point(x, y - i) iterations += 1 return best_line
def post_process_staff_systems(self, staffs_lines: List[System], line_height: int, image: np.ndarray)\ -> List[System]: post_processed_staff_systems = [] h = image.shape[0] l2 = math.ceil(line_height / 2) l2 = max(l2, 2) for system in staffs_lines: processed_system = [] for staff in system: x, y = staff.get_xy() x_new, y_new = interpolate_sequence(x, y) dict_count = defaultdict(list) for i_ind, i in enumerate(y_new): st_point = min(i, image.shape[0] - 1) max_l2 = min(abs(st_point - image.shape[0]), l2 + 1) if image[st_point][x_new[i_ind]] != 0: for z in range(1, max_l2): if image[st_point - z][x_new[i_ind]] == 0: st_point = st_point - z break if image[st_point + z][x_new[i_ind]] == 0: st_point = st_point + z break yt = st_point yb = st_point if image[yt][x_new[i_ind]] == 0: dict_count[x_new[i_ind]].append(yt) while yt < h - 1: yt += 1 if image[yt][x_new[i_ind]] == 0: dict_count[x_new[i_ind]].append(yt) else: break while yb > 0: yb -= 1 if image[yb][x_new[i_ind]] == 0: dict_count[x_new[i_ind]].append(yb) else: break processed_staff = [] for key in dict_count.keys(): if len(dict_count[key]) <= line_height: processed_staff.append( Point(y=np.mean(dict_count[key]), x=key)) processed_system.append(Line(processed_staff)) post_processed_staff_systems.append(System(processed_system)) for system_ind, system in enumerate(post_processed_staff_systems): post_processed_staff_systems[system_ind] = [ lin for lin in system if lin ] post_processed_staff_systems = [ sys for sys in post_processed_staff_systems if sys ] if self.settings.post_process_debug: f, ax = plt.subplots(1, 2, True, True) ax[0].imshow(image, cmap='gray') ax[1].imshow(image, cmap='gray') cmap = plt.get_cmap('jet') colors = cmap(np.linspace(0, 1.0, len(staffs_lines))) for system, color in zip(staffs_lines, colors): for staff in system: x, y = staff.get_xy() ax[0].plot(x, y, color=color) for system, color in zip(post_processed_staff_systems, colors): for staff in system: x, y = staff.get_xy() ax[1].plot(x, y, color=color) plt.show() return post_processed_staff_systems