|
import requests |
|
from pycocotools import mask |
|
import matplotlib.pyplot as plt |
|
from PIL import Image, ImageDraw, ImageOps, ImageFont |
|
from dotenv import find_dotenv, load_dotenv |
|
import os |
|
import base64 |
|
import io |
|
import random |
|
import numpy as np |
|
import cv2 |
|
from image_utils import print_text_on_image_centered, create_background_image |
|
from icecream import ic |
|
import traceback |
|
from pprint import pprint |
|
|
|
|
|
load_dotenv(find_dotenv()) |
|
HUGGINGFACEHUB_API_TOKEN = os.getenv("HUGGINGFACEHUB_API_TOKEN") |
|
|
|
API_URL = "https://api-inference.huggingface.co/models/facebook/mask2former-swin-tiny-coco-panoptic" |
|
headers = {"Authorization": f"Bearer {HUGGINGFACEHUB_API_TOKEN}"} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def transform_image_to_numpy_array(input): |
|
if isinstance(input, np.ndarray): |
|
|
|
h, w = input.shape[:2] |
|
new_height = int(h * (500 / w)) |
|
return cv2.resize(input, (500, new_height)) |
|
elif isinstance(input, str): |
|
|
|
if input.startswith('http://') or input.startswith('https://'): |
|
|
|
|
|
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36"} |
|
response = requests.get(input, headers=headers) |
|
ic(response.status_code) |
|
image_array = np.frombuffer(response.content, dtype=np.uint8) |
|
image = cv2.imdecode(image_array, -1) |
|
|
|
|
|
|
|
if image.ndim == 3: |
|
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) |
|
image = Image.fromarray(image).convert("RGBA") |
|
image = np.array(image) |
|
else: |
|
|
|
image = cv2.imread(input) |
|
|
|
h, w = image.shape[:2] |
|
new_height = int(h * (500 / w)) |
|
return cv2.resize(image, (500, new_height)) |
|
else: |
|
raise ValueError("La entrada no es un array de numpy, una URL ni una ruta de archivo.") |
|
|
|
def transform_image_to_numpy_array2(input): |
|
if isinstance(input, np.ndarray): |
|
|
|
return cv2.resize(input, (500, 500)) |
|
elif isinstance(input, str): |
|
|
|
if input.startswith('http://') or input.startswith('https://'): |
|
|
|
|
|
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36"} |
|
response = requests.get(input, headers=headers) |
|
ic(response.status_code) |
|
image_array = np.frombuffer(response.content, dtype=np.uint8) |
|
image = cv2.imdecode(image_array, -1) |
|
|
|
|
|
|
|
if image.ndim == 3: |
|
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) |
|
image = Image.fromarray(image).convert("RGBA") |
|
image = np.array(image) |
|
else: |
|
|
|
image = cv2.imread(input) |
|
|
|
return cv2.resize(image, (500, 500)) |
|
else: |
|
raise ValueError("La entrada no es un array de numpy, una URL ni una ruta de archivo.") |
|
|
|
def segment_image_from_numpy(image_array): |
|
|
|
is_success, im_buf_arr = cv2.imencode(".jpg", image_array) |
|
data = im_buf_arr.tobytes() |
|
response = requests.post(API_URL, headers=headers, data=data) |
|
pprint(response.json()) |
|
return response.json() |
|
|
|
|
|
def segment_image_from_path(image_path): |
|
with open(image_path, "rb") as f: |
|
data = f.read() |
|
response = requests.post(API_URL, headers=headers, data=data) |
|
return response.json() |
|
|
|
def segment_image_from_image(image): |
|
|
|
is_success, im_buf_arr = cv2.imencode(".jpg", image) |
|
data = im_buf_arr.tobytes() |
|
|
|
response = requests.post(API_URL, headers=headers, data=data) |
|
return response.json() |
|
|
|
def decode_mask(mask_str, size): |
|
mask_data = base64.b64decode(mask_str) |
|
mask_image = Image.open(io.BytesIO(mask_data)) |
|
mask_image = mask_image.resize(size).convert("L") |
|
return mask_image |
|
|
|
|
|
def overlay_masks_on_image(image, segments, transparency=0.4): |
|
if isinstance(image, np.ndarray): |
|
image = Image.fromarray(image) |
|
|
|
original_image = image |
|
if original_image.mode != 'RGBA': |
|
original_image = original_image.convert('RGBA') |
|
|
|
overlay = Image.new("RGBA", original_image.size, (255, 255, 255, 0)) |
|
text_layer = Image.new("RGBA", original_image.size, (255, 255, 255, 0)) |
|
|
|
for segment in segments: |
|
mask_str = segment['mask'] |
|
mask_image = decode_mask(mask_str, original_image.size) |
|
color = generate_random_color() |
|
|
|
color_mask = ImageOps.colorize(mask_image, black="black", white=color) |
|
color_mask.putalpha(mask_image) |
|
|
|
overlay = Image.alpha_composite(overlay, color_mask) |
|
|
|
|
|
x, y = np.where(np.array(mask_image) > 0) |
|
centroid_x = x.mean() |
|
centroid_y = y.mean() |
|
|
|
|
|
font_size = 30 |
|
draw = ImageDraw.Draw(text_layer) |
|
font = ImageFont.load_default().font_variant(size=font_size) |
|
label = segment['label'] |
|
score = segment['score'] |
|
text =f"{label}: {score}" |
|
|
|
|
|
text_bbox = draw.textbbox((0, 0), text, font=font) |
|
text_width = text_bbox[2] - text_bbox[0] |
|
text_height = text_bbox[3] - text_bbox[1] |
|
|
|
|
|
text_x = max(0, min(centroid_x - text_width / 2, original_image.size[0] - text_width)) |
|
text_y = max(0, min(centroid_y - text_height / 2, original_image.size[1] - text_height)) |
|
|
|
draw.text((text_x, text_y), text, fill=(255, 255, 255, 255), font=font) |
|
|
|
|
|
overlay = Image.blend(original_image, overlay, transparency) |
|
|
|
|
|
final_image = Image.alpha_composite(overlay, text_layer) |
|
|
|
return final_image |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def overlay_masks_on_image2(image, segments, transparency=0.4): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if isinstance(image, np.ndarray): |
|
image = Image.fromarray(image) |
|
|
|
print(type(image)) |
|
print(image) |
|
original_image = image |
|
|
|
if original_image.mode != 'RGBA': |
|
original_image = original_image.convert('RGBA') |
|
|
|
print(original_image.size) |
|
overlay = Image.new("RGBA", original_image.size, (255, 255, 255, 0)) |
|
print(overlay.size) |
|
|
|
|
|
text_layer = Image.new("RGBA", original_image.size, (255, 255, 255, 0)) |
|
|
|
for segment in segments: |
|
|
|
|
|
print(segment['label'] + " " + str(segment['score'])) |
|
mask_str = segment['mask'] |
|
mask_image = decode_mask(mask_str, original_image.size) |
|
|
|
|
|
|
|
|
|
mask_array = np.array(mask_image) |
|
|
|
|
|
y, x = np.where(mask_array > 0) |
|
|
|
|
|
x_min, y_min, width, height = cv2.boundingRect(np.array(list(zip(x, y)))) |
|
|
|
|
|
|
|
draw = ImageDraw.Draw(original_image) |
|
|
|
|
|
|
|
draw.rectangle([(x_min, y_min), (x_min + width, y_min + height)], outline=(0, 255, 0), width=2) |
|
|
|
|
|
color = generate_random_color() |
|
|
|
color_mask = ImageOps.colorize(mask_image, black="black", white=color) |
|
color_mask.putalpha(mask_image) |
|
|
|
overlay = Image.alpha_composite(overlay, color_mask) |
|
|
|
|
|
|
|
|
|
x, y = np.where(np.array(mask_image) > 0) |
|
centroid_x = x.mean() |
|
centroid_y = y.mean() |
|
|
|
|
|
|
|
font_size = 30 |
|
draw = ImageDraw.Draw(text_layer) |
|
font_path = "/System/Library/Fonts/Arial.ttf" |
|
font = ImageFont.truetype(font_path, font_size) |
|
label = segment['label'] |
|
score = segment['score'] |
|
text =f"{label}: {score}" |
|
|
|
|
|
|
|
text_width = 500 |
|
text_height = 100 |
|
|
|
|
|
|
|
text_x = max(0, min(centroid_x - text_width / 2, original_image.size[0] - text_width)) |
|
text_y = max(0, min(centroid_y - text_height / 2, original_image.size[1] - text_height)) |
|
|
|
text_x = max(0, min(centroid_x, original_image.size[0] - text_width)) |
|
text_y = max(0, min(centroid_y, original_image.size[1] - text_height)) |
|
|
|
|
|
|
|
text_x = centroid_x - text_width / 2 |
|
text_y = centroid_y - text_height / 2 |
|
|
|
|
|
|
|
text_x = max(0, min(text_x, original_image.size[0] - text_width)) |
|
text_y = max(0, min(text_y, original_image.size[1] - text_height)) |
|
|
|
|
|
draw.text((centroid_x - text_width / 2, centroid_y - text_height / 2), text, fill=(255, 255, 255, 255), font=font) |
|
|
|
|
|
|
|
|
|
print(original_image.size) |
|
print(overlay.size) |
|
overlay = Image.blend(original_image, overlay, transparency) |
|
|
|
|
|
|
|
final_image = Image.alpha_composite(overlay, text_layer) |
|
|
|
|
|
|
|
return final_image |
|
|
|
def generate_random_color(): |
|
return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) |
|
|
|
|
|
def segment_and_overlay_results(image_path, api_token, model): |
|
|
|
|
|
|
|
processed_image = None |
|
segments = [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
image = transform_image_to_numpy_array(image_path) |
|
|
|
print(type(image)) |
|
ic(image[0, 0:3]) |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ic("--- calling segment_image_from_path ---") |
|
segments = segment_image_from_numpy(image) |
|
|
|
|
|
|
|
|
|
|
|
ic("--- printing segments ---") |
|
for segment in segments: |
|
ic(segment['label'] ,segment['score']) |
|
processed_image = print_text_on_image_centered( |
|
create_background_image(500, 500, "white"), |
|
'SEGMENTING OK', |
|
'green' |
|
) |
|
ic("--- calling overlay_masks_on_image ---") |
|
processed_image = overlay_masks_on_image(image, segments) |
|
except Exception as e: |
|
print("EXCEPTION") |
|
ic(e) |
|
print(traceback.format_exc()) |
|
processed_image = print_text_on_image_centered( |
|
create_background_image(500, 500, "white"), |
|
e, |
|
'green' |
|
) |
|
segments = [] |
|
return processed_image, segments |
|
finally: |
|
return processed_image, segments |