@@ -372,7 +372,7 @@ def _process_with_onnx(self, **config):
372372
373373 try :
374374 # Просто передаем numpy массив
375- detections = self .model_manager .predict (
375+ results = self .model_manager .predict (
376376 model_name = config ["model_change" ],
377377 image_np = config ["image" ], # numpy массив
378378 confidence_threshold = config ["confidence_threshold" ],
@@ -383,10 +383,10 @@ def _process_with_onnx(self, **config):
383383 self ._handle_error (e )
384384 return None , None , None
385385
386- if len (detections ) == 0 :
386+ if len (results ) == 0 :
387387 gr .Info (self ._get_translation ("Объекты не обнаружены." ))
388388 return None , None , None
389- elif len (detections ) == config ["number_detections" ]:
389+ elif len (results ) == config ["number_detections" ]:
390390 gr .Info (
391391 self ._get_translation (
392392 "Достигнут предел количества обнаружений. Увеличьте максимальное количество обнаружений в настройках."
@@ -405,8 +405,8 @@ def _process_with_onnx(self, **config):
405405 particle_counter , particle_data , annotations = 1 , [], []
406406
407407 # Обработка детекций
408- for i in range (len (detections .xyxy )):
409- mask = detections .mask [i ] if detections .mask is not None else None
408+ for i in range (len (results .xyxy )):
409+ mask = results .mask [i ] if results .mask is not None else None
410410
411411 if mask is not None :
412412 contours , _ = cv2 .findContours (
@@ -445,6 +445,7 @@ def _process_with_yolo(self, **config):
445445 with torch .no_grad ():
446446 results = model (
447447 config ["image" ],
448+ imgsz = 640 ,
448449 verbose = False ,
449450 conf = config ["confidence_threshold" ],
450451 retina_masks = True ,
@@ -900,37 +901,96 @@ def _cleanup(self, pbar: Optional[tqdm] = None):
900901 """Очистка ресурсов"""
901902 if pbar :
902903 pbar .close ()
904+
903905 gc .collect ()
906+
904907 if torch .cuda .is_available ():
908+ # Синхронизация перед очисткой
909+ torch .cuda .synchronize ()
910+ # Очистка кэша CUDA
905911 torch .cuda .empty_cache ()
912+ # Сброс статистики памяти
913+ torch .cuda .reset_peak_memory_stats ()
906914
907- def _img_to_numpy_array (self , file_path , max_size_kb = 500 , quality = 85 ):
915+ def _img_to_numpy_array (self , file_path : str , max_size_kb : int = 500 , quality : int = 85 ) -> Optional [np .ndarray ]:
916+ """
917+ Конвертирует изображение в numpy array с обработкой различных форматов и оптимизацией размера.
918+
919+ Args:
920+ file_path: Путь к файлу изображения
921+ max_size_kb: Максимальный размер в KB (по умолчанию 500)
922+ quality: Качество JPEG сжатия (по умолчанию 85)
923+
924+ Returns:
925+ np.ndarray или None в случае ошибки
926+ """
908927 try :
909928 with Image .open (file_path ) as img :
910- img_byte_arr = io .BytesIO ()
911-
912- img .save (img_byte_arr , format = "PNG" , optimize = True )
913-
914- current_size_kb = len (img_byte_arr .getvalue ()) / 1024
915-
929+ original_mode = img .mode
930+
931+ # Обработка специальных режимов изображений
932+ if img .mode in ['I' , 'I;16' , 'I;16B' , 'I;16L' , 'F' ]:
933+ img_array = np .array (img )
934+
935+ # Нормализация в 8-бит для специальных форматов
936+ if img_array .dtype in [np .uint16 , np .int16 ]:
937+ img_array = (img_array / 256 ).astype (np .uint8 )
938+ elif img_array .dtype in [np .float32 , np .float64 ]:
939+ img_array = (img_array * 255 ).astype (np .uint8 )
940+ elif img_array .dtype in [np .int32 , np .int64 ]:
941+ img_array = (img_array / (img_array .max () / 255 )).astype (np .uint8 )
942+
943+ img = Image .fromarray (img_array )
944+
945+ elif img .mode == 'CMYK' :
946+ img = img .convert ('RGB' )
947+
948+ elif img .mode in ('RGBA' , 'LA' , 'P' ):
949+ # Обработка прозрачности и палитровых изображений
950+ background = Image .new ('RGB' , img .size , (255 , 255 , 255 ))
951+
952+ if img .mode == 'P' :
953+ img = img .convert ('RGBA' )
954+
955+ if img .mode in ('RGBA' , 'LA' ):
956+ bands = img .split ()
957+ alpha = bands [- 1 ]
958+
959+ # Черный фон для полностью прозрачных изображений
960+ if np .array (alpha ).max () == 0 :
961+ background = Image .new ('RGB' , img .size , (0 , 0 , 0 ))
962+
963+ background .paste (img , mask = img .split ()[- 1 ] if img .mode in ('RGBA' , 'LA' ) else None )
964+ img = background
965+
966+ elif img .mode != 'RGB' :
967+ img = img .convert ('RGB' )
968+
969+ # Проверка и коррекция белых изображений
970+ test_array = np .array (img )
971+ if np .all (test_array >= 250 ):
972+ with Image .open (file_path ) as img_alt :
973+ alt_array = np .array (img_alt )
974+ if alt_array .max () > 0 and alt_array .max () <= 255 :
975+ normalized = (alt_array / alt_array .max () * 255 ).astype (np .uint8 )
976+ img = Image .fromarray (normalized )
977+
978+ # Оптимизация размера файла
979+ with io .BytesIO () as buffer :
980+ img .save (buffer , format = 'JPEG' , quality = quality )
981+ current_size_kb = len (buffer .getvalue ()) / 1024
982+
916983 if current_size_kb > max_size_kb :
917984 ratio = (max_size_kb / current_size_kb ) ** 0.5
918- new_size = (int (img .size [0 ] * ratio ), int (img .size [1 ] * ratio ))
985+ new_size = (max ( 1 , int (img .size [0 ] * ratio )), max ( 1 , int (img .size [1 ] * ratio ) ))
919986 img = img .resize (new_size , Image .Resampling .LANCZOS )
920-
921- img_byte_arr = io .BytesIO ()
922- img .save (img_byte_arr , format = "PNG" , optimize = True )
923-
924- img_byte_arr .seek (0 )
925- compressed_img = Image .open (img_byte_arr )
926-
927- return np .array (compressed_img )
928-
929- except (IOError , OSError , ValueError ) as e :
987+
988+ return np .array (img )
989+
990+ except (IOError , OSError , ValueError , Exception ):
930991 gr .Info (self ._get_translation ("Не поддерживаемый формат изображения." ))
931- print (f"Ошибка при загрузке изображения { file_path } : { e } " )
932992 return None
933-
993+
934994 def handle_file_upload (self , file , scale_selector , request : gr .Request ):
935995 # Быстрая проверка на None файл
936996 if file is None :
0 commit comments