Spaces:
Sleeping
Sleeping
File size: 2,885 Bytes
7435e6e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | from PIL import Image, ImageDraw, ImageFont
import numpy as np
from scipy import ndimage
from dataclasses import dataclass
from typing import Any, List
from zipfile import ZipFile
def add_text(image: Image.Image, text: str, location=(0.5, 0.5), color='red', size=40) -> Image.Image:
draw = ImageDraw.Draw(image)
font = ImageFont.load_default(size=size)
draw.text((int(image.size[0]*location[0]), int(image.size[1]*location[1])), text, font=font, fill=color)
return image
def select_unique_mask(mask):
"""if mask consists of multiple parts, select the largest"""
blobs = ndimage.label(mask)[0]
blob_labels, blob_sizes = np.unique(blobs, return_counts=True)
best_blob_label = blob_labels[1:][np.argmax(blob_sizes[1:])]
return blobs == best_blob_label
def object_slice(mask, margin=128):
rows = np.any(mask, axis=1)
cols = np.any(mask, axis=0)
row_min, row_max = np.where(rows)[0][[0, -1]]
col_min, col_max = np.where(cols)[0][[0, -1]]
# Create a slice object for the bounding box
bounding_box_slice = (
slice(max(0,row_min-margin), min(row_max + 1+margin, len(rows)+1)),
slice(max(0,col_min-margin), min(col_max + 1+margin, len(cols)+1))
)
return bounding_box_slice
def resize_to(image: Image.Image, s=4032) -> Image.Image:
w, h = image.size
longest_size = max(h, w)
resize_factor = longest_size / s
resized_image = image.resize((int(w/resize_factor), int(h/resize_factor)))
return resized_image
def rolling_mean(x, window):
cs = np.r_[0, np.cumsum(x)]
rolling_sum = cs[window:] - cs[:-window]
return rolling_sum/window
@dataclass
class Granum:
image: Any = None#Optional[np.ndarray] = None
mask: Any = None #Optional[np.ndarray] = None
scaler: Any = None
nm_per_px: float = float('nan')
detection_confidence: float = float('nan')
def zip_files(files: List[str], output_name: str) -> None:
with ZipFile(output_name, "w") as zipObj:
for file in files:
zipObj.write(file)
def filter_boundary_detections(masks, scaler=None):
last_index_right = -1 if scaler is None else masks.shape[1]-1-scaler.pad_right
last_index_bottom = -1 if scaler is None else masks.shape[2]-1-scaler.pad_bottom
doesnt_touch_boundary_mask = ~(np.any(masks[:,0,:] != 0, axis=1) | np.any(masks[:,last_index_right:,:] != 0, axis=(1,2)) | np.any(masks[:,:,0] != 0, axis=1) | np.any(masks[:,:,last_index_bottom:] != 0, axis=(1,2)))
return doesnt_touch_boundary_mask
def get_circle_mask(shape, r=None):
if isinstance(shape, int):
shape = (shape, shape)
if r is None:
r = min(shape)/2
X, Y = np.meshgrid(np.arange(shape[1]), np.arange(shape[0]))
center_x = shape[1] / 2 - 0.5
center_y = shape[0] / 2 - 0.5
mask = ((X-center_x)**2 + (Y-center_y)**2) >= r**2
return mask |