Generates a list of crop boxes of different sizes. Each layer has (2**i)**2 boxes for the ith layer.
(
im_size: Tuple[int, ...], n_layers: int, overlap_ratio: float
)
| 198 | |
| 199 | |
| 200 | def generate_crop_boxes( |
| 201 | im_size: Tuple[int, ...], n_layers: int, overlap_ratio: float |
| 202 | ) -> Tuple[List[List[int]], List[int]]: |
| 203 | """ |
| 204 | Generates a list of crop boxes of different sizes. Each layer |
| 205 | has (2**i)**2 boxes for the ith layer. |
| 206 | """ |
| 207 | crop_boxes, layer_idxs = [], [] |
| 208 | im_h, im_w = im_size |
| 209 | short_side = min(im_h, im_w) |
| 210 | |
| 211 | # Original image |
| 212 | crop_boxes.append([0, 0, im_w, im_h]) |
| 213 | layer_idxs.append(0) |
| 214 | |
| 215 | def crop_len(orig_len, n_crops, overlap): |
| 216 | return int(math.ceil((overlap * (n_crops - 1) + orig_len) / n_crops)) |
| 217 | |
| 218 | for i_layer in range(n_layers): |
| 219 | n_crops_per_side = 2 ** (i_layer + 1) |
| 220 | overlap = int(overlap_ratio * short_side * (2 / n_crops_per_side)) |
| 221 | |
| 222 | crop_w = crop_len(im_w, n_crops_per_side, overlap) |
| 223 | crop_h = crop_len(im_h, n_crops_per_side, overlap) |
| 224 | |
| 225 | crop_box_x0 = [int((crop_w - overlap) * i) for i in range(n_crops_per_side)] |
| 226 | crop_box_y0 = [int((crop_h - overlap) * i) for i in range(n_crops_per_side)] |
| 227 | |
| 228 | # Crops in XYWH format |
| 229 | for x0, y0 in product(crop_box_x0, crop_box_y0): |
| 230 | box = [x0, y0, min(x0 + crop_w, im_w), min(y0 + crop_h, im_h)] |
| 231 | crop_boxes.append(box) |
| 232 | layer_idxs.append(i_layer + 1) |
| 233 | |
| 234 | return crop_boxes, layer_idxs |
| 235 | |
| 236 | |
| 237 | def uncrop_boxes_xyxy(boxes: torch.Tensor, crop_box: List[int]) -> torch.Tensor: |
no test coverage detected