Upload processor
Browse files- image_processing_basnet.py +279 -0
- preprocessor_config.json +8 -0
image_processing_basnet.py
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Dict, Tuple, Union
|
| 2 |
+
|
| 3 |
+
import cv2
|
| 4 |
+
import numpy as np
|
| 5 |
+
import torch
|
| 6 |
+
from PIL import Image
|
| 7 |
+
from PIL.Image import Image as PilImage
|
| 8 |
+
from torchvision import transforms
|
| 9 |
+
from transformers.image_processing_base import BatchFeature
|
| 10 |
+
from transformers.image_processing_utils import BaseImageProcessor
|
| 11 |
+
from transformers.image_utils import ImageInput
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class RescaleT(object):
|
| 15 |
+
def __init__(self, output_size: Union[int, Tuple[int, int]]) -> None:
|
| 16 |
+
super().__init__()
|
| 17 |
+
assert isinstance(output_size, (int, tuple))
|
| 18 |
+
self.output_size = output_size
|
| 19 |
+
|
| 20 |
+
def __call__(self, sample):
|
| 21 |
+
image, label = sample["image"], sample["label"]
|
| 22 |
+
|
| 23 |
+
h, w = image.shape[:2]
|
| 24 |
+
|
| 25 |
+
if isinstance(self.output_size, int):
|
| 26 |
+
if h > w:
|
| 27 |
+
new_h, new_w = self.output_size * h / w, self.output_size
|
| 28 |
+
else:
|
| 29 |
+
new_h, new_w = self.output_size, self.output_size * w / h
|
| 30 |
+
else:
|
| 31 |
+
new_h, new_w = self.output_size
|
| 32 |
+
|
| 33 |
+
new_h, new_w = int(new_h), int(new_w)
|
| 34 |
+
|
| 35 |
+
# resize the image to new_h x new_w and convert image from range [0,255] to [0,1]
|
| 36 |
+
# img = transform.resize(image,(new_h,new_w),mode='constant')
|
| 37 |
+
# lbl = transform.resize(label,(new_h,new_w),mode='constant', order=0, preserve_range=True)
|
| 38 |
+
|
| 39 |
+
# img = transform.resize(image, (self.output_size, self.output_size), mode='constant')
|
| 40 |
+
img = (
|
| 41 |
+
cv2.resize(
|
| 42 |
+
image,
|
| 43 |
+
(self.output_size, self.output_size),
|
| 44 |
+
interpolation=cv2.INTER_AREA,
|
| 45 |
+
)
|
| 46 |
+
/ 255.0
|
| 47 |
+
)
|
| 48 |
+
# lbl = transform.resize(label, (self.output_size, self.output_size),
|
| 49 |
+
# mode='constant',
|
| 50 |
+
# order=0,
|
| 51 |
+
# preserve_range=True)
|
| 52 |
+
lbl = cv2.resize(
|
| 53 |
+
label, (self.output_size, self.output_size), interpolation=cv2.INTER_NEAREST
|
| 54 |
+
)
|
| 55 |
+
lbl = np.expand_dims(lbl, axis=-1)
|
| 56 |
+
lbl = np.clip(lbl, np.min(label), np.max(label))
|
| 57 |
+
|
| 58 |
+
return {"image": img, "label": lbl}
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
class ToTensorLab(object):
|
| 62 |
+
"""Convert ndarrays in sample to Tensors."""
|
| 63 |
+
|
| 64 |
+
def __init__(self, flag=0):
|
| 65 |
+
self.flag = flag
|
| 66 |
+
|
| 67 |
+
def __call__(self, sample):
|
| 68 |
+
image, label = sample["image"], sample["label"]
|
| 69 |
+
|
| 70 |
+
tmpLbl = np.zeros(label.shape)
|
| 71 |
+
|
| 72 |
+
if np.max(label) < 1e-6:
|
| 73 |
+
label = label
|
| 74 |
+
else:
|
| 75 |
+
label = label / np.max(label)
|
| 76 |
+
|
| 77 |
+
# print('self.flag:', self.flag) # Default: 0
|
| 78 |
+
# change the color space
|
| 79 |
+
if self.flag == 2: # with rgb and Lab colors
|
| 80 |
+
tmpImg = np.zeros((image.shape[0], image.shape[1], 6))
|
| 81 |
+
tmpImgt = np.zeros((image.shape[0], image.shape[1], 3))
|
| 82 |
+
if image.shape[2] == 1:
|
| 83 |
+
tmpImgt[:, :, 0] = image[:, :, 0]
|
| 84 |
+
tmpImgt[:, :, 1] = image[:, :, 0]
|
| 85 |
+
tmpImgt[:, :, 2] = image[:, :, 0]
|
| 86 |
+
else:
|
| 87 |
+
tmpImgt = image
|
| 88 |
+
# tmpImgtl = color.rgb2lab(tmpImgt)
|
| 89 |
+
tmpImgtl = cv2.cvtColor(tmpImgt, cv2.COLOR_RGB2LAB)
|
| 90 |
+
|
| 91 |
+
# nomalize image to range [0,1]
|
| 92 |
+
tmpImg[:, :, 0] = (tmpImgt[:, :, 0] - np.min(tmpImgt[:, :, 0])) / (
|
| 93 |
+
np.max(tmpImgt[:, :, 0]) - np.min(tmpImgt[:, :, 0])
|
| 94 |
+
)
|
| 95 |
+
tmpImg[:, :, 1] = (tmpImgt[:, :, 1] - np.min(tmpImgt[:, :, 1])) / (
|
| 96 |
+
np.max(tmpImgt[:, :, 1]) - np.min(tmpImgt[:, :, 1])
|
| 97 |
+
)
|
| 98 |
+
tmpImg[:, :, 2] = (tmpImgt[:, :, 2] - np.min(tmpImgt[:, :, 2])) / (
|
| 99 |
+
np.max(tmpImgt[:, :, 2]) - np.min(tmpImgt[:, :, 2])
|
| 100 |
+
)
|
| 101 |
+
tmpImg[:, :, 3] = (tmpImgtl[:, :, 0] - np.min(tmpImgtl[:, :, 0])) / (
|
| 102 |
+
np.max(tmpImgtl[:, :, 0]) - np.min(tmpImgtl[:, :, 0])
|
| 103 |
+
)
|
| 104 |
+
tmpImg[:, :, 4] = (tmpImgtl[:, :, 1] - np.min(tmpImgtl[:, :, 1])) / (
|
| 105 |
+
np.max(tmpImgtl[:, :, 1]) - np.min(tmpImgtl[:, :, 1])
|
| 106 |
+
)
|
| 107 |
+
tmpImg[:, :, 5] = (tmpImgtl[:, :, 2] - np.min(tmpImgtl[:, :, 2])) / (
|
| 108 |
+
np.max(tmpImgtl[:, :, 2]) - np.min(tmpImgtl[:, :, 2])
|
| 109 |
+
)
|
| 110 |
+
|
| 111 |
+
# tmpImg = tmpImg/(np.max(tmpImg)-np.min(tmpImg))
|
| 112 |
+
|
| 113 |
+
tmpImg[:, :, 0] = (tmpImg[:, :, 0] - np.mean(tmpImg[:, :, 0])) / np.std(
|
| 114 |
+
tmpImg[:, :, 0]
|
| 115 |
+
)
|
| 116 |
+
tmpImg[:, :, 1] = (tmpImg[:, :, 1] - np.mean(tmpImg[:, :, 1])) / np.std(
|
| 117 |
+
tmpImg[:, :, 1]
|
| 118 |
+
)
|
| 119 |
+
tmpImg[:, :, 2] = (tmpImg[:, :, 2] - np.mean(tmpImg[:, :, 2])) / np.std(
|
| 120 |
+
tmpImg[:, :, 2]
|
| 121 |
+
)
|
| 122 |
+
tmpImg[:, :, 3] = (tmpImg[:, :, 3] - np.mean(tmpImg[:, :, 3])) / np.std(
|
| 123 |
+
tmpImg[:, :, 3]
|
| 124 |
+
)
|
| 125 |
+
tmpImg[:, :, 4] = (tmpImg[:, :, 4] - np.mean(tmpImg[:, :, 4])) / np.std(
|
| 126 |
+
tmpImg[:, :, 4]
|
| 127 |
+
)
|
| 128 |
+
tmpImg[:, :, 5] = (tmpImg[:, :, 5] - np.mean(tmpImg[:, :, 5])) / np.std(
|
| 129 |
+
tmpImg[:, :, 5]
|
| 130 |
+
)
|
| 131 |
+
|
| 132 |
+
elif self.flag == 1: # with Lab color
|
| 133 |
+
tmpImg = np.zeros((image.shape[0], image.shape[1], 3))
|
| 134 |
+
|
| 135 |
+
if image.shape[2] == 1:
|
| 136 |
+
tmpImg[:, :, 0] = image[:, :, 0]
|
| 137 |
+
tmpImg[:, :, 1] = image[:, :, 0]
|
| 138 |
+
tmpImg[:, :, 2] = image[:, :, 0]
|
| 139 |
+
else:
|
| 140 |
+
tmpImg = image
|
| 141 |
+
|
| 142 |
+
# tmpImg = color.rgb2lab(tmpImg)
|
| 143 |
+
print("tmpImg:", tmpImg.min(), tmpImg.max())
|
| 144 |
+
exit()
|
| 145 |
+
tmpImg = cv2.cvtColor(tmpImg, cv2.COLOR_RGB2LAB)
|
| 146 |
+
|
| 147 |
+
# tmpImg = tmpImg/(np.max(tmpImg)-np.min(tmpImg))
|
| 148 |
+
|
| 149 |
+
tmpImg[:, :, 0] = (tmpImg[:, :, 0] - np.min(tmpImg[:, :, 0])) / (
|
| 150 |
+
np.max(tmpImg[:, :, 0]) - np.min(tmpImg[:, :, 0])
|
| 151 |
+
)
|
| 152 |
+
tmpImg[:, :, 1] = (tmpImg[:, :, 1] - np.min(tmpImg[:, :, 1])) / (
|
| 153 |
+
np.max(tmpImg[:, :, 1]) - np.min(tmpImg[:, :, 1])
|
| 154 |
+
)
|
| 155 |
+
tmpImg[:, :, 2] = (tmpImg[:, :, 2] - np.min(tmpImg[:, :, 2])) / (
|
| 156 |
+
np.max(tmpImg[:, :, 2]) - np.min(tmpImg[:, :, 2])
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
tmpImg[:, :, 0] = (tmpImg[:, :, 0] - np.mean(tmpImg[:, :, 0])) / np.std(
|
| 160 |
+
tmpImg[:, :, 0]
|
| 161 |
+
)
|
| 162 |
+
tmpImg[:, :, 1] = (tmpImg[:, :, 1] - np.mean(tmpImg[:, :, 1])) / np.std(
|
| 163 |
+
tmpImg[:, :, 1]
|
| 164 |
+
)
|
| 165 |
+
tmpImg[:, :, 2] = (tmpImg[:, :, 2] - np.mean(tmpImg[:, :, 2])) / np.std(
|
| 166 |
+
tmpImg[:, :, 2]
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
else: # with rgb color
|
| 170 |
+
tmpImg = np.zeros((image.shape[0], image.shape[1], 3))
|
| 171 |
+
image = image / np.max(image)
|
| 172 |
+
if image.shape[2] == 1:
|
| 173 |
+
tmpImg[:, :, 0] = (image[:, :, 0] - 0.485) / 0.229
|
| 174 |
+
tmpImg[:, :, 1] = (image[:, :, 0] - 0.485) / 0.229
|
| 175 |
+
tmpImg[:, :, 2] = (image[:, :, 0] - 0.485) / 0.229
|
| 176 |
+
else:
|
| 177 |
+
tmpImg[:, :, 0] = (image[:, :, 0] - 0.485) / 0.229
|
| 178 |
+
tmpImg[:, :, 1] = (image[:, :, 1] - 0.456) / 0.224
|
| 179 |
+
tmpImg[:, :, 2] = (image[:, :, 2] - 0.406) / 0.225
|
| 180 |
+
|
| 181 |
+
tmpLbl[:, :, 0] = label[:, :, 0]
|
| 182 |
+
|
| 183 |
+
# change the r,g,b to b,r,g from [0,255] to [0,1]
|
| 184 |
+
# transforms.Normalize(mean = (0.485, 0.456, 0.406), std = (0.229, 0.224, 0.225))
|
| 185 |
+
tmpImg = tmpImg.transpose((2, 0, 1))
|
| 186 |
+
tmpLbl = label.transpose((2, 0, 1))
|
| 187 |
+
|
| 188 |
+
return {"image": torch.from_numpy(tmpImg), "label": torch.from_numpy(tmpLbl)}
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
def apply_transform(
|
| 192 |
+
data: Dict[str, np.ndarray], rescale_size: int, to_tensor_lab_flag: int
|
| 193 |
+
) -> Dict[str, torch.Tensor]:
|
| 194 |
+
transform = transforms.Compose(
|
| 195 |
+
[RescaleT(output_size=rescale_size), ToTensorLab(flag=to_tensor_lab_flag)]
|
| 196 |
+
)
|
| 197 |
+
return transform(data) # type: ignore
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
class BASNetImageProcessor(BaseImageProcessor):
|
| 201 |
+
model_input_names = ["pixel_values"]
|
| 202 |
+
|
| 203 |
+
def __init__(
|
| 204 |
+
self, rescale_size: int = 256, to_tensor_lab_flag: int = 0, **kwargs
|
| 205 |
+
) -> None:
|
| 206 |
+
super().__init__(**kwargs)
|
| 207 |
+
self.rescale_size = rescale_size
|
| 208 |
+
self.to_tensor_lab_flag = to_tensor_lab_flag
|
| 209 |
+
|
| 210 |
+
def preprocess(self, images: ImageInput, **kwargs) -> BatchFeature:
|
| 211 |
+
if not isinstance(images, PilImage):
|
| 212 |
+
raise ValueError(f"Expected PIL.Image, got {type(images)}")
|
| 213 |
+
|
| 214 |
+
image_pil = images
|
| 215 |
+
image_npy = np.array(image_pil, dtype=np.uint8)
|
| 216 |
+
width, height = image_pil.size
|
| 217 |
+
label_npy = np.zeros((height, width), dtype=np.uint8)
|
| 218 |
+
|
| 219 |
+
assert image_npy.shape[-1] == 3
|
| 220 |
+
output = apply_transform(
|
| 221 |
+
{"image": image_npy, "label": label_npy},
|
| 222 |
+
rescale_size=self.rescale_size,
|
| 223 |
+
to_tensor_lab_flag=self.to_tensor_lab_flag,
|
| 224 |
+
)
|
| 225 |
+
image = output["image"]
|
| 226 |
+
|
| 227 |
+
assert isinstance(image, torch.Tensor)
|
| 228 |
+
|
| 229 |
+
return BatchFeature(
|
| 230 |
+
data={"pixel_values": image.float().unsqueeze(dim=0)}, tensor_type="pt"
|
| 231 |
+
)
|
| 232 |
+
|
| 233 |
+
def postprocess(
|
| 234 |
+
self, prediction: torch.Tensor, width: int, height: int
|
| 235 |
+
) -> PilImage:
|
| 236 |
+
def _norm_prediction(d: torch.Tensor) -> torch.Tensor:
|
| 237 |
+
ma, mi = torch.max(d), torch.min(d)
|
| 238 |
+
|
| 239 |
+
# division while avoiding zero division
|
| 240 |
+
dn = (d - mi) / ((ma - mi) + torch.finfo(torch.float32).eps)
|
| 241 |
+
return dn
|
| 242 |
+
|
| 243 |
+
# prediction = _norm_output(prediction)
|
| 244 |
+
# prediction = prediction.squeeze()
|
| 245 |
+
# prediction_np = prediction.cpu().numpy()
|
| 246 |
+
|
| 247 |
+
# image = Image.fromarray(prediction_np * 255).convert("RGB")
|
| 248 |
+
# image = image.resize((width, height), resample=Image.Resampling.BILINEAR)
|
| 249 |
+
|
| 250 |
+
# return image
|
| 251 |
+
|
| 252 |
+
# breakpoint()
|
| 253 |
+
|
| 254 |
+
# output = F.interpolate(output, (height, width), mode="bilinear")
|
| 255 |
+
# output = output.squeeze(dim=0)
|
| 256 |
+
|
| 257 |
+
# output = _norm_output(output)
|
| 258 |
+
|
| 259 |
+
# # Add 0.5 after unnormalizing to [0, 255] to round to nearest integer
|
| 260 |
+
# output = output * 255 + 0.5
|
| 261 |
+
# output = output.clamp(0, 255)
|
| 262 |
+
|
| 263 |
+
# # shape: (C=1, W, H) -> (W, H, C=1)
|
| 264 |
+
# output = output.permute(1, 2, 0)
|
| 265 |
+
# # shape: (W, H, C=3)
|
| 266 |
+
# output = output.repeat(1, 1, 3)
|
| 267 |
+
|
| 268 |
+
# output_np = output.cpu().numpy().astype(np.uint8)
|
| 269 |
+
# return Image.fromarray(output_np)
|
| 270 |
+
|
| 271 |
+
prediction = _norm_prediction(prediction)
|
| 272 |
+
prediction = prediction.squeeze()
|
| 273 |
+
prediction = prediction * 255 + 0.5
|
| 274 |
+
prediction = prediction.clamp(0, 255)
|
| 275 |
+
|
| 276 |
+
prediction_np = prediction.cpu().numpy()
|
| 277 |
+
image = Image.fromarray(prediction_np).convert("RGB")
|
| 278 |
+
image = image.resize((width, height), resample=Image.Resampling.BILINEAR)
|
| 279 |
+
return image
|
preprocessor_config.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"auto_map": {
|
| 3 |
+
"AutoImageProcessor": "image_processing_basnet.BASNetImageProcessor"
|
| 4 |
+
},
|
| 5 |
+
"image_processor_type": "BASNetImageProcessor",
|
| 6 |
+
"rescale_size": 256,
|
| 7 |
+
"to_tensor_lab_flag": 0
|
| 8 |
+
}
|