Spaces:
Runtime error
Runtime error
import cv2 | |
from PIL import Image | |
import numpy as np | |
from transformers import AutoImageProcessor, UperNetForSemanticSegmentation | |
from transformers import SegformerFeatureExtractor, SegformerForSemanticSegmentation | |
class SegmentationTool: | |
def __init__(self, | |
segmentation_version='nvidia/segformer-b5-finetuned-ade-640-640'): | |
self.segmentation_version = segmentation_version | |
if segmentation_version == "openmmlab/upernet-convnext-tiny": | |
self.feature_extractor = AutoImageProcessor.from_pretrained(self.segmentation_version) | |
self.segmentation_model = UperNetForSemanticSegmentation.from_pretrained(self.segmentation_version) | |
elif segmentation_version == "nvidia/segformer-b5-finetuned-ade-640-640": | |
self.feature_extractor = SegformerFeatureExtractor.from_pretrained(self.segmentation_version) | |
self.segmentation_model = SegformerForSemanticSegmentation.from_pretrained(self.segmentation_version) | |
def _predict(self, image): | |
inputs = self.feature_extractor(images=image, return_tensors="pt") | |
outputs = self.segmentation_model(**inputs) | |
prediction = \ | |
self.feature_extractor.post_process_semantic_segmentation(outputs, target_sizes=[image.size[::-1]])[0] | |
return prediction | |
def _save_mask(self, prediction_array, mask_items=[]): | |
mask = np.zeros_like(prediction_array, dtype=np.uint8) | |
mask[np.isin(prediction_array, mask_items)] = 0 | |
mask[~np.isin(prediction_array, mask_items)] = 255 | |
buffer_size = 10 | |
# Dilate the binary image | |
kernel = np.ones((buffer_size, buffer_size), np.uint8) | |
dilated_image = cv2.dilate(mask, kernel, iterations=1) | |
# Subtract the original binary image | |
buffer_area = dilated_image - mask | |
# Apply buffer area to the original image | |
mask = cv2.bitwise_or(mask, buffer_area) | |
# # # Create a PIL Image object from the mask | |
mask_image = Image.fromarray(mask, mode='L') | |
# display(mask_image) | |
# mask_image = mask_image.resize((512, 512)) | |
# mask_image.save(".tmp/mask_1.png", "PNG") | |
# img = img.resize((512, 512)) | |
# img.save(".tmp/input_1.png", "PNG") | |
return mask_image | |
def _save_transparent_mask(self, img, prediction_array, mask_items=None): | |
if mask_items is None: | |
mask_items = [] | |
mask = np.array(img) | |
mask[~np.isin(prediction_array, mask_items), :] = 255 | |
mask_image = Image.fromarray(mask).convert('RGBA') | |
# Set the transparency of the pixels corresponding to object 1 to 0 (fully transparent) | |
mask_data = mask_image.getdata() | |
mask_data = [(r, g, b, 0) if r == 255 else (r, g, b, 255) for (r, g, b, a) in mask_data] | |
mask_image.putdata(mask_data) | |
return mask_image | |
def get_mask(self, image_path=None, image=None): | |
if image_path: | |
image = Image.open(image_path) | |
else: | |
if image is None: | |
raise ValueError("no image provided") | |
# display(image) | |
prediction = self._predict(image) | |
label_ids = np.unique(prediction) | |
# mask_items = [0, 3, 5, 8, 14] | |
mask_items = [8] # windowpane | |
if 73 in label_ids or 50 in label_ids or 61 in label_ids: | |
# mask_items = [0, 3, 5, 8, 14, 50, 61, 71, 73, 118, 124, 129] | |
room = 'kitchen' | |
elif 37 in label_ids or 65 in label_ids or (27 in label_ids and 47 in label_ids and 70 in label_ids): | |
# mask_items = [0, 3, 5, 8, 14, 27, 65] | |
room = 'bathroom' | |
elif 7 in label_ids: | |
room = 'bedroom' | |
elif 23 in label_ids or 49 in label_ids: | |
# mask_items = [0, 3, 5, 8, 14, 49] | |
room = 'living room' | |
elif 15 in label_ids and 19 in label_ids: | |
room = 'dining room' | |
else: | |
room = 'room' | |
label_ids_without_mask = [i for i in label_ids if i not in mask_items] | |
items = [self.segmentation_model.config.id2label[i] for i in label_ids_without_mask] | |
mask_image = self._save_mask(prediction, mask_items) | |
transparent_mask_image = self._save_transparent_mask(image, prediction, mask_items) | |
return mask_image, transparent_mask_image, image, items, room |