Beispiel #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())
Beispiel #2
0
    def test_initialize_with_simple_symbol(self):
        # Arrange
        content = "test\n23,107;30,101;"
        strokes = [[Point2D(23, 107), Point2D(30, 101)]]
        dimensions = Rectangle(Point2D(23, 101), 8, 7)

        # Act
        symbol = HomusSymbol.initialize_from_string(content)

        # Assert
        self.assertIsNotNone(symbol)
        self.assertEqual("test", symbol.symbol_class)
        self.assertEqual(content, symbol.content)
        self.assertEqual(strokes, symbol.strokes)
        self.assertEqual(dimensions, symbol.dimensions)
Beispiel #3
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())
Beispiel #4
0
    def initialize_from_string(content: str) -> 'CapitanSymbol':
        """
        Create and initializes a new symbol from a string
        :param content: The content of a symbol as read from the text-file in the form <label>:<sequence>:<image>
        :return: The initialized symbol
        :rtype: CapitanSymbol
        """

        if content is None or content is "":
            return None

        parts = content.split(":")
        min_x = 100000
        max_x = 0
        min_y = 100000
        max_y = 0

        symbol_name = parts[0]

        sequence = parts[1]
        image_numbers = parts[2].split(',')
        image_data = numpy.asarray(image_numbers, numpy.uint8).reshape(
            (30, 30))

        stroke = []

        for point_string in sequence.split(";"):
            if point_string is "":
                continue  # Skip the last element, that is due to a trailing ; in each line

            point_x, point_y = point_string.split(",")
            x = float(point_x)
            y = float(point_y)
            stroke.append(SimplePoint2D(x, y))

            max_x = max(max_x, x)
            min_x = min(min_x, x)
            max_y = max(max_y, y)
            min_y = min(min_y, y)

        dimensions = Rectangle(Point2D(min_x, min_y), int(max_x - min_x + 1),
                               int(max_y - min_y + 1))
        return CapitanSymbol(content, stroke, image_data, symbol_name,
                             dimensions)
Beispiel #5
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())
    def initialize_from_string(content: str) -> 'HomusSymbol':
        """
        Create and initializes a new symbol from a string

        :param content: The content of a symbol as read from the text-file
        :return: The initialized symbol
        :rtype: HomusSymbol
        """

        if content is None or content is "":
            return None

        lines = content.splitlines()
        min_x = sys.maxsize
        max_x = 0
        min_y = sys.maxsize
        max_y = 0

        symbol_name = lines[0]
        strokes = []

        for stroke_string in lines[1:]:
            stroke = []

            for point_string in stroke_string.split(";"):
                if point_string is "":
                    continue  # Skip the last element, that is due to a trailing ; in each line

                point_x, point_y = point_string.split(",")
                x = int(point_x)
                y = int(point_y)
                stroke.append(Point2D(x, y))

                max_x = max(max_x, x)
                min_x = min(min_x, x)
                max_y = max(max_y, y)
                min_y = min(min_y, y)

            strokes.append(stroke)

        dimensions = Rectangle(Point2D(min_x, min_y), max_x - min_x + 1,
                               max_y - min_y + 1)
        return HomusSymbol(content, strokes, symbol_name, dimensions)
    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()