(self, image_base, image_to_paste, mask, resize_behavior, mask_mapping_optional = None)
| 855 | CATEGORY = "Masquerade Nodes" |
| 856 | |
| 857 | def paste(self, image_base, image_to_paste, mask, resize_behavior, mask_mapping_optional = None): |
| 858 | image_base = tensor2rgba(image_base) |
| 859 | image_to_paste = tensor2rgba(image_to_paste) |
| 860 | mask = tensor2mask(mask) |
| 861 | |
| 862 | # Scale the mask to be a matching size if it isn't |
| 863 | B, H, W, C = image_base.shape |
| 864 | MB = mask.shape[0] |
| 865 | PB = image_to_paste.shape[0] |
| 866 | if mask_mapping_optional is None: |
| 867 | if B < PB: |
| 868 | assert(PB % B == 0) |
| 869 | image_base = image_base.repeat(PB // B, 1, 1, 1) |
| 870 | B, H, W, C = image_base.shape |
| 871 | if MB < B: |
| 872 | assert(B % MB == 0) |
| 873 | mask = mask.repeat(B // MB, 1, 1) |
| 874 | elif B < MB: |
| 875 | assert(MB % B == 0) |
| 876 | image_base = image_base.repeat(MB // B, 1, 1, 1) |
| 877 | if PB < B: |
| 878 | assert(B % PB == 0) |
| 879 | image_to_paste = image_to_paste.repeat(B // PB, 1, 1, 1) |
| 880 | mask = torch.nn.functional.interpolate(mask.unsqueeze(1), size=(H, W), mode='nearest')[:,0,:,:] |
| 881 | MB, MH, MW = mask.shape |
| 882 | |
| 883 | # masks_to_boxes errors if the tensor is all zeros, so we'll add a single pixel and zero it out at the end |
| 884 | is_empty = ~torch.gt(torch.max(torch.reshape(mask,[MB, MH * MW]), dim=1).values, 0.) |
| 885 | mask[is_empty,0,0] = 1. |
| 886 | boxes = masks_to_boxes(mask) |
| 887 | mask[is_empty,0,0] = 0. |
| 888 | |
| 889 | min_x = boxes[:,0] |
| 890 | min_y = boxes[:,1] |
| 891 | max_x = boxes[:,2] |
| 892 | max_y = boxes[:,3] |
| 893 | mid_x = (min_x + max_x) / 2 |
| 894 | mid_y = (min_y + max_y) / 2 |
| 895 | |
| 896 | target_width = max_x - min_x + 1 |
| 897 | target_height = max_y - min_y + 1 |
| 898 | |
| 899 | result = image_base.detach().clone() |
| 900 | for i in range(0, MB): |
| 901 | if is_empty[i]: |
| 902 | continue |
| 903 | else: |
| 904 | image_index = i |
| 905 | if mask_mapping_optional is not None: |
| 906 | image_index = mask_mapping_optional[i].item() |
| 907 | source_size = image_to_paste.size() |
| 908 | SB, SH, SW, _ = image_to_paste.shape |
| 909 | |
| 910 | # Figure out the desired size |
| 911 | width = int(target_width[i].item()) |
| 912 | height = int(target_height[i].item()) |
| 913 | if resize_behavior == "keep_ratio_fill": |
| 914 | target_ratio = width / height |
nothing calls this directly
no test coverage detected