Spaces:
Sleeping
Sleeping
| import numpy as np | |
| import gzip | |
| from pathlib import Path | |
| import tempfile | |
| import cv2 | |
| import tensorflow as tf | |
| import skimage.morphology | |
| import skimage.filters.rank | |
| import skimage.util | |
| from tensorflow.keras.models import load_model | |
| from aix.utils import hardened_dice_coef | |
| from aix.losses import dice_loss | |
| class AreaModel: | |
| def __init__(self, model_path="model/majority_roi_production.keras"): | |
| self.model_path = model_path | |
| self.model = load_model(model_path) | |
| self.IMG_SIZE = (192, 240) | |
| self.INPUT_CHANNELS = 1 | |
| self.IMG_SHAPE = (self.IMG_SIZE[0], self.IMG_SIZE[1], self.INPUT_CHANNELS) | |
| self.MASK_SHAPE = (self.IMG_SIZE[0], self.IMG_SIZE[1], 1) | |
| def compute_area(self, img): | |
| roi_img = roi(img) | |
| roi_shape = roi_img.shape | |
| #print(roi_img.dtype, roi_shape) | |
| t_img = tensor(roi_img, self.IMG_SHAPE) | |
| y = self.model.predict(x=t_img) | |
| mask = y[0] | |
| #print(roi_shape) | |
| resized_mask = tf.image.resize(mask, roi_shape) | |
| area = np.sum(resized_mask) | |
| return area, roi_img, resized_mask | |
| def image_to_file_path(image): | |
| with tempfile.NamedTemporaryFile(delete=False) as temp_file: | |
| temp_file.write(image.read()) | |
| return temp_file.name | |
| def raw_image(file_path, remove_alpha=True): | |
| img = cv2.imread(file_path, cv2.IMREAD_GRAYSCALE) | |
| #print(img.shape) | |
| if len(img.shape) == 3 and img.shape[2] == 4: | |
| #print("The image is in RGBA format. We remove the A") | |
| img = img[:, :, :3] | |
| return img | |
| def tensor(img, shape): | |
| #img = raw_image(file_path, cv2.IMREAD_GRAYSCALE) | |
| if len(img.shape) == 2: | |
| img.shape = (img.shape[0], img.shape[1], 1) | |
| t = tf.convert_to_tensor(img) | |
| t = tf.image.resize(t, shape[:2]) | |
| t = tf.reshape(t, (1, *shape)) | |
| t = tf.cast(t, tf.float32) | |
| return t | |
| def roi(cv2_img): | |
| roi, (left, top), (right, bottom) = extract_roi(cv2_img / 255., filled=True, border=.01) | |
| #print("ROI found", (left, top), (right, bottom)) | |
| return cv2_img[top:bottom, left:right] | |
| def overlay_mask_on_image(image, mask, alpha=0.1, mask_color=(0, 255, 0)): | |
| """ | |
| Overlays a mask on an image. | |
| Args: | |
| image (np.array): The original image. | |
| mask (np.array): The mask to overlay. | |
| alpha (float): The opacity of the mask. | |
| mask_color (tuple): The color to use for the mask. | |
| Returns: | |
| np.array: The image with the mask overlay. | |
| """ | |
| rgb_image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB) | |
| colored_mask = np.zeros_like(rgb_image) | |
| #print(colored_mask.shape) | |
| #print(mask.shape) | |
| colored_mask[:, :, 0] = mask_color[0] * mask[:, :, 0] | |
| colored_mask[:, :, 1] = mask_color[1] * mask[:, :, 0] | |
| colored_mask[:, :, 2] = mask_color[2] * mask[:, :, 0] | |
| #colored_mask *= mask | |
| # Overlay the mask on the image | |
| overlay = cv2.addWeighted(rgb_image, 1, colored_mask, alpha, 0) | |
| return overlay | |
| def local_entropy(im, kernel_size=5, normalize=True): | |
| kernel=skimage.morphology.disk(kernel_size) | |
| entr_img = skimage.filters.rank.entropy(skimage.util.img_as_ubyte(im), kernel) | |
| if normalize: | |
| max_img = np.max(entr_img) | |
| entr_img = (entr_img*255/max_img).astype(np.uint8) | |
| return entr_img | |
| def calc_dim(contour): | |
| c_0 = [ point[0][0] for point in contour] | |
| c_1 = [ point[0][1] for point in contour] | |
| return (min(c_0), max(c_0), min(c_1), max(c_1)) | |
| def calc_size(dim): | |
| return (dim[1] - dim[0]) * (dim[3] - dim[2]) | |
| def calc_dist(dim1, dim2): | |
| return None | |
| def extract_roi(img, threshold=135, kernel_size=5, min_fratio=.3, max_sratio=5, filled=True, border=.01): | |
| entr_img = local_entropy(img, kernel_size=kernel_size) | |
| _, mask = cv2.threshold(entr_img, threshold, 255, cv2.THRESH_BINARY) | |
| contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) | |
| contours_d = [calc_dim(c) for c in contours] | |
| contours_sizes = [calc_size(c) for c in contours_d] | |
| contour_indices = np.argsort(contours_sizes)[::-1] | |
| # remove artifacts | |
| fratio = min_fratio | |
| sratio = max_sratio | |
| idx = -1 | |
| while fratio<=min_fratio or sratio>=max_sratio: | |
| idx += 1 | |
| biggest = contour_indices[idx] | |
| filled_mask = np.zeros(img.shape, dtype=np.uint8) | |
| filled_mask = cv2.fillPoly(filled_mask, [contours[biggest]], 255) | |
| fratio = filled_mask.sum()/255/contours_sizes[biggest] | |
| cdim = contours_d[biggest] | |
| sratio = (cdim[3]-cdim[2])/(cdim[1]-cdim[0]) | |
| if sratio<1: sratio = 1 / sratio | |
| #print(fratio, sratio, cdim, filled_mask.sum()//255) | |
| # generating the mask | |
| filled_mask = np.zeros(img.shape, dtype=np.uint8) | |
| extra = ( int(img.shape[0] * border) , int(img.shape[1] * border) ) | |
| origin = (max(0, cdim[0]-extra[1]), max(0, cdim[2]-extra[0])) | |
| to = (min(img.shape[1]-1 , cdim[1]+extra[1]), min(img.shape[0]-1 , cdim[3]+extra[0])) | |
| if filled: | |
| filled_mask = cv2.rectangle(filled_mask, origin, to, 255, -1) | |
| else: | |
| filled_mask = cv2.rectangle(filled_mask, origin, to, 255, 2) | |
| return filled_mask, origin, to | |