def test_true_segments_1d_large(self): # Arbitrary boolean array to get True and False runs from. run_values = [False, True, False, True, False, True, False, True] run_lengths = [3, 5, 2, 6, 4, 8, 7, 1] values = tf.constant(np.repeat(run_values, run_lengths)) centers, lengths = segments.true_segments_1d( values, mode=segments.SegmentsMode.CENTERS) with self.test_session(): self.assertAllEqual(centers.eval(), [ sum(run_lengths[:1]) + (run_lengths[1] - 1) // 2, sum(run_lengths[:3]) + (run_lengths[3] - 1) // 2, sum(run_lengths[:5]) + (run_lengths[5] - 1) // 2, sum(run_lengths[:7]) + (run_lengths[7] - 1) // 2 ]) self.assertAllEqual(lengths.eval(), run_lengths[1::2]) starts, lengths = segments.true_segments_1d( values, mode=segments.SegmentsMode.STARTS) with self.test_session(): self.assertAllEqual(starts.eval(), [ sum(run_lengths[:1]), sum(run_lengths[:3]), sum(run_lengths[:5]), sum(run_lengths[:7]) ]) self.assertAllEqual(lengths.eval(), run_lengths[1::2])
def test_true_segments_1d_max_gap(self): # Arbitrary boolean array to get True and False runs from. values = tf.constant([ False, False, True, True, True, False, False, True, False, False, False, False, False, False, True, True, True, True, False, True, True, False, False, True, ]) # pyformat: disable centers, lengths = segments.true_segments_1d(values, max_gap=0) with self.test_session(): self.assertAllEqual(centers.eval(), [3, 7, 15, 19, 23]) self.assertAllEqual(lengths.eval(), [3, 1, 4, 2, 1]) centers, lengths = segments.true_segments_1d(values, max_gap=1) with self.test_session(): self.assertAllEqual(centers.eval(), [3, 7, 17, 23]) self.assertAllEqual(lengths.eval(), [3, 1, 7, 1]) for max_gap in range(2, 6): centers, lengths = segments.true_segments_1d(values, max_gap=max_gap) with self.test_session(): self.assertAllEqual(centers.eval(), [4, 18]) self.assertAllEqual(lengths.eval(), [6, 10]) centers, lengths = segments.true_segments_1d(values, max_gap=6) with self.test_session(): self.assertAllEqual(centers.eval(), [12]) self.assertAllEqual(lengths.eval(), [22])
def test_true_segments_1d(self): # Arbitrary boolean array to get True and False runs from. values = tf.constant([True, True, True, False, True, False, True, True]) centers, lengths = segments.true_segments_1d( values, mode=segments.SegmentsMode.CENTERS) with self.test_session(): self.assertAllEqual(centers.eval(), [1, 4, 6]) self.assertAllEqual(lengths.eval(), [3, 1, 2]) starts, lengths = segments.true_segments_1d( values, mode=segments.SegmentsMode.STARTS) with self.test_session(): self.assertAllEqual(starts.eval(), [0, 4, 6]) self.assertAllEqual(lengths.eval(), [3, 1, 2])
def _verticals_in_column(self, max_gap, column): """Gets the verticals from a single column. Args: max_gap: The scalar max_gap value to use. int tensor. column: The scalar column index. int tensor. Returns: int32 tensor of shape (num_lines_in_column, 2, 2). All start_x and end_x values are equal to column. """ image_column = self.filtered_image[:, column] run_starts, run_lengths = segments.true_segments_1d( image_column, mode=segments.SegmentsMode.STARTS, max_gap=max_gap, min_length=self.min_length) num_runs = tf.shape(run_starts)[0] # x is the same for all runs in the column. x = tf.fill([num_runs], column) y0 = run_starts y1 = run_starts + run_lengths - 1 return tf.stack( [ tf.stack([x, y0], axis=1), tf.stack([x, y1], axis=1), ], axis=1)
def _test_true_segments_1d_min_length(self, min_length): # Arbitrary boolean array to get True and False runs from. values = tf.constant([ False, False, False, True, False, True, True, False, True, False, True, True, True, True, False, True, True, ]) # pyformat: disable all_centers = np.asarray([3, 5, 8, 11, 15]) all_lengths = np.asarray([1, 2, 1, 4, 2]) expected_centers = all_centers[all_lengths >= min_length] expected_lengths = all_lengths[all_lengths >= min_length] centers, lengths = segments.true_segments_1d(values, min_length=min_length) with self.test_session(): self.assertAllEqual(expected_centers, centers.eval()) self.assertAllEqual(expected_lengths, lengths.eval())
def test_true_segments_1d_empty(self): for mode in list(segments.SegmentsMode): for max_gap in [0, 1]: centers, lengths = segments.true_segments_1d( [], mode=mode, max_gap=max_gap) with self.test_session(): self.assertAllEqual(centers.eval(), []) self.assertAllEqual(lengths.eval(), [])
def _process_column(i): """Removes staves from a single column of the image. Args: i: The index of the column to remove. Returns: The single column of the image with staff lines erased. """ column = image[:, i] # Identify runs in the column that correspond to staff lines and can be # erased. runs, run_lengths = segments.true_segments_1d( column < self.threshold) column_staffline_ys = all_staffline_center_ys[:, :, i] # The run center has to be within staffline_thickness of a staff line. run_matches_staffline = tf.less_equal( tf.reduce_min(tf.abs(runs[:, None, None] - column_staffline_ys[None, :, :]), axis=[1, 2]), self.staff_detector.staffline_thickness) keep_run = tf.logical_and(run_lengths < max_runlength, run_matches_staffline) keep_run.set_shape([None]) runs = tf.boolean_mask(runs, keep_run) run_lengths = tf.boolean_mask(run_lengths, keep_run) def do_process_column(runs, run_lengths): """Process the column if there are any runs matching staff lines. Args: runs: The center of each vertical run. run_lengths: The length of each vertical run. Returns: The column of the image with staff lines erased. """ # Erase ys that belong to a run corresponding to a staff line. y_run_pair_distance = tf.abs(ys[:, None] - runs[None, :]) y_runs = tf.argmin(y_run_pair_distance, axis=1) y_run_distance = tf.reduce_min(y_run_pair_distance, axis=1) y_run_lengths = tf.gather(run_lengths, y_runs) erase_y = tf.less_equal(y_run_distance, tf.floordiv(y_run_lengths, 2)) white_column = tf.fill(tf.shape(column), tf.constant(255, tf.uint8)) return tf.where(erase_y, white_column, column) return tf.cond( tf.shape(runs)[0] > 0, lambda: do_process_column(runs, run_lengths), lambda: column)
def _test_true_segments_1d_all_false(self, length): centers, lengths = segments.true_segments_1d(tf.zeros(length, tf.bool)) with self.test_session(): self.assertAllEqual(centers.eval(), []) self.assertAllEqual(lengths.eval(), [])
def _get_staff_ys(is_staff, staffline_thickness): # Return the detected staves--segments in is_staff that are roughly not much # bigger than staffline_thickness. segment_ys, segment_sizes = segments.true_segments_1d(is_staff) return tf.boolean_mask(segment_ys, segment_sizes <= staffline_thickness * 2)