vkit.mechanism.cropper

  1# Copyright 2022 vkit-x Administrator. All Rights Reserved.
  2#
  3# This project (vkit-x/vkit) is dual-licensed under commercial and SSPL licenses.
  4#
  5# The commercial license gives you the full rights to create and distribute software
  6# on your own terms without any SSPL license obligations. For more information,
  7# please see the "LICENSE_COMMERCIAL.txt" file.
  8#
  9# This project is also available under Server Side Public License (SSPL).
 10# The SSPL licensing is ideal for use cases such as open source projects with
 11# SSPL distribution, student/academic purposes, hobby projects, internal research
 12# projects without external distribution, or other projects where all SSPL
 13# obligations can be met. For more information, please see the "LICENSE_SSPL.txt" file.
 14from typing import Tuple
 15
 16import attrs
 17from numpy.random import Generator as RandomGenerator
 18
 19from vkit.element import (
 20    Point,
 21    Box,
 22    Mask,
 23    ScoreMap,
 24    Image,
 25)
 26
 27
 28@attrs.define
 29class CropperState:
 30    height: int
 31    width: int
 32    pad_value: int
 33    crop_size: int
 34    origin_box: Box
 35    target_box: Box
 36    core_box: Box
 37    origin_core_box: Box
 38
 39    @classmethod
 40    def sample_cropping_positions(
 41        cls,
 42        core_size: int,
 43        pad_size: int,
 44        crop_size: int,
 45        length: int,
 46        rng: RandomGenerator,
 47    ):
 48        if core_size <= length:
 49            core_begin = rng.integers(0, length - core_size + 1)
 50            begin = core_begin - pad_size
 51            offset = 0
 52            if begin < 0:
 53                offset = abs(begin)
 54                begin = 0
 55
 56        else:
 57            begin = 0
 58            offset = pad_size
 59            offset += rng.integers(0, core_size - length + 1)
 60
 61        end = min(length - 1, begin + (crop_size - offset) - 1)
 62        return offset, begin, end
 63
 64    @classmethod
 65    def sample_cropper_state(
 66        cls,
 67        height: int,
 68        width: int,
 69        core_size: int,
 70        pad_size: int,
 71        crop_size: int,
 72        rng: RandomGenerator,
 73    ):
 74        vert_offset, up, down = cls.sample_cropping_positions(
 75            core_size=core_size,
 76            pad_size=pad_size,
 77            crop_size=crop_size,
 78            length=height,
 79            rng=rng,
 80        )
 81        hori_offset, left, right = cls.sample_cropping_positions(
 82            core_size=core_size,
 83            pad_size=pad_size,
 84            crop_size=crop_size,
 85            length=width,
 86            rng=rng,
 87        )
 88        return (
 89            vert_offset,
 90            up,
 91            down,
 92            hori_offset,
 93            left,
 94            right,
 95        )
 96
 97    @classmethod
 98    def create_from_cropping_positions(
 99        cls,
100        height: int,
101        width: int,
102        pad_size: int,
103        pad_value: int,
104        core_size: int,
105        crop_size: int,
106        vert_offset: int,
107        up: int,
108        down: int,
109        hori_offset: int,
110        left: int,
111        right: int,
112    ):
113        origin_box = Box(
114            up=up,
115            down=down,
116            left=left,
117            right=right,
118        )
119
120        target_box = Box(
121            up=vert_offset,
122            down=vert_offset + origin_box.height - 1,
123            left=hori_offset,
124            right=hori_offset + origin_box.width - 1,
125        )
126
127        core_begin = pad_size
128        core_end = core_begin + core_size - 1
129        core_box = Box(
130            up=core_begin,
131            down=core_end,
132            left=core_begin,
133            right=core_end,
134        )
135
136        origin_core_box = Box(
137            up=up + core_box.up - target_box.up,
138            down=down + core_box.down - target_box.down,
139            left=left + core_box.left - target_box.left,
140            right=right + core_box.right - target_box.right,
141        )
142
143        return CropperState(
144            height=height,
145            width=width,
146            pad_value=pad_value,
147            crop_size=crop_size,
148            origin_box=origin_box,
149            target_box=target_box,
150            core_box=core_box,
151            origin_core_box=origin_core_box,
152        )
153
154    @classmethod
155    def create(
156        cls,
157        shape: Tuple[int, int],
158        core_size: int,
159        pad_size: int,
160        pad_value: int,
161        rng: RandomGenerator,
162    ):
163        height, width = shape
164        crop_size = 2 * pad_size + core_size
165        (
166            vert_offset,
167            up,
168            down,
169            hori_offset,
170            left,
171            right,
172        ) = cls.sample_cropper_state(
173            height=height,
174            width=width,
175            core_size=core_size,
176            pad_size=pad_size,
177            crop_size=crop_size,
178            rng=rng,
179        )
180        return cls.create_from_cropping_positions(
181            height=height,
182            width=width,
183            pad_size=pad_size,
184            pad_value=pad_value,
185            core_size=core_size,
186            crop_size=crop_size,
187            vert_offset=vert_offset,
188            up=up,
189            down=down,
190            hori_offset=hori_offset,
191            left=left,
192            right=right,
193        )
194
195    @classmethod
196    def create_from_center_point(
197        cls,
198        shape: Tuple[int, int],
199        core_size: int,
200        pad_size: int,
201        pad_value: int,
202        center_point: Point,
203    ):
204        height, width = shape
205        crop_size = 2 * pad_size + core_size
206
207        assert 0 <= center_point.y < height
208        assert 0 <= center_point.x < width
209
210        vert_offset = 0
211        up = center_point.y - crop_size // 2
212        down = up + crop_size - 1
213        if up < 0:
214            vert_offset = abs(up)
215            up = 0
216        down = min(height - 1, down)
217
218        hori_offset = 0
219        left = center_point.x - crop_size // 2
220        right = left + crop_size - 1
221        if left < 0:
222            hori_offset = abs(left)
223            left = 0
224        right = min(width - 1, right)
225
226        return CropperState.create_from_cropping_positions(
227            height=height,
228            width=width,
229            pad_size=pad_size,
230            pad_value=pad_value,
231            core_size=core_size,
232            crop_size=crop_size,
233            vert_offset=vert_offset,
234            up=up,
235            down=down,
236            hori_offset=hori_offset,
237            left=left,
238            right=right,
239        )
240
241    @property
242    def need_post_filling(self):
243        return self.origin_box.height != self.crop_size or self.origin_box.width != self.crop_size
244
245    @property
246    def cropped_shape(self):
247        return (self.crop_size,) * 2
248
249
250class Cropper:
251
252    @classmethod
253    def create(
254        cls,
255        shape: Tuple[int, int],
256        core_size: int,
257        pad_size: int,
258        rng: RandomGenerator,
259        pad_value: int = 0,
260    ):
261        cropper_state = CropperState.create(
262            shape=shape,
263            core_size=core_size,
264            pad_size=pad_size,
265            pad_value=pad_value,
266            rng=rng,
267        )
268        return Cropper(cropper_state)
269
270    @classmethod
271    def create_from_center_point(
272        cls,
273        shape: Tuple[int, int],
274        core_size: int,
275        pad_size: int,
276        center_point: Point,
277        pad_value: int = 0,
278    ):
279        cropper_state = CropperState.create_from_center_point(
280            shape=shape,
281            core_size=core_size,
282            pad_size=pad_size,
283            pad_value=pad_value,
284            center_point=center_point,
285        )
286        return Cropper(cropper_state)
287
288    def __init__(self, cropper_state: CropperState):
289        self.cropper_state = cropper_state
290
291    @property
292    def origin_box(self):
293        return self.cropper_state.origin_box
294
295    @property
296    def target_box(self):
297        return self.cropper_state.target_box
298
299    @property
300    def core_box(self):
301        return self.cropper_state.core_box
302
303    @property
304    def origin_core_box(self):
305        return self.cropper_state.origin_core_box
306
307    @property
308    def need_post_filling(self):
309        return self.cropper_state.need_post_filling
310
311    @property
312    def crop_size(self):
313        return self.cropper_state.crop_size
314
315    @property
316    def cropped_shape(self):
317        return self.cropper_state.cropped_shape
318
319    @property
320    def pad_value(self):
321        return self.cropper_state.pad_value
322
323    def crop_mask(self, mask: Mask, core_only: bool = False):
324        mask = self.origin_box.extract_mask(mask)
325
326        if self.need_post_filling:
327            new_mask = Mask.from_shape(self.cropped_shape)
328            self.target_box.fill_mask(new_mask, mask)
329            mask = new_mask
330
331        if core_only:
332            mask = self.core_box.extract_mask(mask)
333            mask = mask.to_box_attached(self.core_box)
334
335        return mask
336
337    def crop_score_map(self, score_map: ScoreMap, core_only: bool = False):
338        score_map = self.origin_box.extract_score_map(score_map)
339
340        if self.need_post_filling:
341            new_score_map = ScoreMap.from_shape(
342                self.cropped_shape,
343                is_prob=score_map.is_prob,
344            )
345            self.target_box.fill_score_map(new_score_map, score_map)
346            score_map = new_score_map
347
348        if core_only:
349            score_map = self.core_box.extract_score_map(score_map)
350            score_map = score_map.to_box_attached(self.core_box)
351
352        return score_map
353
354    def crop_image(self, image: Image):
355        image = self.origin_box.extract_image(image)
356
357        if self.need_post_filling:
358            new_image = Image.from_shape(
359                self.cropped_shape,
360                num_channels=image.num_channels,
361                value=self.pad_value,
362            )
363            self.target_box.fill_image(new_image, image)
364            image = new_image
365
366        return image
class CropperState:
 30class CropperState:
 31    height: int
 32    width: int
 33    pad_value: int
 34    crop_size: int
 35    origin_box: Box
 36    target_box: Box
 37    core_box: Box
 38    origin_core_box: Box
 39
 40    @classmethod
 41    def sample_cropping_positions(
 42        cls,
 43        core_size: int,
 44        pad_size: int,
 45        crop_size: int,
 46        length: int,
 47        rng: RandomGenerator,
 48    ):
 49        if core_size <= length:
 50            core_begin = rng.integers(0, length - core_size + 1)
 51            begin = core_begin - pad_size
 52            offset = 0
 53            if begin < 0:
 54                offset = abs(begin)
 55                begin = 0
 56
 57        else:
 58            begin = 0
 59            offset = pad_size
 60            offset += rng.integers(0, core_size - length + 1)
 61
 62        end = min(length - 1, begin + (crop_size - offset) - 1)
 63        return offset, begin, end
 64
 65    @classmethod
 66    def sample_cropper_state(
 67        cls,
 68        height: int,
 69        width: int,
 70        core_size: int,
 71        pad_size: int,
 72        crop_size: int,
 73        rng: RandomGenerator,
 74    ):
 75        vert_offset, up, down = cls.sample_cropping_positions(
 76            core_size=core_size,
 77            pad_size=pad_size,
 78            crop_size=crop_size,
 79            length=height,
 80            rng=rng,
 81        )
 82        hori_offset, left, right = cls.sample_cropping_positions(
 83            core_size=core_size,
 84            pad_size=pad_size,
 85            crop_size=crop_size,
 86            length=width,
 87            rng=rng,
 88        )
 89        return (
 90            vert_offset,
 91            up,
 92            down,
 93            hori_offset,
 94            left,
 95            right,
 96        )
 97
 98    @classmethod
 99    def create_from_cropping_positions(
100        cls,
101        height: int,
102        width: int,
103        pad_size: int,
104        pad_value: int,
105        core_size: int,
106        crop_size: int,
107        vert_offset: int,
108        up: int,
109        down: int,
110        hori_offset: int,
111        left: int,
112        right: int,
113    ):
114        origin_box = Box(
115            up=up,
116            down=down,
117            left=left,
118            right=right,
119        )
120
121        target_box = Box(
122            up=vert_offset,
123            down=vert_offset + origin_box.height - 1,
124            left=hori_offset,
125            right=hori_offset + origin_box.width - 1,
126        )
127
128        core_begin = pad_size
129        core_end = core_begin + core_size - 1
130        core_box = Box(
131            up=core_begin,
132            down=core_end,
133            left=core_begin,
134            right=core_end,
135        )
136
137        origin_core_box = Box(
138            up=up + core_box.up - target_box.up,
139            down=down + core_box.down - target_box.down,
140            left=left + core_box.left - target_box.left,
141            right=right + core_box.right - target_box.right,
142        )
143
144        return CropperState(
145            height=height,
146            width=width,
147            pad_value=pad_value,
148            crop_size=crop_size,
149            origin_box=origin_box,
150            target_box=target_box,
151            core_box=core_box,
152            origin_core_box=origin_core_box,
153        )
154
155    @classmethod
156    def create(
157        cls,
158        shape: Tuple[int, int],
159        core_size: int,
160        pad_size: int,
161        pad_value: int,
162        rng: RandomGenerator,
163    ):
164        height, width = shape
165        crop_size = 2 * pad_size + core_size
166        (
167            vert_offset,
168            up,
169            down,
170            hori_offset,
171            left,
172            right,
173        ) = cls.sample_cropper_state(
174            height=height,
175            width=width,
176            core_size=core_size,
177            pad_size=pad_size,
178            crop_size=crop_size,
179            rng=rng,
180        )
181        return cls.create_from_cropping_positions(
182            height=height,
183            width=width,
184            pad_size=pad_size,
185            pad_value=pad_value,
186            core_size=core_size,
187            crop_size=crop_size,
188            vert_offset=vert_offset,
189            up=up,
190            down=down,
191            hori_offset=hori_offset,
192            left=left,
193            right=right,
194        )
195
196    @classmethod
197    def create_from_center_point(
198        cls,
199        shape: Tuple[int, int],
200        core_size: int,
201        pad_size: int,
202        pad_value: int,
203        center_point: Point,
204    ):
205        height, width = shape
206        crop_size = 2 * pad_size + core_size
207
208        assert 0 <= center_point.y < height
209        assert 0 <= center_point.x < width
210
211        vert_offset = 0
212        up = center_point.y - crop_size // 2
213        down = up + crop_size - 1
214        if up < 0:
215            vert_offset = abs(up)
216            up = 0
217        down = min(height - 1, down)
218
219        hori_offset = 0
220        left = center_point.x - crop_size // 2
221        right = left + crop_size - 1
222        if left < 0:
223            hori_offset = abs(left)
224            left = 0
225        right = min(width - 1, right)
226
227        return CropperState.create_from_cropping_positions(
228            height=height,
229            width=width,
230            pad_size=pad_size,
231            pad_value=pad_value,
232            core_size=core_size,
233            crop_size=crop_size,
234            vert_offset=vert_offset,
235            up=up,
236            down=down,
237            hori_offset=hori_offset,
238            left=left,
239            right=right,
240        )
241
242    @property
243    def need_post_filling(self):
244        return self.origin_box.height != self.crop_size or self.origin_box.width != self.crop_size
245
246    @property
247    def cropped_shape(self):
248        return (self.crop_size,) * 2
CropperState( height: int, width: int, pad_value: int, crop_size: int, origin_box: vkit.element.box.Box, target_box: vkit.element.box.Box, core_box: vkit.element.box.Box, origin_core_box: vkit.element.box.Box)
 2def __init__(self, height, width, pad_value, crop_size, origin_box, target_box, core_box, origin_core_box):
 3    self.height = height
 4    self.width = width
 5    self.pad_value = pad_value
 6    self.crop_size = crop_size
 7    self.origin_box = origin_box
 8    self.target_box = target_box
 9    self.core_box = core_box
10    self.origin_core_box = origin_core_box

Method generated by attrs for class CropperState.

@classmethod
def sample_cropping_positions( cls, core_size: int, pad_size: int, crop_size: int, length: int, rng: numpy.random._generator.Generator):
40    @classmethod
41    def sample_cropping_positions(
42        cls,
43        core_size: int,
44        pad_size: int,
45        crop_size: int,
46        length: int,
47        rng: RandomGenerator,
48    ):
49        if core_size <= length:
50            core_begin = rng.integers(0, length - core_size + 1)
51            begin = core_begin - pad_size
52            offset = 0
53            if begin < 0:
54                offset = abs(begin)
55                begin = 0
56
57        else:
58            begin = 0
59            offset = pad_size
60            offset += rng.integers(0, core_size - length + 1)
61
62        end = min(length - 1, begin + (crop_size - offset) - 1)
63        return offset, begin, end
@classmethod
def sample_cropper_state( cls, height: int, width: int, core_size: int, pad_size: int, crop_size: int, rng: numpy.random._generator.Generator):
65    @classmethod
66    def sample_cropper_state(
67        cls,
68        height: int,
69        width: int,
70        core_size: int,
71        pad_size: int,
72        crop_size: int,
73        rng: RandomGenerator,
74    ):
75        vert_offset, up, down = cls.sample_cropping_positions(
76            core_size=core_size,
77            pad_size=pad_size,
78            crop_size=crop_size,
79            length=height,
80            rng=rng,
81        )
82        hori_offset, left, right = cls.sample_cropping_positions(
83            core_size=core_size,
84            pad_size=pad_size,
85            crop_size=crop_size,
86            length=width,
87            rng=rng,
88        )
89        return (
90            vert_offset,
91            up,
92            down,
93            hori_offset,
94            left,
95            right,
96        )
@classmethod
def create_from_cropping_positions( cls, height: int, width: int, pad_size: int, pad_value: int, core_size: int, crop_size: int, vert_offset: int, up: int, down: int, hori_offset: int, left: int, right: int):
 98    @classmethod
 99    def create_from_cropping_positions(
100        cls,
101        height: int,
102        width: int,
103        pad_size: int,
104        pad_value: int,
105        core_size: int,
106        crop_size: int,
107        vert_offset: int,
108        up: int,
109        down: int,
110        hori_offset: int,
111        left: int,
112        right: int,
113    ):
114        origin_box = Box(
115            up=up,
116            down=down,
117            left=left,
118            right=right,
119        )
120
121        target_box = Box(
122            up=vert_offset,
123            down=vert_offset + origin_box.height - 1,
124            left=hori_offset,
125            right=hori_offset + origin_box.width - 1,
126        )
127
128        core_begin = pad_size
129        core_end = core_begin + core_size - 1
130        core_box = Box(
131            up=core_begin,
132            down=core_end,
133            left=core_begin,
134            right=core_end,
135        )
136
137        origin_core_box = Box(
138            up=up + core_box.up - target_box.up,
139            down=down + core_box.down - target_box.down,
140            left=left + core_box.left - target_box.left,
141            right=right + core_box.right - target_box.right,
142        )
143
144        return CropperState(
145            height=height,
146            width=width,
147            pad_value=pad_value,
148            crop_size=crop_size,
149            origin_box=origin_box,
150            target_box=target_box,
151            core_box=core_box,
152            origin_core_box=origin_core_box,
153        )
@classmethod
def create( cls, shape: Tuple[int, int], core_size: int, pad_size: int, pad_value: int, rng: numpy.random._generator.Generator):
155    @classmethod
156    def create(
157        cls,
158        shape: Tuple[int, int],
159        core_size: int,
160        pad_size: int,
161        pad_value: int,
162        rng: RandomGenerator,
163    ):
164        height, width = shape
165        crop_size = 2 * pad_size + core_size
166        (
167            vert_offset,
168            up,
169            down,
170            hori_offset,
171            left,
172            right,
173        ) = cls.sample_cropper_state(
174            height=height,
175            width=width,
176            core_size=core_size,
177            pad_size=pad_size,
178            crop_size=crop_size,
179            rng=rng,
180        )
181        return cls.create_from_cropping_positions(
182            height=height,
183            width=width,
184            pad_size=pad_size,
185            pad_value=pad_value,
186            core_size=core_size,
187            crop_size=crop_size,
188            vert_offset=vert_offset,
189            up=up,
190            down=down,
191            hori_offset=hori_offset,
192            left=left,
193            right=right,
194        )
@classmethod
def create_from_center_point( cls, shape: Tuple[int, int], core_size: int, pad_size: int, pad_value: int, center_point: vkit.element.point.Point):
196    @classmethod
197    def create_from_center_point(
198        cls,
199        shape: Tuple[int, int],
200        core_size: int,
201        pad_size: int,
202        pad_value: int,
203        center_point: Point,
204    ):
205        height, width = shape
206        crop_size = 2 * pad_size + core_size
207
208        assert 0 <= center_point.y < height
209        assert 0 <= center_point.x < width
210
211        vert_offset = 0
212        up = center_point.y - crop_size // 2
213        down = up + crop_size - 1
214        if up < 0:
215            vert_offset = abs(up)
216            up = 0
217        down = min(height - 1, down)
218
219        hori_offset = 0
220        left = center_point.x - crop_size // 2
221        right = left + crop_size - 1
222        if left < 0:
223            hori_offset = abs(left)
224            left = 0
225        right = min(width - 1, right)
226
227        return CropperState.create_from_cropping_positions(
228            height=height,
229            width=width,
230            pad_size=pad_size,
231            pad_value=pad_value,
232            core_size=core_size,
233            crop_size=crop_size,
234            vert_offset=vert_offset,
235            up=up,
236            down=down,
237            hori_offset=hori_offset,
238            left=left,
239            right=right,
240        )
class Cropper:
251class Cropper:
252
253    @classmethod
254    def create(
255        cls,
256        shape: Tuple[int, int],
257        core_size: int,
258        pad_size: int,
259        rng: RandomGenerator,
260        pad_value: int = 0,
261    ):
262        cropper_state = CropperState.create(
263            shape=shape,
264            core_size=core_size,
265            pad_size=pad_size,
266            pad_value=pad_value,
267            rng=rng,
268        )
269        return Cropper(cropper_state)
270
271    @classmethod
272    def create_from_center_point(
273        cls,
274        shape: Tuple[int, int],
275        core_size: int,
276        pad_size: int,
277        center_point: Point,
278        pad_value: int = 0,
279    ):
280        cropper_state = CropperState.create_from_center_point(
281            shape=shape,
282            core_size=core_size,
283            pad_size=pad_size,
284            pad_value=pad_value,
285            center_point=center_point,
286        )
287        return Cropper(cropper_state)
288
289    def __init__(self, cropper_state: CropperState):
290        self.cropper_state = cropper_state
291
292    @property
293    def origin_box(self):
294        return self.cropper_state.origin_box
295
296    @property
297    def target_box(self):
298        return self.cropper_state.target_box
299
300    @property
301    def core_box(self):
302        return self.cropper_state.core_box
303
304    @property
305    def origin_core_box(self):
306        return self.cropper_state.origin_core_box
307
308    @property
309    def need_post_filling(self):
310        return self.cropper_state.need_post_filling
311
312    @property
313    def crop_size(self):
314        return self.cropper_state.crop_size
315
316    @property
317    def cropped_shape(self):
318        return self.cropper_state.cropped_shape
319
320    @property
321    def pad_value(self):
322        return self.cropper_state.pad_value
323
324    def crop_mask(self, mask: Mask, core_only: bool = False):
325        mask = self.origin_box.extract_mask(mask)
326
327        if self.need_post_filling:
328            new_mask = Mask.from_shape(self.cropped_shape)
329            self.target_box.fill_mask(new_mask, mask)
330            mask = new_mask
331
332        if core_only:
333            mask = self.core_box.extract_mask(mask)
334            mask = mask.to_box_attached(self.core_box)
335
336        return mask
337
338    def crop_score_map(self, score_map: ScoreMap, core_only: bool = False):
339        score_map = self.origin_box.extract_score_map(score_map)
340
341        if self.need_post_filling:
342            new_score_map = ScoreMap.from_shape(
343                self.cropped_shape,
344                is_prob=score_map.is_prob,
345            )
346            self.target_box.fill_score_map(new_score_map, score_map)
347            score_map = new_score_map
348
349        if core_only:
350            score_map = self.core_box.extract_score_map(score_map)
351            score_map = score_map.to_box_attached(self.core_box)
352
353        return score_map
354
355    def crop_image(self, image: Image):
356        image = self.origin_box.extract_image(image)
357
358        if self.need_post_filling:
359            new_image = Image.from_shape(
360                self.cropped_shape,
361                num_channels=image.num_channels,
362                value=self.pad_value,
363            )
364            self.target_box.fill_image(new_image, image)
365            image = new_image
366
367        return image
Cropper(cropper_state: vkit.mechanism.cropper.CropperState)
289    def __init__(self, cropper_state: CropperState):
290        self.cropper_state = cropper_state
@classmethod
def create( cls, shape: Tuple[int, int], core_size: int, pad_size: int, rng: numpy.random._generator.Generator, pad_value: int = 0):
253    @classmethod
254    def create(
255        cls,
256        shape: Tuple[int, int],
257        core_size: int,
258        pad_size: int,
259        rng: RandomGenerator,
260        pad_value: int = 0,
261    ):
262        cropper_state = CropperState.create(
263            shape=shape,
264            core_size=core_size,
265            pad_size=pad_size,
266            pad_value=pad_value,
267            rng=rng,
268        )
269        return Cropper(cropper_state)
@classmethod
def create_from_center_point( cls, shape: Tuple[int, int], core_size: int, pad_size: int, center_point: vkit.element.point.Point, pad_value: int = 0):
271    @classmethod
272    def create_from_center_point(
273        cls,
274        shape: Tuple[int, int],
275        core_size: int,
276        pad_size: int,
277        center_point: Point,
278        pad_value: int = 0,
279    ):
280        cropper_state = CropperState.create_from_center_point(
281            shape=shape,
282            core_size=core_size,
283            pad_size=pad_size,
284            pad_value=pad_value,
285            center_point=center_point,
286        )
287        return Cropper(cropper_state)
def crop_mask(self, mask: vkit.element.mask.Mask, core_only: bool = False):
324    def crop_mask(self, mask: Mask, core_only: bool = False):
325        mask = self.origin_box.extract_mask(mask)
326
327        if self.need_post_filling:
328            new_mask = Mask.from_shape(self.cropped_shape)
329            self.target_box.fill_mask(new_mask, mask)
330            mask = new_mask
331
332        if core_only:
333            mask = self.core_box.extract_mask(mask)
334            mask = mask.to_box_attached(self.core_box)
335
336        return mask
def crop_score_map( self, score_map: vkit.element.score_map.ScoreMap, core_only: bool = False):
338    def crop_score_map(self, score_map: ScoreMap, core_only: bool = False):
339        score_map = self.origin_box.extract_score_map(score_map)
340
341        if self.need_post_filling:
342            new_score_map = ScoreMap.from_shape(
343                self.cropped_shape,
344                is_prob=score_map.is_prob,
345            )
346            self.target_box.fill_score_map(new_score_map, score_map)
347            score_map = new_score_map
348
349        if core_only:
350            score_map = self.core_box.extract_score_map(score_map)
351            score_map = score_map.to_box_attached(self.core_box)
352
353        return score_map
def crop_image(self, image: vkit.element.image.Image):
355    def crop_image(self, image: Image):
356        image = self.origin_box.extract_image(image)
357
358        if self.need_post_filling:
359            new_image = Image.from_shape(
360                self.cropped_shape,
361                num_channels=image.num_channels,
362                value=self.pad_value,
363            )
364            self.target_box.fill_image(new_image, image)
365            image = new_image
366
367        return image