83 lines
2.4 KiB
Python
83 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
from base64 import b64decode
|
|
from base64 import b64encode
|
|
from io import BytesIO
|
|
from pathlib import Path
|
|
|
|
from PIL import Image
|
|
from pydantic import BaseModel
|
|
from pydantic import field_serializer
|
|
from pydantic import field_validator
|
|
|
|
from core.dto import ModelData
|
|
|
|
|
|
class NoDocumentFoundException(Exception):
|
|
pass
|
|
|
|
|
|
class VisualCommunication(BaseModel):
|
|
name: str
|
|
image: Image.Image
|
|
annotation: ModelData | None = None
|
|
prediction: ModelData | None = None
|
|
|
|
class Config:
|
|
arbitrary_types_allowed = True
|
|
|
|
@classmethod
|
|
def classname(cls) -> str:
|
|
"""Return classname."""
|
|
return cls.__name__
|
|
|
|
@classmethod
|
|
def from_file(cls, path: Path) -> VisualCommunication:
|
|
"""Instantiate from file."""
|
|
name = path.stem
|
|
image = Image.open(path)
|
|
image.load()
|
|
return VisualCommunication(name=name, image=image)
|
|
|
|
@classmethod
|
|
def decode_image(cls, content: str) -> Image.Image:
|
|
"""Decode image."""
|
|
_, content_data = content.split(',')
|
|
return Image.open(BytesIO(b64decode(content_data)))
|
|
|
|
@field_serializer('image')
|
|
def serialize_image(image: Image.Image) -> bytes: # type: ignore
|
|
buffer = BytesIO()
|
|
image.save(buffer, format='JPEG')
|
|
return buffer.getvalue()
|
|
|
|
@field_validator('image', mode='before')
|
|
@classmethod
|
|
def convert_to_image(
|
|
cls,
|
|
image: Image.Image | BytesIO | bytes,
|
|
) -> Image.Image:
|
|
if isinstance(image, bytes):
|
|
image = BytesIO(image)
|
|
if isinstance(image, BytesIO):
|
|
image = Image.open(image)
|
|
return image
|
|
|
|
def __repr__(self) -> str:
|
|
return f"{self.classname()}(name='{self.name}')"
|
|
|
|
def webencoded_image(self) -> str:
|
|
"""Convert image to be displayed on webpage."""
|
|
# convert images to bytes string
|
|
buffer = BytesIO()
|
|
self.image.save(buffer, format='png')
|
|
img_enc = b64encode(buffer.getvalue()).decode('utf-8')
|
|
return f"data:image/png;base64, {img_enc}"
|
|
|
|
def generate_random_prediction(self, force: bool = False) -> None:
|
|
"""Generate random prediction values."""
|
|
if not force and self.prediction is not None:
|
|
logging.warning('set force=True to overwrite existing values.')
|
|
self.prediction = ModelData.from_random()
|