Ejemplo n.º 1
0
    def test_draw_onto_canvas_random_position(self):
        # Arrange
        symbol = HomusSymbol("",
                             [[Point2D(0, 0), Point2D(100, 100)]], "",
                             Rectangle(Point2D(0, 0), 100, 100))
        export_path = ExportPath("", "", "bitmap_random", "png", 2)
        bounding_boxes = dict()

        # Act
        symbol.draw_onto_canvas(export_path,
                                stroke_thickness=2,
                                margin=2,
                                destination_width=1000,
                                destination_height=1000,
                                random_position_on_canvas=True,
                                bounding_boxes=bounding_boxes)

        # Assert
        self.assertTrue(os.path.exists(export_path.get_full_path()))
        bounding_box = bounding_boxes["bitmap_random_2.png"]
        self.assertEqual(bounding_box.height, 100)
        self.assertEqual(bounding_box.width, 100)
        self.assertNotEqual(bounding_box.left, 450)
        self.assertNotEqual(bounding_box.top, 450)
        self.assertNotEqual(bounding_box.right, 550)
        self.assertNotEqual(bounding_box.bottom, 550)

        # Cleanup
        os.remove(export_path.get_full_path())
Ejemplo n.º 2
0
    def test_draw_capitan_stroke_onto_canvas(self):
        # Arrange
        symbol = CapitanSymbol.initialize_from_string(self.real_content_sample)
        export_path = ExportPath("", "", "bitmap", "png", 2)

        # Act
        symbol.draw_capitan_stroke_onto_canvas(export_path, stroke_thickness=2, margin=2)

        # Assert
        self.assertTrue(os.path.exists(export_path.get_full_path()))

        # Cleanup
        os.remove(export_path.get_full_path())
Ejemplo n.º 3
0
    def test_draw_capitan_score_bitmap(self):
        # Arrange
        symbol = CapitanSymbol.initialize_from_string(self.real_content_sample)
        export_path = ExportPath("", "", "bitmap", "png", 2)

        # Act
        symbol.draw_capitan_score_bitmap(export_path)

        # Assert
        self.assertTrue(os.path.exists(export_path.get_full_path()))

        # Cleanup
        os.remove(export_path.get_full_path())
Ejemplo n.º 4
0
    def test_draw_into_bitmap_without_larger_canvas(self):
        # Arrange
        symbol = HomusSymbol("",
                             [[Point2D(0, 0), Point2D(100, 100)]], "",
                             Rectangle(Point2D(0, 0), 100, 100))
        export_path = ExportPath("", "", "bitmap", "png", 3)

        # Act
        symbol.draw_into_bitmap(export_path, stroke_thickness=3, margin=2)

        # Assert
        self.assertTrue(os.path.exists(export_path.get_full_path()))

        # Cleanup
        os.remove(export_path.get_full_path())
Ejemplo n.º 5
0
    def draw_capitan_stroke_onto_canvas(self, export_path: ExportPath, stroke_thickness: int, margin: int):
        """
        Draws the symbol strokes onto a canvas
        :param export_path: The path, where the symbols should be created on disk
        :param stroke_thickness:
        :param margin:
        """
        width = int(self.dimensions.width + 2 * margin)
        height = int(self.dimensions.height + 2 * margin)
        offset = Point2D(self.dimensions.origin.x - margin, self.dimensions.origin.y - margin)

        image = Image.new('RGB', (width, height), "white")  # create a new white image
        draw = ImageDraw.Draw(image)
        black = (0, 0, 0)

        for i in range(0, len(self.stroke) - 1):
            start_point = self.__subtract_offset(self.stroke[i], offset)
            end_point = self.__subtract_offset(self.stroke[i + 1], offset)
            distance = self.__euclidean_distance(start_point, end_point)
            if distance > 1600:  # User moved more than 40 pixels - probably we should not draw a line here
                continue
            draw.line((start_point.x, start_point.y, end_point.x, end_point.y), black, stroke_thickness)

        del draw

        image.save(export_path.get_full_path())
        image.close()
Ejemplo n.º 6
0
 def draw_capitan_score_bitmap(self, export_path: ExportPath) -> None:
     """
     Draws the 30x30 symbol into the given file
     :param export_path: The path, where the symbols should be created on disk
     """
     with Image.fromarray(self.image_data, mode='L') as image:
         image.save(export_path.get_full_path())
Ejemplo n.º 7
0
    def test_draw_staff_lines(self):
        content = "Quarter-Note\n144,130;144,130;143,130;141,130;139,130;138,131;138,131;138,133;140,135;143,135;146," \
                  "135;150,132;154,128;155,126;153,124;150,124;146,124;142,125;140,127;140,128;141,129;144,130;149," \
                  "129;152,128;153,126;153,124;150,123;147,122;144,123;142,125;140,126;141,128;143,128;146,127;149," \
                  "126;151,124;151,122;148,121;145,122;141,125;138,129;137,131;138,132;141,132;144,131;147,128;148," \
                  "126;148,125;147,125;145,126;144,127;144,129;144,129;147,130;149,130;150,129;150,128;150,127;148," \
                  "127;147,128;147,129;147,130;148,131;151,131;153,130;153,129;154,127;152,126;150,126;148,126;147," \
                  "127;147,128;147,129;148,130;148,130;148,130;146,130;144,130;141,131;140,131;139,131;139,131;139," \
                  "131;139,131;139,131;140,131;140,133;141,137;141,143;141,150;141,158;139,172;139,180;139,188;140," \
                  "192;141,195;142,196;143,196;144,196;144,196;144,197;144,197;"
        export_path = ExportPath("", "", "test", "png", 3)
        symbol = HomusSymbol.initialize_from_string(content)

        # Act
        offsets = [18 + 7 * i for i in range(3)]  # [18,25,32]
        bounding_boxes = dict()
        symbol.draw_onto_canvas(export_path, 3, 0, 128, 224, 14, offsets,
                                bounding_boxes)

        # Assert
        bounding_box_in_image = bounding_boxes["test_3_offset_25.png"]
        self.assertEqual(bounding_box_in_image.origin,
                         Point2D(109 / 2, 147 / 2))
        self.assertEqual(bounding_box_in_image.width, 19)
        self.assertEqual(bounding_box_in_image.height, 77)

        # Cleanup
        for offset in offsets:
            os.remove(export_path.get_full_path(offset))
    def render_masks_of_crop_objects_into_image(self,
                                                crop_objects: List[CropObject],
                                                destination_directory: str):
        for crop_object in tqdm(
                crop_objects,
                desc="Generating images from crop-object masks",
                smoothing=0.1):
            symbol_class = crop_object.clsname
            # Make a copy of the mask to not temper with the original data
            mask = crop_object.mask.copy()
            # We want to draw black symbols on white canvas. The mask encodes foreground pixels
            # that we are interested in with a 1 and background pixels with a 0 and stores those values in
            # an uint8 numpy array. To use Image.fromarray, we have to generate a greyscale mask, where
            # white pixels have the value 255 and black pixels have the value 0. To achieve this, we simply
            # subtract one from each uint, and by exploiting the underflow of the uint we get the following mapping:
            # 0 (background) => 255 (white) and 1 (foreground) => 0 (black) which is exactly what we wanted.
            mask -= 1
            image = Image.fromarray(mask, mode="L")

            target_directory = os.path.join(destination_directory,
                                            symbol_class)
            os.makedirs(target_directory, exist_ok=True)

            export_path = ExportPath(destination_directory, symbol_class,
                                     crop_object.uid)
            image.save(export_path.get_full_path())
Ejemplo n.º 9
0
    def test_draw_onto_canvas(self):
        # Arrange
        symbol = HomusSymbol("",
                             [[Point2D(0, 0), Point2D(100, 100)]], "",
                             Rectangle(Point2D(0, 0), 100, 100))
        export_path = ExportPath("", "", "bitmap", "png", 2)

        # Act
        symbol.draw_onto_canvas(export_path,
                                stroke_thickness=2,
                                margin=2,
                                destination_width=150,
                                destination_height=150)

        # Assert
        self.assertTrue(os.path.exists(export_path.get_full_path()))

        # Cleanup
        os.remove(export_path.get_full_path())
Ejemplo n.º 10
0
    def test_get_full_path_without_stroke_thickness(self):
        # Arrange
        export_path = ExportPath("data/images", "3-4-Time", "1-13", "png")

        # Act
        full_path = export_path.get_full_path()

        # Assert
        full_path = full_path.replace('\\', '/')
        self.assertEqual("data/images/3-4-Time/1-13.png", full_path)
Ejemplo n.º 11
0
    def test_get_full_path_with_offset(self):
        # Arrange
        export_path = ExportPath("data/images", "3-4-Time", "1-13", "png", 3)

        # Act
        full_path = export_path.get_full_path(33)

        # Assert
        full_path = full_path.replace('\\', '/')
        self.assertEqual("data/images/3-4-Time/1-13_3_offset_33.png", full_path)
    def __extract_symbols(self, xml_file: str, image_file: str,
                          destination_directory: str):
        # xml_file, image_file = 'data/audiveris_omr_raw\\IMSLP06053p1.xml', 'data/audiveris_omr_raw\\IMSLP06053p1.png'
        # xml_file, image_file = 'data/audiveris_omr_raw\\mops-1.xml', 'data/audiveris_omr_raw\\mops-1.png'
        # xml_file, image_file = 'data/audiveris_omr_raw\\mtest1-1.xml', 'data/audiveris_omr_raw\\mtest1-1.png'
        # xml_file, image_file = 'data/audiveris_omr_raw\\mtest2-1.xml', 'data/audiveris_omr_raw\\mtest2-1.png'
        image = Image.open(image_file)
        annotations = ElementTree.parse(xml_file).getroot()
        xml_symbols = annotations.findall("Symbol")

        file_name_without_extension = os.path.splitext(
            os.path.basename(xml_file))[0]
        symbols = []

        for xml_symbol in xml_symbols:
            symbol_class = xml_symbol.get("shape")

            bounds = xml_symbol.find("Bounds")
            x, y, width, height = bounds.get("x"), bounds.get("y"), bounds.get(
                "w"), bounds.get("h")
            x, y, width, height = int(float(x)), int(float(y)), int(
                float(width)), int(float(height))

            symbol = AudiverisOmrSymbol(symbol_class, x, y, width, height)
            symbols.append(symbol)

        symbol_number = 0
        for symbol in symbols:
            symbol_class = symbol.symbol_class
            bounding_box_with_one_pixel_margin = symbol.as_bounding_box_with_margin(
                1)
            symbol_image = image.crop(bounding_box_with_one_pixel_margin)

            target_directory = os.path.join(destination_directory,
                                            symbol_class)
            os.makedirs(target_directory, exist_ok=True)

            export_path = ExportPath(
                destination_directory, symbol_class,
                file_name_without_extension + str(symbol_number))
            symbol_image.save(export_path.get_full_path())
            symbol_number += 1
Ejemplo n.º 13
0
    def draw_onto_canvas(self,
                         export_path: ExportPath,
                         stroke_thickness: int,
                         margin: int,
                         destination_width: int,
                         destination_height: int,
                         staff_line_spacing: int = 14,
                         staff_line_vertical_offsets: List[int] = None,
                         bounding_boxes: dict = None,
                         random_position_on_canvas: bool = False) -> None:
        """
        Draws the symbol onto a canvas with a fixed size

        :param bounding_boxes: The dictionary into which the bounding-boxes will be added of each generated image
        :param export_path: The path, where the symbols should be created on disk
        :param stroke_thickness:
        :param margin:
        :param destination_width:
        :param destination_height:
        :param staff_line_spacing:
        :param staff_line_vertical_offsets: Offsets used for drawing staff-lines. If None provided, no staff-lines will be drawn if multiple integers are provided, multiple images will be generated
        """
        width = self.dimensions.width + 2 * margin
        height = self.dimensions.height + 2 * margin
        if random_position_on_canvas:
            # max is required for elements that are larger than the canvas,
            # where the possible range for the random value would be negative
            random_horizontal_offset = random.randint(
                0, max(0, destination_width - width))
            random_vertical_offset = random.randint(
                0, max(0, destination_height - height))
            offset = Point2D(
                self.dimensions.origin.x - margin - random_horizontal_offset,
                self.dimensions.origin.y - margin - random_vertical_offset)
        else:
            width_offset_for_centering = (destination_width - width) / 2
            height_offset_for_centering = (destination_height - height) / 2
            offset = Point2D(
                self.dimensions.origin.x - margin - width_offset_for_centering,
                self.dimensions.origin.y - margin -
                height_offset_for_centering)

        image_without_staff_lines = Image.new(
            'RGB', (destination_width, destination_height),
            "white")  # create a new white image
        draw = ImageDraw.Draw(image_without_staff_lines)
        black = (0, 0, 0)

        for stroke in self.strokes:
            for i in range(0, len(stroke) - 1):
                start_point = self.__subtract_offset(stroke[i], offset)
                end_point = self.__subtract_offset(stroke[i + 1], offset)
                draw.line(
                    (start_point.x, start_point.y, end_point.x, end_point.y),
                    black, stroke_thickness)

        location = self.__subtract_offset(self.dimensions.origin, offset)
        bounding_box_in_image = Rectangle(location, self.dimensions.width,
                                          self.dimensions.height)
        # self.draw_bounding_box(draw, location)

        del draw

        if staff_line_vertical_offsets is not None and staff_line_vertical_offsets:
            for staff_line_vertical_offset in staff_line_vertical_offsets:
                image_with_staff_lines = image_without_staff_lines.copy()
                self.__draw_staff_lines_into_image(image_with_staff_lines,
                                                   stroke_thickness,
                                                   staff_line_spacing,
                                                   staff_line_vertical_offset)
                file_name_with_offset = export_path.get_full_path(
                    staff_line_vertical_offset)
                image_with_staff_lines.save(file_name_with_offset)
                image_with_staff_lines.close()

                if bounding_boxes is not None:
                    # Note that the ImageDatasetGenerator does not yield the full path, but only the class_name and
                    # the file_name, e.g. '3-4-Time\\1-13_3_offset_74.png', so we store only that part in the dictionary
                    class_and_file_name = export_path.get_class_name_and_file_path(
                        staff_line_vertical_offset)
                    bounding_boxes[class_and_file_name] = bounding_box_in_image
        else:
            image_without_staff_lines.save(export_path.get_full_path())
            if bounding_boxes is not None:
                # Note that the ImageDatasetGenerator does not yield the full path, but only the class_name and
                # the file_name, e.g. '3-4-Time\\1-13_3_offset_74.png', so we store only that part in the dictionary
                class_and_file_name = export_path.get_class_name_and_file_path(
                )
                bounding_boxes[class_and_file_name] = bounding_box_in_image

        image_without_staff_lines.close()