File size: 5,203 Bytes
29f689c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import cv2


def padding_image(img, size=(640, 640)):
    """
    Padding an image using OpenCV:
    - If the image is smaller than the target size, pad it to 640x640.
    - If the image is larger than the target size, split it into multiple 640x640 images and record positions.

    :param image_path: Path to the input image.
    :param output_dir: Directory to save the output images.
    :param size: The target size for padding or splitting (default 640x640).
    :return: List of tuples containing the coordinates of the top-left corner of each cropped 640x640 image.
    """

    img_height, img_width = img.shape[:2]
    target_width, target_height = size

    # If image is smaller than target size, pad the image to 640x640

    # Calculate padding amounts (top, bottom, left, right)
    pad_top = 0
    pad_bottom = target_height - img_height
    pad_left = 0
    pad_right = target_width - img_width

    # Pad the image (white padding, border type: constant)
    padded_img = cv2.copyMakeBorder(img,
                                    pad_top,
                                    pad_bottom,
                                    pad_left,
                                    pad_right,
                                    cv2.BORDER_CONSTANT,
                                    value=[0, 0, 0])

    # Return the padded area positions (top-left and bottom-right coordinates of the original image)
    return padded_img


class CropResize(object):

    def __init__(self, size=(640, 640), interpolation=cv2.INTER_LINEAR):
        self.size = size
        self.interpolation = interpolation

    def __call__(self, data):
        """
        Resize an image using OpenCV:
        - If the image is smaller than the target size, pad it to 640x640.
        - If the image is larger than the target size, split it into multiple 640x640 images and record positions.

        :param image_path: Path to the input image.
        :param output_dir: Directory to save the output images.
        :param size: The target size for padding or splitting (default 640x640).
        :return: List of tuples containing the coordinates of the top-left corner of each cropped 640x640 image.
        """
        img = data['image']
        img_height, img_width = img.shape[:2]
        target_width, target_height = self.size

        # If image is smaller than target size, pad the image to 640x640
        if img_width <= target_width and img_height <= target_height:
            # Calculate padding amounts (top, bottom, left, right)
            if img_width == target_width and img_height == target_height:
                return [img], [[0, 0, img_width, img_height]]
            padded_img = padding_image(img, self.size)

            # Return the padded area positions (top-left and bottom-right coordinates of the original image)
            return [padded_img], [[0, 0, img_width, img_height]]

        if img_width < target_width:
            img = cv2.copyMakeBorder(img,
                                     0,
                                     0,
                                     0,
                                     target_width - img_width,
                                     cv2.BORDER_CONSTANT,
                                     value=[0, 0, 0])

        if img_height < target_height:
            img = cv2.copyMakeBorder(img,
                                     0,
                                     target_height - img_height,
                                     0,
                                     0,
                                     cv2.BORDER_CONSTANT,
                                     value=[0, 0, 0])
            # raise ValueError("Image dimensions must be greater than or equal to target size")

        img_height, img_width = img.shape[:2]
        # If image is larger than or equal to target size, crop it into 640x640 tiles
        crop_positions = []
        count = 0
        cropped_img_list = []
        for top in range(0, img_height - target_height // 2,
                         target_height // 2):
            for left in range(0, img_width - target_height // 2,
                              target_width // 2):
                # Calculate the bottom and right boundaries for the crop
                right = min(left + target_width, img_width)
                bottom = min(top + target_height, img_height)
                if right > img_width:
                    right = img_width
                    left = max(0, right - target_width)
                if bottom > img_height:
                    bottom = img_height
                    top = max(0, bottom - target_height)
                # Crop the image
                cropped_img = img[top:bottom, left:right]
                if bottom - top < target_height or right - left < target_width:
                    cropped_img = padding_image(cropped_img, self.size)

                count += 1
                cropped_img_list.append(cropped_img)

                # Record the position of the cropped image
                crop_positions.append([left, top, right, bottom])

        # print(f"Images cropped and saved at {output_dir}.")

        return cropped_img_list, crop_positions