It will first crop input images to tiles, and then process each tile. Finally, all the processed tiles are merged into one images. Modified from: https://github.com/ata4/esrgan-launcher
(self)
| 80 | self.output = self.model(self.img) |
| 81 | |
| 82 | def tile_process(self): |
| 83 | """It will first crop input images to tiles, and then process each tile. |
| 84 | Finally, all the processed tiles are merged into one images. |
| 85 | |
| 86 | Modified from: https://github.com/ata4/esrgan-launcher |
| 87 | """ |
| 88 | batch, channel, height, width = self.img.shape |
| 89 | output_height = height * self.scale |
| 90 | output_width = width * self.scale |
| 91 | output_shape = (batch, channel, output_height, output_width) |
| 92 | |
| 93 | # start with black image |
| 94 | self.output = self.img.new_zeros(output_shape) |
| 95 | tiles_x = math.ceil(width / self.tile_size) |
| 96 | tiles_y = math.ceil(height / self.tile_size) |
| 97 | |
| 98 | # loop over all tiles |
| 99 | for y in range(tiles_y): |
| 100 | for x in range(tiles_x): |
| 101 | # extract tile from input image |
| 102 | ofs_x = x * self.tile_size |
| 103 | ofs_y = y * self.tile_size |
| 104 | # input tile area on total image |
| 105 | input_start_x = ofs_x |
| 106 | input_end_x = min(ofs_x + self.tile_size, width) |
| 107 | input_start_y = ofs_y |
| 108 | input_end_y = min(ofs_y + self.tile_size, height) |
| 109 | |
| 110 | # input tile area on total image with padding |
| 111 | input_start_x_pad = max(input_start_x - self.tile_pad, 0) |
| 112 | input_end_x_pad = min(input_end_x + self.tile_pad, width) |
| 113 | input_start_y_pad = max(input_start_y - self.tile_pad, 0) |
| 114 | input_end_y_pad = min(input_end_y + self.tile_pad, height) |
| 115 | |
| 116 | # input tile dimensions |
| 117 | input_tile_width = input_end_x - input_start_x |
| 118 | input_tile_height = input_end_y - input_start_y |
| 119 | tile_idx = y * tiles_x + x + 1 |
| 120 | input_tile = self.img[:, :, input_start_y_pad:input_end_y_pad, input_start_x_pad:input_end_x_pad] |
| 121 | |
| 122 | # upscale tile |
| 123 | try: |
| 124 | with torch.no_grad(): |
| 125 | output_tile = self.model(input_tile) |
| 126 | except RuntimeError as error: |
| 127 | print('Error', error) |
| 128 | print(f'\tTile {tile_idx}/{tiles_x * tiles_y}') |
| 129 | |
| 130 | # output tile area on total image |
| 131 | output_start_x = input_start_x * self.scale |
| 132 | output_end_x = input_end_x * self.scale |
| 133 | output_start_y = input_start_y * self.scale |
| 134 | output_end_y = input_end_y * self.scale |
| 135 | |
| 136 | # output tile area without padding |
| 137 | output_start_x_tile = (input_start_x - input_start_x_pad) * self.scale |
| 138 | output_end_x_tile = output_start_x_tile + input_tile_width * self.scale |
| 139 | output_start_y_tile = (input_start_y - input_start_y_pad) * self.scale |