You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.5 KiB
90 lines
2.5 KiB
from pathlib import Path |
|
from collections import namedtuple |
|
|
|
import numpy |
|
from PIL import Image, ImageDraw, ImageFont |
|
|
|
Point = namedtuple("Point", ["x", "y"]) |
|
Spot = namedtuple("Spot", ["found", "x", "y"]) |
|
|
|
|
|
THIS_DIR = Path(__file__).absolute().parent |
|
FONT_PATH = THIS_DIR / "arial.ttf" |
|
FONT = ImageFont.truetype(str(FONT_PATH), 32) |
|
|
|
GREEN = (0, 255, 0) |
|
RED = (255, 0, 0) |
|
|
|
|
|
def recalculate(iterable, factor): |
|
recalculated = [v * factor for v in iterable] |
|
cls = type(iterable) |
|
try: |
|
return cls(*recalculated) |
|
except TypeError: |
|
return tuple(recalculated) |
|
|
|
|
|
def convert_16bit_to_8bit(img): |
|
array = numpy.uint8(numpy.array(img) / 256) |
|
return Image.fromarray(array) |
|
|
|
|
|
def convert_16bit_grey_to_color(img): |
|
return convert_16bit_to_8bit(img).convert(mode="RGB") |
|
|
|
|
|
def resize(img, scale=1): |
|
return img.resize(recalculate(img.size, scale)) |
|
|
|
|
|
def load_array_image(file_path, scale=1): |
|
img = Image.open(file_path) |
|
colored = convert_16bit_grey_to_color(img) |
|
return resize(colored, scale) |
|
|
|
|
|
def get_position(data_series, actual=True): |
|
prefix = "Pos" if actual else "Pos.Nom" |
|
x = int(data_series[f"{prefix}.X"]) |
|
y = int(data_series[f"{prefix}.Y"]) |
|
return Point(x, y) |
|
|
|
|
|
def get_box(center, width, height=None): |
|
height = width if height is None else height |
|
|
|
dx = width / 2 |
|
dy = height / 2 |
|
|
|
return (center.x - dx, center.y - dy, center.x + dx, center.y + dy) |
|
|
|
|
|
def annotate_spot(canvas, spot_parameters, spot_data, scale=1): |
|
found = spot_data["Spot.Found"] |
|
center = recalculate(get_position(spot_data, found), scale) |
|
color = GREEN if found else RED |
|
|
|
box = get_box(center, spot_parameters.roi_x, spot_parameters.roi_y) |
|
canvas.rectangle(box, outline=color, width=1) |
|
|
|
box = get_box(center, spot_parameters.radius_bkg) |
|
canvas.ellipse(box, outline=color, width=2) |
|
|
|
box = get_box(center, spot_parameters.radius_spot) |
|
canvas.ellipse(box, outline=color, width=1) |
|
|
|
canvas.text(center, str(spot_data["Pos.Id"]), RED, font=FONT) |
|
|
|
|
|
def annotate_image(array_img, spot_parameters, array_data, scale): |
|
canvas = ImageDraw.Draw(array_img) |
|
for index, spot_data in array_data.iterrows(): |
|
annotate_spot(canvas, spot_parameters, spot_data, scale) |
|
|
|
|
|
def crop(array_img, spot_parameters, spot_data, scale=1): |
|
found = spot_data["Spot.Found"] |
|
center = recalculate(get_position(spot_data, found), scale) |
|
box = get_box(center, spot_parameters.crop_x, spot_parameters.crop_y) |
|
return array_img.crop(box)
|
|
|