Ejemplo n.º 1
0
    def start_bundle(self):
        # TODO(ringw): Expose a cleaner way to set this value.
        # The image is too small for the default min staffline distance score.
        # pylint: disable=protected-access
        staffline_distance._MIN_STAFFLINE_DISTANCE_SCORE = 100

        self.omr = engine.OMREngine()
Ejemplo n.º 2
0
    def testIMSLP00823_008_mergeStandardAndBeginRepeatBars(self):
        page = engine.OMREngine().run(
            _get_imslp_path('IMSLP00823-008.png')).page[0]
        self.assertEqual(len(page.system), 6)

        self.assertEqual(len(page.system[0].staff), 2)
        self.assertEqual(len(page.system[0].bar), 6)

        self.assertEqual(len(page.system[1].staff), 2)
        self.assertEqual(len(page.system[1].bar), 6)

        self.assertEqual(len(page.system[2].staff), 2)
        self.assertEqual(len(page.system[2].bar), 7)

        self.assertEqual(len(page.system[3].staff), 2)
        self.assertEqual(len(page.system[3].bar), 6)

        self.assertEqual(len(page.system[4].staff), 2)
        self.assertEqual(len(page.system[4].bar), 6)
        # TODO(ringw): Detect BEGIN_REPEAT_BAR here.
        self.assertEqual(page.system[4].bar[0].type,
                         musicscore_pb2.StaffSystem.Bar.END_BAR)
        self.assertEqual(page.system[4].bar[1].type,
                         musicscore_pb2.StaffSystem.Bar.STANDARD_BAR)

        self.assertEqual(len(page.system[5].staff), 2)
        self.assertEqual(len(page.system[5].bar), 7)
Ejemplo n.º 3
0
 def testIMSLP39661_keySignature_CSharpMinor(self):
     page = engine.OMREngine().run(
         _get_imslp_path('IMSLP39661-000.png')).page[0]
     score_reader = reader.ScoreReader()
     score_reader.read_system(page.system[0])
     treble_sig = score_reader.score_state.staves[0].get_key_signature()
     self.assertEqual(treble_sig.get_type(), musicscore_pb2.Glyph.SHARP)
     self.assertEqual(len(treble_sig), 4)
     bass_sig = score_reader.score_state.staves[1].get_key_signature()
     self.assertEqual(bass_sig.get_type(), musicscore_pb2.Glyph.SHARP)
Ejemplo n.º 4
0
    def testIMSLP01963_106_multipleStaffSizes(self):
        page = engine.OMREngine().run(
            _get_imslp_path('IMSLP01963-106.png')).page[0]
        self.assertEqual(len(page.system), 3)

        for system in page.system:
            self.assertEqual(len(system.staff), 4)
            self.assertEqual(system.staff[0].staffline_distance, 14)
            self.assertEqual(system.staff[1].staffline_distance, 14)
            self.assertEqual(system.staff[2].staffline_distance, 22)
            self.assertEqual(system.staff[3].staffline_distance, 22)
Ejemplo n.º 5
0
    def testIMSLP00023_015_doubleNoteDots(self):
        """Tests note dots in system[1].staff[1] of the image."""
        page = engine.OMREngine().run(
            _get_imslp_path('IMSLP00023-015.png')).page[0]
        self.assertEqual(len(page.system), 6)

        system = page.system[1]
        system_measures = measures.Measures(system)
        staff = system.staff[1]

        # All dotted notes in the first measure belong to one chord, and are
        # double-dotted.
        double_dotted_notes = [
            glyph for glyph in staff.glyph
            if system_measures.get_measure(glyph) == 0 and len(glyph.dot) == 2
        ]
        for note in double_dotted_notes:
            self.assertEqual(len(note.beam), 1)
            # Double-dotted eighth note duration.
            self.assertEqual(note.note.end_time - note.note.start_time,
                             .5 + .25 + .125)
        double_dotted_note_ys = [
            glyph.y_position for glyph in double_dotted_notes
        ]
        self.assertIn(-6, double_dotted_note_ys)
        self.assertIn(-1, double_dotted_note_ys)
        self.assertIn(-3, double_dotted_note_ys)
        self.assertIn(3, double_dotted_note_ys)
        # TODO(ringw): Fix 3 dots detected at y position +4. The dots from y
        # position +3 are too close, and we should only consider a single row of
        # horizontally adjacent dots. For now, assert that there are no other notes
        # in the measure with 2 dots.
        self.assertTrue(
            set(double_dotted_note_ys).issubset([-6, -3, -1, 3, 4]),
            'No unexpected noteheads')

        # All dotted notes in the second measure belong to one chord, and are
        # single-dotted.
        single_dotted_notes = [
            glyph for glyph in staff.glyph
            if system_measures.get_measure(glyph) == 1 and len(glyph.dot) == 1
        ]
        for note in single_dotted_notes:
            self.assertEqual(len(note.beam), 1)
            # Single-dotted eighth note duration.
            self.assertEqual(note.note.end_time - note.note.start_time, .75)
        single_dotted_note_ys = [
            glyph.y_position for glyph in single_dotted_notes
        ]
        self.assertIn(-5, single_dotted_note_ys)
        self.assertIn(-3, single_dotted_note_ys)
Ejemplo n.º 6
0
  def testGetPage_x_scale(self):
    # Random staffline images matching the dimensions of PREDICTIONS.
    dummy_stafflines = np.random.random((2, 3, 5, 6))
    classifier = glyphs_testing.DummyGlyphClassifier(glyphs_testing.PREDICTIONS)
    image = np.random.randint(0, 255, (30, 20), dtype=np.uint8)
    staves = staves_testing.FakeStaves(
        image_t=image,
        staves_t=np.asarray([[[0, 10], [19, 10]], [[0, 20], [19, 20]]],
                            np.int32),
        staffline_distance_t=np.asarray([5, 20], np.int32),
        staffline_thickness_t=np.asarray(1, np.int32))
    structure = structure_module.create_structure(image,
                                                  lambda unused_image: staves)

    class DummyStafflineExtractor(object):
      """A placeholder for StafflineExtractor.

      It only contains the constants necessary to scale the x coordinates.
      """
      staffline_distance_multiple = 2
      target_height = 10

    omr = engine.OMREngine(lambda _: classifier)
    page = omr.process_image(
        # Feed in a dummy image. It doesn't matter because FakeStaves has
        # hard-coded staff values.
        np.random.randint(0, 255, (100, 100)),
        process_structure=False)
    page = staff_processor.StaffProcessor(structure,
                                          DummyStafflineExtractor()).apply(page)
    self.assertEqual(len(page.system[0].staff), 2)
    # The first staff has a staffline distance of 5.
    # The extracted staffline slices have an original height of
    # staffline_distance * staffline_distance_multiple (10), which equals
    # target_height here, so there is no scaling.
    self.assertEqual(
        musicscore_pb2.Staff(glyph=page.system[0].staff[0].glyph),
        glyphs_testing.GLYPHS_PAGE.system[0].staff[0])
    # Glyphs in the second staff have a scaled x coordinate.
    self.assertEqual(
        len(page.system[0].staff[1].glyph),
        len(glyphs_testing.GLYPHS_PAGE.system[0].staff[1].glyph))
    for glyph in glyphs_testing.GLYPHS_PAGE.system[0].staff[1].glyph:
      expected_glyph = copy.deepcopy(glyph)
      # The second staff has a staffline distance of 20. The extracted staffline
      # slice would be 4 times the size of the scaled staffline, so x
      # coordinates are scaled by 4. Also, the glyphs may be in a different
      # order.
      expected_glyph.x *= 4
      self.assertIn(expected_glyph, page.system[0].staff[1].glyph)
Ejemplo n.º 7
0
def run(input_pngs, glyphs_saved_model=None, output_notesequence=False):
  """Runs OMR over a list of input images.

  Args:
    input_pngs: A list of PNG filenames to process.
    glyphs_saved_model: Optional saved model dir to override the included model.
    output_notesequence: Whether to return a NoteSequence, as opposed to a Score
      containing Pages with Glyphs.

  Returns:
    A NoteSequence message, or a Score message holding Pages for each input
        image (with their detected Glyphs).
  """
  return engine.OMREngine(
      saved_classifier_fn.build_classifier_fn(glyphs_saved_model)).run(
          input_pngs, output_notesequence=output_notesequence)
    def testEndToEnd(self):
        with tempfile.TemporaryDirectory() as tmpdir:
            with engine.get_included_labels_file() as centroids:
                export_dir = os.path.join(tmpdir, 'export')
                export_kmeans_centroids.run(centroids.name, export_dir)

            # Now load the saved model.
            omr = engine.OMREngine(
                glyph_classifier_fn=saved_classifier.
                SavedConvolutional1DClassifier.glyph_classifier_fn(export_dir))
            filename = os.path.join(tf.resource_loader.get_data_files_path(),
                                    '../testdata/IMSLP00747-000.png')
            notes = omr.run(filename, output_notesequence=True)
            # TODO(ringw): Fix the extra note that is detected before the actual
            # first eighth note.
            self.assertEqual(librosa.note_to_midi('C4'), notes.notes[1].pitch)
            self.assertEqual(librosa.note_to_midi('D4'), notes.notes[2].pitch)
            self.assertEqual(librosa.note_to_midi('E4'), notes.notes[3].pitch)
Ejemplo n.º 9
0
def main(argv):
    pages = argv[1:]
    assert pages, 'Pass one or more PNG files'
    omr = engine.OMREngine()
    for i, filename in enumerate(pages):
        escaped_filename = re.sub(r'([\'\\])', r'\\\0', filename)
        page = omr.run(filename).page[0]
        # TODO(ringw): Use a real templating system (e.g. jinja or mako).
        if i > 0:
            print('')
        print('  def test%s_structure(self):' % _sanitized_basename(filename))
        print('    page = engine.OMREngine().run(')
        print('        \'%s\').page[0]' % escaped_filename)
        print('    self.assertEqual(len(page.system), %d)' % len(page.system))
        for i, system in enumerate(page.system):
            print('')
            print('    self.assertEqual(len(page.system[%d].staff), %d)' %
                  (i, len(system.staff)))
            print('    self.assertEqual(len(page.system[%d].bar), %d)' %
                  (i, len(system.bar)))
Ejemplo n.º 10
0
    def testIMSLP00304_038_MultipleStaffSizes(self):
        # Image has staff systems with different numbers of staves, some of which
        # contain staves slightly smaller than the others.
        page = engine.OMREngine().run(
            _get_imslp_path('IMSLP00304-038.png')).page[0]
        self.assertEqual(len(page.system), 3)

        self.assertEqual(len(page.system[0].staff), 4)
        self.assertEqual(page.system[0].staff[0].staffline_distance, 19)
        self.assertEqual(page.system[0].staff[1].staffline_distance, 19)
        self.assertEqual(page.system[0].staff[2].staffline_distance, 16)
        self.assertEqual(page.system[0].staff[3].staffline_distance, 16)

        self.assertEqual(len(page.system[1].staff), 2)
        self.assertEqual(page.system[1].staff[0].staffline_distance, 19)
        self.assertEqual(page.system[1].staff[1].staffline_distance, 19)

        self.assertEqual(len(page.system[2].staff), 4)
        self.assertEqual(page.system[2].staff[0].staffline_distance, 19)
        self.assertEqual(page.system[2].staff[1].staffline_distance, 19)
        self.assertEqual(page.system[2].staff[2].staffline_distance, 16)
        self.assertEqual(page.system[2].staff[3].staffline_distance, 16)
Ejemplo n.º 11
0
    def testIMSLP00823_000_structure(self):
        page = engine.OMREngine().run(
            _get_imslp_path('IMSLP00823-000.png')).page[0]
        self.assertEqual(len(page.system), 6)

        self.assertEqual(len(page.system[0].staff), 2)
        self.assertEqual(len(page.system[0].bar), 7)

        self.assertEqual(len(page.system[1].staff), 2)
        self.assertEqual(len(page.system[1].bar), 7)

        self.assertEqual(len(page.system[2].staff), 2)
        # TODO(ringw): Detect thick repeat barlines correctly.
        # page.system[2] should have 6 bars.

        self.assertEqual(len(page.system[3].staff), 2)
        self.assertEqual(len(page.system[3].bar), 6)

        self.assertEqual(len(page.system[4].staff), 2)
        # TODO(ringw): Fix. page.system[4] should have 6 bars.

        self.assertEqual(len(page.system[5].staff), 2)
        self.assertEqual(len(page.system[5].bar), 6)
Ejemplo n.º 12
0
    def testIMSLP00823_000_structure(self):
        page = engine.OMREngine().run(
            _get_imslp_path('IMSLP00823-000.png')).page[0]
        self.assertEqual(len(page.system), 6)

        self.assertEqual(len(page.system[0].staff), 2)
        self.assertEqual(len(page.system[0].bar), 7)

        self.assertEqual(len(page.system[1].staff), 2)
        self.assertEqual(len(page.system[1].bar), 7)

        self.assertEqual(len(page.system[2].staff), 2)
        self.assertEqual(len(page.system[2].bar), 6)

        self.assertEqual(len(page.system[3].staff), 2)
        self.assertEqual(len(page.system[3].bar), 6)

        self.assertEqual(len(page.system[4].staff), 2)
        # TODO(ringw): Fix barline detection here.
        # self.assertEqual(len(page.system[4].bar), 6)

        self.assertEqual(len(page.system[5].staff), 2)
        self.assertEqual(len(page.system[5].bar), 6)
Ejemplo n.º 13
0
    def testIMSLP00023_015_doubleNoteDots(self):
        """Tests note dots in system[1].staff[1] of the image."""
        page = engine.OMREngine().run(
            _get_imslp_path('IMSLP00023-015.png')).page[0]
        self.assertEqual(len(page.system), 6)

        system = page.system[1]
        system_measures = measures.Measures(system)
        staff = system.staff[1]

        # All dotted notes in the first measure belong to one chord, and are
        # double-dotted.
        double_dotted_notes = [
            glyph for glyph in staff.glyph
            if system_measures.get_measure(glyph) == 0 and len(glyph.dot) == 2
        ]
        for note in double_dotted_notes:
            self.assertEqual(len(note.beam), 1)
            # Double-dotted eighth note duration.
            self.assertEqual(note.note.end_time - note.note.start_time,
                             .5 + .25 + .125)
        double_dotted_note_ys = [
            glyph.y_position for glyph in double_dotted_notes
        ]
        self.assertIn(-6, double_dotted_note_ys)
        self.assertIn(-3, double_dotted_note_ys)
        self.assertIn(-1, double_dotted_note_ys)
        self.assertTrue(
            set(double_dotted_note_ys).issubset([-6, -3, -1, +3, +4]),
            'No unexpected double-dotted noteheads')

        # TODO(ringw): Notehead at +4 picks up extra dots (4 total). The dots
        # should be in a horizontal line, and we should discard other dots.
        # There should only be one notehead at +4 with 2 or more dots.
        self.assertEqual(
            len([
                glyph for glyph in staff.glyph
                if system_measures.get_measure(glyph) == 0
                and glyph.type == NOTEHEAD_FILLED and glyph.y_position == +4
                and len(glyph.dot) >= 2
            ]), 1)

        # All dotted notes in the second measure belong to one chord, and are
        # single-dotted.
        single_dotted_notes = [
            glyph for glyph in staff.glyph
            if system_measures.get_measure(glyph) == 1 and len(glyph.dot) == 1
        ]
        for note in single_dotted_notes:
            if note.y_position == +2:
                # TODO(ringw): Detect the beam for this notehead. Its stem is too
                # short.
                continue
            self.assertEqual(len(note.beam), 1)
            # Single-dotted eighth note duration.
            self.assertEqual(note.note.end_time - note.note.start_time, .75)
        single_dotted_note_ys = [
            glyph.y_position for glyph in single_dotted_notes
        ]
        self.assertIn(-5, single_dotted_note_ys)
        self.assertIn(-3, single_dotted_note_ys)
        self.assertIn(0, single_dotted_note_ys)
        self.assertIn(+2, single_dotted_note_ys)
        # TODO(ringw): Detect the dot for the note at y position +4.
        self.assertTrue(
            set(single_dotted_note_ys).issubset([-5, -3, 0, +2, +4]))
Ejemplo n.º 14
0
 def setUp(self):
   self.engine = engine.OMREngine()
Ejemplo n.º 15
0
 def __init__(self, **kwargs):
   self.omr = engine.OMREngine(**kwargs)