| 203 | |
| 204 | |
| 205 | class PyramidPatchMatcher: |
| 206 | def __init__( |
| 207 | self, image_height, image_width, channel, minimum_patch_size, |
| 208 | threads_per_block=8, num_iter=5, gpu_id=0, guide_weight=10.0, |
| 209 | use_mean_target_style=False, use_pairwise_patch_error=False, |
| 210 | tracking_window_size=0, |
| 211 | initialize="identity" |
| 212 | ): |
| 213 | maximum_patch_size = minimum_patch_size + (num_iter - 1) * 2 |
| 214 | self.pyramid_level = int(np.log2(min(image_height, image_width) / maximum_patch_size)) |
| 215 | self.pyramid_heights = [] |
| 216 | self.pyramid_widths = [] |
| 217 | self.patch_matchers = [] |
| 218 | self.minimum_patch_size = minimum_patch_size |
| 219 | self.num_iter = num_iter |
| 220 | self.gpu_id = gpu_id |
| 221 | self.initialize = initialize |
| 222 | for level in range(self.pyramid_level): |
| 223 | height = image_height//(2**(self.pyramid_level - 1 - level)) |
| 224 | width = image_width//(2**(self.pyramid_level - 1 - level)) |
| 225 | self.pyramid_heights.append(height) |
| 226 | self.pyramid_widths.append(width) |
| 227 | self.patch_matchers.append(PatchMatcher( |
| 228 | height, width, channel, minimum_patch_size=minimum_patch_size, |
| 229 | threads_per_block=threads_per_block, num_iter=num_iter, gpu_id=gpu_id, guide_weight=guide_weight, |
| 230 | use_mean_target_style=use_mean_target_style, use_pairwise_patch_error=use_pairwise_patch_error, |
| 231 | tracking_window_size=tracking_window_size |
| 232 | )) |
| 233 | |
| 234 | def resample_image(self, images, level): |
| 235 | height, width = self.pyramid_heights[level], self.pyramid_widths[level] |
| 236 | images = images.get() |
| 237 | images_resample = [] |
| 238 | for image in images: |
| 239 | image_resample = cv2.resize(image, (width, height), interpolation=cv2.INTER_AREA) |
| 240 | images_resample.append(image_resample) |
| 241 | images_resample = cp.array(np.stack(images_resample), dtype=cp.float32) |
| 242 | return images_resample |
| 243 | |
| 244 | def initialize_nnf(self, batch_size): |
| 245 | if self.initialize == "random": |
| 246 | height, width = self.pyramid_heights[0], self.pyramid_widths[0] |
| 247 | nnf = cp.stack([ |
| 248 | cp.random.randint(0, height, (batch_size, height, width), dtype=cp.int32), |
| 249 | cp.random.randint(0, width, (batch_size, height, width), dtype=cp.int32) |
| 250 | ], axis=3) |
| 251 | elif self.initialize == "identity": |
| 252 | height, width = self.pyramid_heights[0], self.pyramid_widths[0] |
| 253 | nnf = cp.stack([ |
| 254 | cp.repeat(cp.arange(height), width).reshape(height, width), |
| 255 | cp.tile(cp.arange(width), height).reshape(height, width) |
| 256 | ], axis=2) |
| 257 | nnf = cp.stack([nnf] * batch_size) |
| 258 | else: |
| 259 | raise NotImplementedError() |
| 260 | return nnf |
| 261 | |
| 262 | def update_nnf(self, nnf, level): |
no outgoing calls
no test coverage detected