def __init__(self, glyph_classifier_fn=None): """Creates the engine and TF graph for running OMR. Args: glyph_classifier_fn: Callable that loads the glyph classifier into the graph. Accepts a `Structure` as the single argument, and returns an instance of `BaseGlyphClassifier`. The function typically loads a TF saved model or other external data, and wraps the classification in a concrete glyph classifier subclass. If the classifier uses a `StafflineExtractor` for classification, it must set the `staffline_extractor` attribute of the `Structure`. Otherwise, glyph x coordinates will not be scaled back to image coordinates. """ glyph_classifier_fn = (glyph_classifier_fn or saved_classifier_fn.build_classifier_fn()) self.graph = tf.Graph() self.session = tf.Session(graph=self.graph) with self.graph.as_default(): with self.session.as_default(): with tf.name_scope('OMREngine'): self.png_path = tf.placeholder(tf.string, name='png_path', shape=()) self.image = image.decode_music_score_png( tf.read_file(self.png_path, name='page_image')) self.structure = structure_module.create_structure( self.image) # Loading saved models happens outside of the name scope, because scopes # can rename tensors from the model and cause dangling references. # TODO(ringw): TF should be able to load models gracefully within a # name scope. self.glyph_classifier = glyph_classifier_fn(self.structure)
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)