Manu commited on
Commit
ce469f2
·
1 Parent(s): c4b5ce1

fixed bug in segmentation_utils.py

Browse files
Files changed (1) hide show
  1. segmentation_utils.py +249 -40
segmentation_utils.py CHANGED
@@ -2,7 +2,6 @@ import requests
2
  from pycocotools import mask
3
  import matplotlib.pyplot as plt
4
  from PIL import Image, ImageDraw, ImageOps, ImageFont
5
- from dotenv import find_dotenv, load_dotenv
6
  import os
7
  import base64
8
  import io
@@ -11,13 +10,94 @@ import numpy as np
11
  import cv2
12
  from image_utils import print_text_on_image_centered, create_background_image
13
  from icecream import ic
 
 
14
 
15
 
16
- load_dotenv(find_dotenv())
17
- HUGGINGFACEHUB_API_TOKEN = os.getenv("HUGGINGFACEHUB_API_TOKEN")
18
 
19
- API_URL = "https://api-inference.huggingface.co/models/facebook/mask2former-swin-tiny-coco-panoptic"
20
- headers = {"Authorization": f"Bearer {HUGGINGFACEHUB_API_TOKEN}"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  def segment_image_from_path(image_path):
23
  with open(image_path, "rb") as f:
@@ -39,13 +119,90 @@ def decode_mask(mask_str, size):
39
  mask_image = mask_image.resize(size).convert("L")
40
  return mask_image
41
 
 
42
  def overlay_masks_on_image(image, segments, transparency=0.4):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  # Convert numpy array to PIL Image
44
- original_image = Image.fromarray(image).convert("RGBA")
45
-
46
  #original_image = Image.open(image).convert("RGBA")
47
- overlay = Image.new("RGBA", original_image.size, (255, 255, 255, 0))
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
 
 
 
49
  # Nueva capa para el texto
50
 
51
  text_layer = Image.new("RGBA", original_image.size, (255, 255, 255, 0))
@@ -56,6 +213,27 @@ def overlay_masks_on_image(image, segments, transparency=0.4):
56
  print(segment['label'] + " " + str(segment['score']))
57
  mask_str = segment['mask']
58
  mask_image = decode_mask(mask_str, original_image.size)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  color = generate_random_color()
60
 
61
  color_mask = ImageOps.colorize(mask_image, black="black", white=color)
@@ -63,6 +241,7 @@ def overlay_masks_on_image(image, segments, transparency=0.4):
63
 
64
  overlay = Image.alpha_composite(overlay, color_mask)
65
 
 
66
  # Calcula el centroide de la mascara
67
 
68
  x, y = np.where(np.array(mask_image) > 0)
@@ -83,11 +262,33 @@ def overlay_masks_on_image(image, segments, transparency=0.4):
83
 
84
  text_width = 500
85
  text_height = 100
86
- draw.text((centroid_x - text_width / 2, centroid_y - text_height / 2), text, fill=(255, 255, 255, 255), font=font)
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
  # Ajusta la transparencia de la capa de superposición
90
-
 
91
  overlay = Image.blend(original_image, overlay, transparency)
92
 
93
  # Combina la capa de superposición con la capa de texto
@@ -102,63 +303,71 @@ def generate_random_color():
102
  return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
103
 
104
 
105
- def segment_and_overlay_results(image, api_token, model):
106
  #segments = segment_image_from_image(image)
107
  #final_image = overlay_masks_on_image(image, segments)
108
  #return final_image
109
  processed_image = None # Initialize processed_image
110
  segments = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  try:
112
  #segments = segment_image_from_image(image)
113
  #processed_image = overlay_masks_on_image(image, segments)
114
 
115
  # debug image contents
116
-
117
- ic(image)
118
-
119
- if image.startswith('http://') or image.startswith('https://'):
120
- ic("image is a URL: " + image)
121
- response = requests.get(image)
122
- image = Image.open(BytesIO(response.content))
123
- else:
124
- # Check if image is a local file
125
-
126
-
127
- if os.path.isfile(os.path.join(os.getcwd(), image)):
128
- ic("image is a file: " + image + "OK")
129
- image = Image.open(image)
130
- else:
131
- raise ValueError("The image is neither a URL nor a local file.")
132
-
133
-
134
-
135
  #if os.path.isfile(image):
136
  # ic ("--- image is a file ---")
137
  # image = Image.open(image)
138
  # if image is None:
139
  # ic("image is None")
140
  # return None, []
141
- print(image)
142
- ic("--- calling segment_image_from_image ---")
143
- #segments = segment_image_from_image(image)
144
- segments = segment_image_from_path('cats.jpg')
145
- for segment in segments:
146
- print("segmentation_utils.py segment_and_overlay_results")
147
- print(segment['label'] + " " + str(segment['score']))
 
 
 
 
148
  processed_image = print_text_on_image_centered(
149
  create_background_image(500, 500, "white"),
150
  'SEGMENTING OK',
151
  'green'
152
  )
153
- print("--- calling overlay_masks_on_image ---")
154
  processed_image = overlay_masks_on_image(image, segments)
 
155
  except Exception as e:
 
156
  ic(e)
 
157
  processed_image = print_text_on_image_centered(
158
  create_background_image(500, 500, "white"),
159
  e,
160
  'green'
161
  )
162
  segments = []
163
- finally:
164
- return processed_image, segments
 
 
2
  from pycocotools import mask
3
  import matplotlib.pyplot as plt
4
  from PIL import Image, ImageDraw, ImageOps, ImageFont
 
5
  import os
6
  import base64
7
  import io
 
10
  import cv2
11
  from image_utils import print_text_on_image_centered, create_background_image
12
  from icecream import ic
13
+ import traceback
14
+ from pprint import pprint
15
 
16
 
 
 
17
 
18
+
19
+ # Función para transformar la entrada en un array de numpy
20
+ # Si la entrada es una URL, descarga la imagen y la convierte en un array de numpy
21
+ # Si la entrada es una ruta de archivo, carga la imagen y la convierte en un array de numpy
22
+ # Si la entrada ya es un array de numpy, devuélvela tal cual
23
+ # Si la entrada no es ninguna de las anteriores, lanza un ValueError
24
+
25
+ def transform_image_to_numpy_array(input):
26
+ if isinstance(input, np.ndarray):
27
+ # Si la entrada es un array de numpy, devuélvela tal cual
28
+ h, w = input.shape[:2]
29
+ new_height = int(h * (500 / w))
30
+ return cv2.resize(input, (500, new_height))
31
+ elif isinstance(input, str):
32
+ # Si la entrada es una cadena, podría ser una URL o una ruta de archivo
33
+ if input.startswith('http://') or input.startswith('https://'):
34
+ # Si la entrada es una URL, descarga la imagen y conviértela en un array de numpy
35
+ # se necesita un header para evitar el error 403
36
+ 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"}
37
+ response = requests.get(input, headers=headers)
38
+ ic(response.status_code)
39
+ image_array = np.frombuffer(response.content, dtype=np.uint8)
40
+ image = cv2.imdecode(image_array, -1)
41
+
42
+ # Si la imagen tiene 3 canales (es decir, es una imagen en color),
43
+ # convertirla de BGR a RGB
44
+ if image.ndim == 3:
45
+ image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
46
+ image = Image.fromarray(image).convert("RGBA")
47
+ image = np.array(image)
48
+ else:
49
+ # Si la entrada es una ruta de archivo, carga la imagen y conviértela en un array de numpy
50
+ image = cv2.imread(input)
51
+
52
+ h, w = image.shape[:2]
53
+ new_height = int(h * (500 / w))
54
+ return cv2.resize(image, (500, new_height))
55
+ else:
56
+ raise ValueError("La entrada no es un array de numpy, una URL ni una ruta de archivo.")
57
+
58
+ def transform_image_to_numpy_array2(input):
59
+ if isinstance(input, np.ndarray):
60
+ # Si la entrada es un array de numpy, devuélvela tal cual
61
+ return cv2.resize(input, (500, 500))
62
+ elif isinstance(input, str):
63
+ # Si la entrada es una cadena, podría ser una URL o una ruta de archivo
64
+ if input.startswith('http://') or input.startswith('https://'):
65
+ # Si la entrada es una URL, descarga la imagen y conviértela en un array de numpy
66
+ # se necesita un header para evitar el error 403
67
+ 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"}
68
+ response = requests.get(input, headers=headers)
69
+ ic(response.status_code)
70
+ image_array = np.frombuffer(response.content, dtype=np.uint8)
71
+ image = cv2.imdecode(image_array, -1)
72
+
73
+ # Si la imagen tiene 3 canales (es decir, es una imagen en color),
74
+ # convertirla de BGR a RGB
75
+ if image.ndim == 3:
76
+ image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
77
+ image = Image.fromarray(image).convert("RGBA")
78
+ image = np.array(image)
79
+ else:
80
+ # Si la entrada es una ruta de archivo, carga la imagen y conviértela en un array de numpy
81
+ image = cv2.imread(input)
82
+
83
+ return cv2.resize(image, (500, 500))
84
+ else:
85
+ raise ValueError("La entrada no es un array de numpy, una URL ni una ruta de archivo.")
86
+
87
+ def segment_image_from_numpy(image_array, api_token, model):
88
+
89
+ #API_URL = "https://api-inference.huggingface.co/models/facebook/mask2former-swin-tiny-coco-panoptic"
90
+ API_URL = f"https://api-inference.huggingface.co/models/{model}"
91
+ headers = {"Authorization": f"Bearer {api_token}"}
92
+ ic(API_URL)
93
+ ic(headers)
94
+ # Convert the image to bytes
95
+ is_success, im_buf_arr = cv2.imencode(".jpg", image_array)
96
+ data = im_buf_arr.tobytes()
97
+ response = requests.post(API_URL, headers=headers, data=data)
98
+ pprint(response.json())
99
+ return response.json()
100
+
101
 
102
  def segment_image_from_path(image_path):
103
  with open(image_path, "rb") as f:
 
119
  mask_image = mask_image.resize(size).convert("L")
120
  return mask_image
121
 
122
+
123
  def overlay_masks_on_image(image, segments, transparency=0.4):
124
+ if isinstance(image, np.ndarray):
125
+ image = Image.fromarray(image)
126
+
127
+ original_image = image
128
+ if original_image.mode != 'RGBA':
129
+ original_image = original_image.convert('RGBA')
130
+
131
+ overlay = Image.new("RGBA", original_image.size, (255, 255, 255, 0))
132
+ text_layer = Image.new("RGBA", original_image.size, (255, 255, 255, 0))
133
+
134
+ for segment in segments:
135
+ mask_str = segment['mask']
136
+ mask_image = decode_mask(mask_str, original_image.size)
137
+ color = generate_random_color()
138
+
139
+ color_mask = ImageOps.colorize(mask_image, black="black", white=color)
140
+ color_mask.putalpha(mask_image)
141
+
142
+ overlay = Image.alpha_composite(overlay, color_mask)
143
+
144
+ # Calcula el centroide de la mascara
145
+ x, y = np.where(np.array(mask_image) > 0)
146
+ centroid_x = x.mean()
147
+ centroid_y = y.mean()
148
+
149
+ # Imprime la etiqueta y la puntuación en la capa de texto
150
+ font_size = 30
151
+ draw = ImageDraw.Draw(text_layer)
152
+ font = ImageFont.load_default().font_variant(size=font_size)
153
+ label = segment['label']
154
+ score = segment['score']
155
+ text =f"{label}: {score}"
156
+
157
+ # Calcula el tamaño del texto
158
+ text_bbox = draw.textbbox((0, 0), text, font=font)
159
+ text_width = text_bbox[2] - text_bbox[0]
160
+ text_height = text_bbox[3] - text_bbox[1]
161
+
162
+ # Asegúrate de que las coordenadas del texto están dentro de los límites de la imagen
163
+ text_x = max(0, min(centroid_x - text_width / 2, original_image.size[0] - text_width))
164
+ text_y = max(0, min(centroid_y - text_height / 2, original_image.size[1] - text_height))
165
+
166
+ draw.text((text_x, text_y), text, fill=(255, 255, 255, 255), font=font)
167
+
168
+ # Ajusta la transparencia de la capa de superposición
169
+ overlay = Image.blend(original_image, overlay, transparency)
170
+
171
+ # Combina la capa de superposición con la capa de texto
172
+ final_image = Image.alpha_composite(overlay, text_layer)
173
+
174
+ return final_image
175
+
176
+
177
+
178
+
179
+
180
+
181
+
182
+
183
+ def overlay_masks_on_image2(image, segments, transparency=0.4):
184
  # Convert numpy array to PIL Image
185
+ #original_image = Image.fromarray(image).convert("RGBA")
186
+ #original_image = image
187
  #original_image = Image.open(image).convert("RGBA")
188
+ # para file es str
189
+ # para url es numpy.ndarray
190
+ # para cv.imread es numpy.ndarray
191
+
192
+ # Convertir el array de numpy a una imagen PIL si es necesario
193
+ if isinstance(image, np.ndarray):
194
+ image = Image.fromarray(image)
195
+
196
+ print(type(image))
197
+ print(image)
198
+ original_image = image
199
+
200
+ if original_image.mode != 'RGBA':
201
+ original_image = original_image.convert('RGBA')
202
 
203
+ print(original_image.size)
204
+ overlay = Image.new("RGBA", original_image.size, (255, 255, 255, 0))
205
+ print(overlay.size)
206
  # Nueva capa para el texto
207
 
208
  text_layer = Image.new("RGBA", original_image.size, (255, 255, 255, 0))
 
213
  print(segment['label'] + " " + str(segment['score']))
214
  mask_str = segment['mask']
215
  mask_image = decode_mask(mask_str, original_image.size)
216
+
217
+
218
+
219
+ # Convierte la imagen de la máscara a un array de numpy
220
+ mask_array = np.array(mask_image)
221
+
222
+ # Encuentra los píxeles blancos
223
+ y, x = np.where(mask_array > 0)
224
+
225
+ # Calcula el cuadro delimitador de los píxeles blancos
226
+ x_min, y_min, width, height = cv2.boundingRect(np.array(list(zip(x, y))))
227
+
228
+
229
+ # Crea un objeto ImageDraw para dibujar en la imagen original
230
+ draw = ImageDraw.Draw(original_image)
231
+
232
+
233
+ # Dibuja el cuadro delimitador en la imagen original
234
+ draw.rectangle([(x_min, y_min), (x_min + width, y_min + height)], outline=(0, 255, 0), width=2)
235
+
236
+
237
  color = generate_random_color()
238
 
239
  color_mask = ImageOps.colorize(mask_image, black="black", white=color)
 
241
 
242
  overlay = Image.alpha_composite(overlay, color_mask)
243
 
244
+
245
  # Calcula el centroide de la mascara
246
 
247
  x, y = np.where(np.array(mask_image) > 0)
 
262
 
263
  text_width = 500
264
  text_height = 100
 
265
 
266
+
267
+ # Asegúrate de que las coordenadas del texto están dentro de los límites de la imagen
268
+ text_x = max(0, min(centroid_x - text_width / 2, original_image.size[0] - text_width))
269
+ text_y = max(0, min(centroid_y - text_height / 2, original_image.size[1] - text_height))
270
+ # Asegúrate de que las coordenadas del texto están dentro de los límites de la imagen
271
+ text_x = max(0, min(centroid_x, original_image.size[0] - text_width))
272
+ text_y = max(0, min(centroid_y, original_image.size[1] - text_height))
273
+
274
+
275
+ # Calcula las coordenadas del texto
276
+ text_x = centroid_x - text_width / 2
277
+ text_y = centroid_y - text_height / 2
278
+
279
+
280
+ # Asegúrate de que las coordenadas del texto están dentro de los límites de la imagen
281
+ text_x = max(0, min(text_x, original_image.size[0] - text_width))
282
+ text_y = max(0, min(text_y, original_image.size[1] - text_height))
283
+
284
+
285
+ draw.text((centroid_x - text_width / 2, centroid_y - text_height / 2), text, fill=(255, 255, 255, 255), font=font)
286
+
287
+ #draw.text((text_x, text_y), text, fill=(255, 255, 255, 255), font=font)
288
 
289
  # Ajusta la transparencia de la capa de superposición
290
+ print(original_image.size)
291
+ print(overlay.size)
292
  overlay = Image.blend(original_image, overlay, transparency)
293
 
294
  # Combina la capa de superposición con la capa de texto
 
303
  return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
304
 
305
 
306
+ def segment_and_overlay_results(image_path, api_token, model):
307
  #segments = segment_image_from_image(image)
308
  #final_image = overlay_masks_on_image(image, segments)
309
  #return final_image
310
  processed_image = None # Initialize processed_image
311
  segments = []
312
+ #image_type = None
313
+ #if isinstance(image_path, str):
314
+ # image_type = 'FILE'
315
+ # image = cv2.imread('cats.jpg')
316
+ #elif isinstance(image_path, np.ndarray):
317
+ # image_type = 'NUMPY ARRAY'
318
+ #else:
319
+ # raise ValueError("The image is neither a Image nor a local file.")
320
+
321
+ #ic(image_type)
322
+ image = transform_image_to_numpy_array(image_path)
323
+ # imprime tres primeros pixeles
324
+ print(type(image))
325
+ ic(image[0, 0:3])
326
+
327
+
328
+
329
+
330
  try:
331
  #segments = segment_image_from_image(image)
332
  #processed_image = overlay_masks_on_image(image, segments)
333
 
334
  # debug image contents
335
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  #if os.path.isfile(image):
337
  # ic ("--- image is a file ---")
338
  # image = Image.open(image)
339
  # if image is None:
340
  # ic("image is None")
341
  # return None, []
342
+
343
+ ic("--- calling segment_image_from_path ---")
344
+ segments = segment_image_from_numpy(image, api_token, model)
345
+ #if image_type == 'FILE':
346
+ # segments = segment_image_from_path(image_path)
347
+ #if image_type == 'NUMPY ARRAY':
348
+ # segments = segment_image_from_image(image_path)
349
+
350
+ ic("--- printing segments ---")
351
+ for segment in segments:
352
+ ic(segment['label'] ,segment['score'])
353
  processed_image = print_text_on_image_centered(
354
  create_background_image(500, 500, "white"),
355
  'SEGMENTING OK',
356
  'green'
357
  )
358
+ ic("--- calling overlay_masks_on_image ---")
359
  processed_image = overlay_masks_on_image(image, segments)
360
+ return processed_image, segments
361
  except Exception as e:
362
+ print("EXCEPTION")
363
  ic(e)
364
+ print(traceback.format_exc())
365
  processed_image = print_text_on_image_centered(
366
  create_background_image(500, 500, "white"),
367
  e,
368
  'green'
369
  )
370
  segments = []
371
+ return processed_image, segments
372
+ #finally:
373
+ #return processed_image, segments