Spaces:
Sleeping
Sleeping
| 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 | |
| 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 |