MolParser-Mobile / image_processing_molparser_mobile.py
AI4Industry's picture
Upload MolParser-Mobile
c81207b verified
Raw
History Blame Contribute Delete
3.57 kB
"""Image processor for MolParser Mobile."""
from __future__ import annotations
from typing import List, Sequence, Union
import cv2
import numpy as np
import torch
from PIL import Image
from transformers import BaseImageProcessor
from transformers.feature_extraction_utils import BatchFeature
ImageInput = Union[str, Image.Image, np.ndarray, torch.Tensor]
class MolParserImageProcessor(BaseImageProcessor):
model_input_names = ["pixel_values"]
def __init__(
self,
image_size: int = 224,
do_resize: bool = True,
do_normalize: bool = True,
image_mean: Sequence[float] = (0.485, 0.456, 0.406),
image_std: Sequence[float] = (0.229, 0.224, 0.225),
**kwargs,
):
super().__init__(**kwargs)
self.image_size = int(image_size)
self.do_resize = bool(do_resize)
self.do_normalize = bool(do_normalize)
self.image_mean = list(image_mean)
self.image_std = list(image_std)
@property
def size(self):
return {"height": self.image_size, "width": self.image_size}
def _to_pil(self, image: ImageInput) -> Image.Image:
if isinstance(image, Image.Image):
return image.convert("RGB")
if isinstance(image, str):
return Image.open(image).convert("RGB")
if isinstance(image, torch.Tensor):
tensor = image.detach().cpu()
if tensor.ndim == 3 and tensor.shape[0] in {1, 3, 4}:
tensor = tensor.permute(1, 2, 0)
array = tensor.numpy()
else:
array = np.asarray(image)
if array.dtype != np.uint8:
if array.max() <= 1.0:
array = array * 255.0
array = np.clip(np.rint(array), 0, 255).astype(np.uint8)
if array.ndim == 2:
return Image.fromarray(array, mode="L").convert("RGB")
if array.shape[-1] == 4:
return Image.fromarray(array, mode="RGBA").convert("RGB")
return Image.fromarray(array).convert("RGB")
def _preprocess_one(self, image: ImageInput) -> np.ndarray:
pil_image = self._to_pil(image)
array = np.asarray(pil_image).astype(np.uint8)
if self.do_resize:
# Match deploy/transform.py: albumentations.Resize defaults to OpenCV INTER_LINEAR.
array = cv2.resize(array, (self.image_size, self.image_size), interpolation=cv2.INTER_LINEAR)
array = array.astype(np.float32) / 255.0
if self.do_normalize:
mean = np.asarray(self.image_mean, dtype=np.float32).reshape(1, 1, 3)
std = np.asarray(self.image_std, dtype=np.float32).reshape(1, 1, 3)
array = (array - mean) / std
return np.transpose(array, (2, 0, 1))
def preprocess(
self,
images: Union[ImageInput, Sequence[ImageInput]],
return_tensors: str | None = None,
**kwargs,
) -> BatchFeature:
if not isinstance(images, (list, tuple)):
images = [images]
pixel_values: List[np.ndarray] = [self._preprocess_one(image) for image in images]
data = {"pixel_values": np.stack(pixel_values, axis=0)}
encoded = BatchFeature(data=data)
if return_tensors is not None:
encoded = encoded.convert_to_tensors(return_tensors)
return encoded
def __call__(self, images: Union[ImageInput, Sequence[ImageInput]], return_tensors: str | None = None, **kwargs):
return self.preprocess(images=images, return_tensors=return_tensors, **kwargs)
__all__ = ["MolParserImageProcessor"]