Leyogho commited on
Commit
f6ae060
·
1 Parent(s): de9f0d6

Change methode request gpu

Browse files
Files changed (3) hide show
  1. app.py +95 -109
  2. translator.py +38 -0
  3. utilities/distributed.py +0 -1
app.py CHANGED
@@ -20,16 +20,24 @@ subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'SimpleITK'])
20
  # Imports Hugging Face
21
  from huggingface_hub import hf_hub_download, login
22
  import spaces
 
 
 
 
 
 
23
 
24
  # Imports locaux
25
  from modeling.BaseModel import BaseModel
26
  from modeling import build_model
27
- from utilities.distributed import init_distributed
28
  from utilities.arguments import load_opt_from_config_files
29
  from utilities.constants import BIOMED_CLASSES
30
- from inference_utils.inference import interactive_infer_image
31
  from inference_utils.output_processing import check_mask_stats
32
- from inference_utils.processing_utils import read_rgb, get_instances
 
 
 
33
 
34
  def init_huggingface():
35
  """Initialize Hugging Face connection and download the model."""
@@ -45,151 +53,124 @@ def init_huggingface():
45
  )
46
  return pretrained_path
47
 
48
- def apply_distributed(opt):
49
- """Applique les paramètres distribués pour le mode multi-processus."""
50
- print(f"Configuration distribuée appliquée : {opt}")
51
-
52
  def init_distributed(opt):
53
- """Initialize distributed mode without premature CUDA initialization."""
54
  opt['CUDA'] = opt.get('CUDA', True) and torch.cuda.is_available()
55
  if 'OMPI_COMM_WORLD_SIZE' not in os.environ:
56
- # Application started without MPI
 
57
  opt['env_info'] = 'no MPI'
58
  opt['world_size'] = 1
59
  opt['local_size'] = 1
60
  opt['rank'] = 0
61
- opt['local_rank'] = 0 # Ensure this is set to 0
62
  opt['master_address'] = '127.0.0.1'
63
  opt['master_port'] = '8673'
64
  else:
65
- # Application started with MPI
 
66
  opt['world_size'] = int(os.environ['OMPI_COMM_WORLD_SIZE'])
67
  opt['local_size'] = int(os.environ['OMPI_COMM_WORLD_LOCAL_SIZE'])
68
  opt['rank'] = int(os.environ['OMPI_COMM_WORLD_RANK'])
69
  opt['local_rank'] = int(os.environ['OMPI_COMM_WORLD_LOCAL_RANK'])
70
 
 
71
  if not opt['CUDA']:
72
- assert opt['world_size'] == 1, 'Multi-GPU training without CUDA is not supported since we use NCCL as communication backend'
73
  opt['device'] = torch.device("cpu")
74
  else:
75
- opt['device'] = torch.device("cuda", opt['local_rank']) # Ensure local_rank is integer
 
76
 
77
- apply_distributed(opt)
78
  return opt
79
 
80
  def setup_model():
81
  """Initialize the model on CPU without CUDA initialization."""
82
  opt = load_opt_from_config_files(["configs/biomedparse_inference.yaml"])
83
  opt = init_distributed(opt)
84
- opt['device'] = 'cpu'
85
-
86
  pretrained_path = init_huggingface()
87
- model = BaseModel(opt, build_model(opt))
88
- state_dict = torch.load(pretrained_path, map_location='cpu', weights_only=True)
89
- model.load_state_dict(state_dict, strict=False)
90
-
91
- # Initialize train_class_names
92
- model.train_class_names = BIOMED_CLASSES + ["background"]
93
-
94
- return model.eval()
95
-
96
- import numpy as np
97
- from PIL import Image
98
 
99
- def preprocess_image(image):
100
- """Preprocess image for SEEM model input."""
101
- if isinstance(image, Image.Image):
102
- # Convert PIL Image to numpy array
103
- image = np.array(image)
104
-
105
- # Ensure image is float32 and normalized
106
- image = image.astype(np.float32) / 255.0
 
 
 
 
 
 
 
 
 
 
 
107
 
108
- # Ensure correct dimensions (B, C, H, W)
109
- if len(image.shape) == 3:
110
- image = np.transpose(image, (2, 0, 1)) # HWC -> CHW
111
- image = np.expand_dims(image, axis=0) # Add batch dimension
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
- return image
 
 
114
 
115
- @spaces.GPU
116
- def predict_image(model, image, prompts):
117
- """Process image prediction with proper formatting."""
118
- try:
119
- # Convert PIL Image to numpy array if needed
120
- if isinstance(image, Image.Image):
121
- image = np.array(image)
122
-
123
- # Ensure image is in float32 and normalized
124
- image = image.astype(np.float32) / 255.0
125
-
126
- # Transpose from HWC to CHW format
127
- if len(image.shape) == 3:
128
- image = np.transpose(image, (2, 0, 1))
129
-
130
- # Add batch dimension if needed
131
- if len(image.shape) == 3:
132
- image = np.expand_dims(image, axis=0)
133
-
134
- # Convert to tensor
135
- image_tensor = torch.from_numpy(image)
136
-
137
- # Move to GPU if available
138
- if torch.cuda.is_available():
139
- device = torch.device("cuda", 0)
140
- model = model.to(device)
141
- image_tensor = image_tensor.to(device)
142
- else:
143
- device = torch.device("cpu")
144
-
145
- # Create batched input
146
- batched_inputs = [{
147
- "image": image_tensor,
148
- "prompt": prompts,
149
- "height": image_tensor.shape[-2],
150
- "width": image_tensor.shape[-1]
151
- }]
152
-
153
- with torch.no_grad():
154
- pred_masks = model(batched_inputs)
155
-
156
- # Move back to CPU if needed
157
- if device.type == "cuda":
158
- model = model.to("cpu")
159
- pred_masks = [mask.cpu() for mask in pred_masks]
160
-
161
- return pred_masks
162
-
163
- except Exception as e:
164
- print(f"Error processing image: {str(e)}")
165
- raise
166
 
167
- def process_image(image, text, model):
168
  """Process image with proper error handling."""
169
  try:
170
- prompts = [p.strip() for p in text.split(',') if p.strip()]
 
 
 
 
 
 
171
  if not prompts:
172
  raise ValueError("No valid prompts provided")
173
 
174
  pred_masks = predict_image(model, image, prompts)
175
-
176
- # Create visualization
177
- fig = plt.figure(figsize=(5 * (len(pred_masks) + 1), 5))
178
-
179
- # Show original image
180
  plt.subplot(1, len(pred_masks) + 1, 1)
181
- plt.imshow(preprocess_image(image))
182
- plt.title("Original")
183
  plt.axis('off')
184
-
185
- # Show predictions
186
  for i, mask in enumerate(pred_masks):
187
- plt.subplot(1, len(pred_masks) + 1, i+2)
188
- plt.imshow(preprocess_image(image))
189
- plt.imshow(mask.cpu().numpy(), alpha=0.5, cmap='Reds')
190
  plt.title(prompts[i])
191
  plt.axis('off')
192
-
193
  return fig
194
 
195
  except Exception as e:
@@ -199,6 +180,7 @@ def process_image(image, text, model):
199
  def setup_gradio_interface(model):
200
  """Configure l'interface Gradio."""
201
  return gr.Interface(
 
202
  fn=lambda img, txt: process_image(img, txt, model),
203
  inputs=[
204
  gr.Image(type="numpy", label="Image médicale"),
@@ -209,8 +191,12 @@ def setup_gradio_interface(model):
209
  )
210
  ],
211
  outputs=gr.Plot(),
212
- title="Core IA - Traitement d'image medicale",
213
- description="Chargez une image médicale et spécifiez les éléments à segmenter",
 
 
 
 
214
  examples=[
215
  ["examples/144DME_as_F.jpeg", "Dans cette image donne moi l'œdème"],
216
  ["examples/T0011.jpg", "disque optique, cupule optique"],
@@ -224,7 +210,7 @@ def main():
224
  """Entry point avoiding CUDA initialization in main process."""
225
  try:
226
  init_huggingface()
227
- model = setup_model() # Load on CPU
228
  interface = setup_gradio_interface(model)
229
  interface.launch(debug=True)
230
  except Exception as e:
 
20
  # Imports Hugging Face
21
  from huggingface_hub import hf_hub_download, login
22
  import spaces
23
+ import numpy as np
24
+ from PIL import Image
25
+ import torch
26
+ import torch.nn.functional as F
27
+ from torchvision import transforms
28
+ from translator import translate_text
29
 
30
  # Imports locaux
31
  from modeling.BaseModel import BaseModel
32
  from modeling import build_model
 
33
  from utilities.arguments import load_opt_from_config_files
34
  from utilities.constants import BIOMED_CLASSES
35
+ from modeling.language.loss import vl_similarity
36
  from inference_utils.output_processing import check_mask_stats
37
+
38
+ t = []
39
+ t.append(transforms.Resize((1024, 1024), interpolation=Image.BICUBIC))
40
+ transform = transforms.Compose(t)
41
 
42
  def init_huggingface():
43
  """Initialize Hugging Face connection and download the model."""
 
53
  )
54
  return pretrained_path
55
 
56
+ @torch.no_grad()
57
+ @spaces.GPU
 
 
58
  def init_distributed(opt):
 
59
  opt['CUDA'] = opt.get('CUDA', True) and torch.cuda.is_available()
60
  if 'OMPI_COMM_WORLD_SIZE' not in os.environ:
61
+ # application was started without MPI
62
+ # default to single node with single process
63
  opt['env_info'] = 'no MPI'
64
  opt['world_size'] = 1
65
  opt['local_size'] = 1
66
  opt['rank'] = 0
67
+ opt['local_rank'] = 0
68
  opt['master_address'] = '127.0.0.1'
69
  opt['master_port'] = '8673'
70
  else:
71
+ # application was started with MPI
72
+ # get MPI parameters
73
  opt['world_size'] = int(os.environ['OMPI_COMM_WORLD_SIZE'])
74
  opt['local_size'] = int(os.environ['OMPI_COMM_WORLD_LOCAL_SIZE'])
75
  opt['rank'] = int(os.environ['OMPI_COMM_WORLD_RANK'])
76
  opt['local_rank'] = int(os.environ['OMPI_COMM_WORLD_LOCAL_RANK'])
77
 
78
+ # set up device
79
  if not opt['CUDA']:
80
+ assert opt['world_size'] == 1, 'multi-GPU training without CUDA is not supported since we use NCCL as communication backend'
81
  opt['device'] = torch.device("cpu")
82
  else:
83
+ torch.cuda.set_device(opt['local_rank'])
84
+ opt['device'] = torch.device("cuda", opt['local_rank'])
85
 
 
86
  return opt
87
 
88
  def setup_model():
89
  """Initialize the model on CPU without CUDA initialization."""
90
  opt = load_opt_from_config_files(["configs/biomedparse_inference.yaml"])
91
  opt = init_distributed(opt)
 
 
92
  pretrained_path = init_huggingface()
93
+ model = BaseModel(opt, build_model(opt)).from_pretrained(pretrained_path).eval()
94
+ return model
 
 
 
 
 
 
 
 
 
95
 
96
+ @torch.no_grad()
97
+ @spaces.GPU
98
+ def predict_image(model, image, prompts):
99
+ model = model.cuda()
100
+ print("====================== Model moved to GPU via predict_image ======================")
101
+ prompts = [translate_text(p, "fr", "en") for p in prompts]
102
+ # Initialiser les embeddings textuels avant l'évaluation
103
+ lang_encoder = model.model.sem_seg_head.predictor.lang_encoder
104
+ lang_encoder.get_text_embeddings(BIOMED_CLASSES + ["background"], is_eval=True)
105
+ model.model.sem_seg_head.predictor.lang_encoder.get_text_embeddings(BIOMED_CLASSES + ["background"], is_eval=True)
106
+ # Préparer l'image
107
+ image_resize = transform(image)
108
+ width = image.size[0]
109
+ height = image.size[1]
110
+ image_resize = np.asarray(image_resize)
111
+ image = torch.from_numpy(image_resize.copy()).permute(2,0,1).cuda()
112
+
113
+ # Préparer les données d'entrée
114
+ data = {"image": image, 'text': prompts, "height": height, "width": width}
115
 
116
+ # Configurer les tâches
117
+ model.model.task_switch['spatial'] = False
118
+ model.model.task_switch['visual'] = False
119
+ model.model.task_switch['grounding'] = True
120
+ model.model.task_switch['audio'] = False
121
+
122
+ # Évaluation
123
+ batch_inputs = [data]
124
+ results, image_size, extra = model.model.evaluate_demo(batch_inputs)
125
+
126
+ # Traitement des prédictions
127
+ pred_masks = results['pred_masks'][0]
128
+ v_emb = results['pred_captions'][0]
129
+ t_emb = extra['grounding_class']
130
+
131
+ # Normalisation
132
+ t_emb = t_emb / (t_emb.norm(dim=-1, keepdim=True) + 1e-7)
133
+ v_emb = v_emb / (v_emb.norm(dim=-1, keepdim=True) + 1e-7)
134
+
135
+ # Calcul de similarité
136
+ temperature = lang_encoder.logit_scale
137
+ out_prob = vl_similarity(v_emb, t_emb, temperature=temperature)
138
 
139
+ # Sélection des masques
140
+ matched_id = out_prob.max(0)[1]
141
+ pred_masks_pos = pred_masks[matched_id,:,:]
142
 
143
+ # Redimensionnement à la taille d'origine
144
+ pred_mask_prob = F.interpolate(pred_masks_pos[None,], (data['height'], data['width']),
145
+ mode='bilinear')[0,:,:data['height'],:data['width']].sigmoid().cpu().detach().numpy()
146
+ return pred_mask_prob
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
+ def process_image(image, prompts, model):
149
  """Process image with proper error handling."""
150
  try:
151
+ if isinstance(image, str):
152
+ image = Image.open(image)
153
+ else:
154
+ image = Image.fromarray(image)
155
+
156
+ prompts = [p.strip() for p in prompts.split(',')]
157
+
158
  if not prompts:
159
  raise ValueError("No valid prompts provided")
160
 
161
  pred_masks = predict_image(model, image, prompts)
162
+ fig = plt.figure(figsize=(10, 5))
 
 
 
 
163
  plt.subplot(1, len(pred_masks) + 1, 1)
164
+ plt.imshow(image)
165
+ plt.title('Image originale')
166
  plt.axis('off')
167
+
 
168
  for i, mask in enumerate(pred_masks):
169
+ plt.subplot(1, len(pred_masks) + 1, i + 2)
170
+ plt.imshow(image)
171
+ plt.imshow(mask, alpha=0.5, cmap='Reds')
172
  plt.title(prompts[i])
173
  plt.axis('off')
 
174
  return fig
175
 
176
  except Exception as e:
 
180
  def setup_gradio_interface(model):
181
  """Configure l'interface Gradio."""
182
  return gr.Interface(
183
+ theme=gr.Theme.from_hub("JohnSmith9982/small_and_pretty"),
184
  fn=lambda img, txt: process_image(img, txt, model),
185
  inputs=[
186
  gr.Image(type="numpy", label="Image médicale"),
 
191
  )
192
  ],
193
  outputs=gr.Plot(),
194
+ title=" 🇬🇦 Core IA - Traitement d'image medicale",
195
+ description="""Chargez une image médicale de type (IRM , Echographie, ) et spécifiez les éléments à segmenter : Les cas d’utilisation incluent des tâches variées d’analyse d’images médicales. En imagerie CT, le modèle peut détecter et segmenter des organes et pathologies dans des régions telles que l’abdomen, le côlon, le foie, les poumons ou le bassin. Avec l’IRM, il est capable de traiter des structures abdominales, cérébrales, cardiaques et prostatiques selon les différentes séquences (FLAIR, T1-Gd, T2). En radiographie, il peut identifier des anomalies pulmonaires ou des infections liées à la COVID-19.
196
+
197
+ Le modèle couvre également d’autres modalités comme la dermoscopie, l’endoscopie, le fond d’œil, et la pathologie, avec des applications pour la détection de lésions, de polypes ou de cellules néoplasiques dans divers tissus et organes. En échographie, il identifie des anomalies mammaires, cardiaques ou fœtales. Enfin, en TOCT, il peut analyser des structures rétiniennes.
198
+
199
+ Bien que performant dans ces contextes, il est important de considérer les spécificités des ensembles de données externes et de procéder à un ajustement pour des résultats précis.""",
200
  examples=[
201
  ["examples/144DME_as_F.jpeg", "Dans cette image donne moi l'œdème"],
202
  ["examples/T0011.jpg", "disque optique, cupule optique"],
 
210
  """Entry point avoiding CUDA initialization in main process."""
211
  try:
212
  init_huggingface()
213
+ model = setup_model()
214
  interface = setup_gradio_interface(model)
215
  interface.launch(debug=True)
216
  except Exception as e:
translator.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+
4
+ def translate_text(text, source_lang, target_lang):
5
+ url = "https://google-translator9.p.rapidapi.com/v2"
6
+ payload = {
7
+ "q": text,
8
+ "source": source_lang,
9
+ "target": target_lang,
10
+ "format": "text"
11
+ }
12
+ headers = {
13
+ "x-rapidapi-key": os.getenv("RAPIDAPI_KEY"),
14
+ "x-rapidapi-host": "google-translator9.p.rapidapi.com",
15
+ "Content-Type": "application/json"
16
+ }
17
+
18
+ try:
19
+ response = requests.post(url, json=payload, headers=headers)
20
+ response.raise_for_status()
21
+ print('=====================', response.json())
22
+ translations = response.json().get('data', {}).get('translations', [])
23
+ if translations:
24
+ translated_text = translations[0].get('translatedText', '')
25
+ return translated_text
26
+ else:
27
+ return text
28
+ except requests.exceptions.RequestException as e:
29
+ print(f"An error occurred: {e}")
30
+ return text
31
+
32
+ if __name__ == "__main__":
33
+ text_to_translate = "Dans cette image donne moi l'œdème"
34
+ source_language = "fr"
35
+ target_language = "en"
36
+ translation = translate_text(text_to_translate, source_language, target_language)
37
+ if translation:
38
+ print(translation)
utilities/distributed.py CHANGED
@@ -30,7 +30,6 @@ def apply_distributed(opt):
30
  init_method=init_method_url,
31
  world_size=world_size,
32
  rank=rank)
33
-
34
  def init_distributed(opt):
35
  opt['CUDA'] = opt.get('CUDA', True) and torch.cuda.is_available()
36
  if 'OMPI_COMM_WORLD_SIZE' not in os.environ:
 
30
  init_method=init_method_url,
31
  world_size=world_size,
32
  rank=rank)
 
33
  def init_distributed(opt):
34
  opt['CUDA'] = opt.get('CUDA', True) and torch.cuda.is_available()
35
  if 'OMPI_COMM_WORLD_SIZE' not in os.environ: