File size: 14,250 Bytes
10e69ed
 
 
 
 
 
 
 
 
 
 
 
ce469f2
 
10e69ed
 
 
ce469f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10e69ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ce469f2
10e69ed
ce469f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10e69ed
ce469f2
 
10e69ed
ce469f2
 
 
 
 
 
 
 
 
 
 
 
 
 
c4b5ce1
ce469f2
 
 
10e69ed
 
 
 
 
 
 
 
 
 
ce469f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10e69ed
 
 
 
 
 
 
ce469f2
10e69ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c4b5ce1
ce469f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10e69ed
 
ce469f2
 
10e69ed
 
 
 
 
 
 
 
 
 
 
 
 
 
ce469f2
10e69ed
 
 
 
 
ce469f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10e69ed
 
 
 
 
ce469f2
10e69ed
 
 
 
 
 
ce469f2
 
 
 
 
 
 
 
 
 
 
10e69ed
 
 
 
 
ce469f2
10e69ed
ce469f2
10e69ed
ce469f2
10e69ed
ce469f2
10e69ed
 
 
 
 
 
ce469f2
 
 
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
import requests
from pycocotools import mask
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw, ImageOps, ImageFont
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




# Función para transformar la entrada en un array de numpy
# Si la entrada es una URL, descarga la imagen y la convierte en un array de numpy
# Si la entrada es una ruta de archivo, carga la imagen y la convierte en un array de numpy
# Si la entrada ya es un array de numpy, devuélvela tal cual
# Si la entrada no es ninguna de las anteriores, lanza un ValueError

def transform_image_to_numpy_array(input):
    if isinstance(input, np.ndarray):
        # Si la entrada es un array de numpy, devuélvela tal cual
        h, w = input.shape[:2]
        new_height = int(h * (500 / w))
        return cv2.resize(input, (500, new_height))
    elif isinstance(input, str):
        # Si la entrada es una cadena, podría ser una URL o una ruta de archivo
        if input.startswith('http://') or input.startswith('https://'):
            # Si la entrada es una URL, descarga la imagen y conviértela en un array de numpy
            # se necesita un header para evitar el error 403
            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)
            
            # Si la imagen tiene 3 canales (es decir, es una imagen en color),
            # convertirla de BGR a RGB
            if image.ndim == 3:
                image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
            image = Image.fromarray(image).convert("RGBA") 
            image = np.array(image)
        else:
            # Si la entrada es una ruta de archivo, carga la imagen y conviértela en un array de numpy
            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):
        # Si la entrada es un array de numpy, devuélvela tal cual
        return cv2.resize(input, (500, 500))
    elif isinstance(input, str):
        # Si la entrada es una cadena, podría ser una URL o una ruta de archivo
        if input.startswith('http://') or input.startswith('https://'):
            # Si la entrada es una URL, descarga la imagen y conviértela en un array de numpy
            # se necesita un header para evitar el error 403
            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)
            
             # Si la imagen tiene 3 canales (es decir, es una imagen en color),
             # convertirla de BGR a RGB
            if image.ndim == 3:
                image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
            image = Image.fromarray(image).convert("RGBA") 
            image = np.array(image)
        else:
            # Si la entrada es una ruta de archivo, carga la imagen y conviértela en un array de numpy
            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, api_token, model):
    
    #API_URL = "https://api-inference.huggingface.co/models/facebook/mask2former-swin-tiny-coco-panoptic"
    API_URL = f"https://api-inference.huggingface.co/models/{model}"
    headers = {"Authorization": f"Bearer {api_token}"}
    ic(API_URL)
    ic(headers)
    # Convert the image to bytes
    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):
    # Convert the image to bytes
    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)
        
        # Calcula el centroide de la mascara
        x, y = np.where(np.array(mask_image) > 0)
        centroid_x = x.mean()
        centroid_y = y.mean()
        
        # Imprime la etiqueta y la puntuación en la capa de texto
        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}"
        
        # Calcula el tamaño del texto
        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]
        
        # Asegúrate de que las coordenadas del texto están dentro de los límites de la imagen
        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)
    
    # Ajusta la transparencia de la capa de superposición
    overlay = Image.blend(original_image, overlay, transparency)

    # Combina la capa de superposición con la capa de texto
    final_image = Image.alpha_composite(overlay, text_layer)
    
    return final_image








def overlay_masks_on_image2(image, segments, transparency=0.4):
    # Convert numpy array to PIL Image
    #original_image = Image.fromarray(image).convert("RGBA")
    #original_image = image
    #original_image = Image.open(image).convert("RGBA")
    # para file es str
    # para url es numpy.ndarray
    # para cv.imread es numpy.ndarray
    
    # Convertir el array de numpy a una imagen PIL si es necesario
    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)
    # Nueva capa para el texto

    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)
        
        
        
        # Convierte la imagen de la máscara a un array de numpy
        mask_array = np.array(mask_image)

        # Encuentra los píxeles blancos
        y, x = np.where(mask_array > 0)

        # Calcula el cuadro delimitador de los píxeles blancos
        x_min, y_min, width, height = cv2.boundingRect(np.array(list(zip(x, y))))

    
        # Crea un objeto ImageDraw para dibujar en la imagen original
        draw = ImageDraw.Draw(original_image)   
        
                
        # Dibuja el cuadro delimitador en la imagen original
        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)
        
        
        # Calcula el centroide de la mascara
        
        x, y = np.where(np.array(mask_image) > 0)
        centroid_x = x.mean()
        centroid_y = y.mean()
        
        # Imprime la etiqueta y la puntuación en la capa de texto
        
        font_size = 30
        draw = ImageDraw.Draw(text_layer)
        font_path = "/System/Library/Fonts/Arial.ttf"  # Path to Arial font on macOS
        font = ImageFont.truetype(font_path, font_size)
        label = segment['label']
        score = segment['score']
        text =f"{label}: {score}"
        
        # Estima el tamaño del texto hard rockandroll way
       
        text_width = 500
        text_height = 100
        
        
        # Asegúrate de que las coordenadas del texto están dentro de los límites de la imagen
        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))
# Asegúrate de que las coordenadas del texto están dentro de los límites de la imagen
        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))


        # Calcula las coordenadas del texto
        text_x = centroid_x - text_width / 2
        text_y = centroid_y - text_height / 2
        
        
        # Asegúrate de que las coordenadas del texto están dentro de los límites de la imagen
        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)

        #draw.text((text_x, text_y), text, fill=(255, 255, 255, 255), font=font)
    
    # Ajusta la transparencia de la capa de superposición
    print(original_image.size)
    print(overlay.size)
    overlay = Image.blend(original_image, overlay, transparency)

    # Combina la capa de superposición con la capa de texto
    
    final_image = Image.alpha_composite(overlay, text_layer)
    
    #final_image = print_text_on_image_centered(final_image, 'SEGMENTING OK', 'green')
    
    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):
    #segments = segment_image_from_image(image)
    #final_image = overlay_masks_on_image(image, segments)
    #return final_image
    processed_image = None  # Initialize processed_image
    segments = []
    #image_type = None
    #if isinstance(image_path, str):
    #    image_type = 'FILE'
    #    image = cv2.imread('cats.jpg')
    #elif isinstance(image_path, np.ndarray):
    #    image_type = 'NUMPY ARRAY'
    #else:
    #    raise ValueError("The image is neither a Image nor a local file.")  
          
    #ic(image_type)
    image = transform_image_to_numpy_array(image_path)
    # imprime tres primeros pixeles
    print(type(image))
    ic(image[0, 0:3])
    
    
    
    
    try:
        #segments = segment_image_from_image(image)
        #processed_image = overlay_masks_on_image(image, segments) 
        
        # debug image contents

        #if os.path.isfile(image):
       #     ic ("--- image is a file ---")
       #     image = Image.open(image)
       # if image is None:
       #     ic("image is None")
       #     return None, []
        
        ic("--- calling segment_image_from_path ---")    
        segments = segment_image_from_numpy(image, api_token, model)
        #if image_type == 'FILE':
        #    segments = segment_image_from_path(image_path)
        #if image_type == 'NUMPY ARRAY':
        #    segments = segment_image_from_image(image_path)
            
        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)
        return processed_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