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

Update requirements.txt

Browse files
Files changed (2) hide show
  1. app.py +167 -55
  2. requirements.txt +3 -2
app.py CHANGED
@@ -8,8 +8,18 @@ import os
8
  import subprocess
9
  import sys
10
 
 
 
 
 
 
 
 
 
 
11
  # Imports Hugging Face
12
  from huggingface_hub import hf_hub_download, login
 
13
 
14
  # Imports locaux
15
  from modeling.BaseModel import BaseModel
@@ -21,75 +31,174 @@ from inference_utils.inference import interactive_infer_image
21
  from inference_utils.output_processing import check_mask_stats
22
  from inference_utils.processing_utils import read_rgb, get_instances
23
 
24
-
25
  def init_huggingface():
26
- """Initialise la connexion Hugging Face et télécharge le modèle."""
27
  hf_token = os.getenv('HF_TOKEN')
28
  if hf_token is None:
29
  raise ValueError("Hugging Face token not found. Please set the HF_TOKEN environment variable.")
30
  login(hf_token)
31
- packages = [
32
- 'openmpi-bin',
33
- 'libopenmpi-dev'
34
- ]
35
- command = ['sudo', 'apt-get', 'install', '-y'] + packages
36
- subprocess.run(
37
- command,
38
- check=True,
39
- stdout=subprocess.PIPE,
40
- stderr=subprocess.PIPE,
41
- text=True
42
- )
43
- subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'mpi4py'])
44
- return hf_hub_download(
45
  repo_id="microsoft/BiomedParse",
46
  filename="biomedparse_v1.pt",
47
  local_dir="pretrained"
48
  )
 
49
 
50
- def setup_model():
51
- """Configure et retourne le modèle."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  opt = init_distributed(opt)
54
- model = BaseModel(opt, build_model(opt)).from_pretrained('hf_hub:microsoft/BiomedParse').eval().cuda()
55
 
56
- with torch.no_grad():
57
- model.model.sem_seg_head.predictor.lang_encoder.get_text_embeddings(
58
- BIOMED_CLASSES + ["background"],
59
- is_eval=True
60
- )
61
- return model
62
-
63
- def process_image(image, prompts, model):
64
- """Traite l'image avec les prompts donnés."""
65
- if isinstance(image, str):
66
- image = Image.open(image)
67
- else:
68
- image = Image.fromarray(image)
69
 
70
- prompts = [p.strip() for p in prompts.split(',')]
 
71
 
72
- pred_masks = interactive_infer_image(model, image, prompts)
 
 
 
 
 
 
 
 
 
73
 
74
- fig = plt.figure(figsize=(10, 5))
75
- plt.subplot(1, len(pred_masks) + 1, 1)
76
- plt.imshow(image)
77
- plt.title('Image originale')
78
- plt.axis('off')
79
-
80
- for i, mask in enumerate(pred_masks):
81
- plt.subplot(1, len(pred_masks) + 1, i+2)
82
- plt.imshow(image)
83
- plt.imshow(mask, alpha=0.5, cmap='Reds')
84
- plt.title(prompts[i])
85
- plt.axis('off')
86
 
87
- return fig
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
  def setup_gradio_interface(model):
90
  """Configure l'interface Gradio."""
91
  return gr.Interface(
92
- theme=gr.Theme.from_hub("allenai/gradio-theme"),
93
  fn=lambda img, txt: process_image(img, txt, model),
94
  inputs=[
95
  gr.Image(type="numpy", label="Image médicale"),
@@ -104,7 +213,6 @@ def setup_gradio_interface(model):
104
  description="Chargez une image médicale et spécifiez les éléments à segmenter",
105
  examples=[
106
  ["examples/144DME_as_F.jpeg", "Dans cette image donne moi l'œdème"],
107
- ["examples/ISIC_0015551.jpg", "Cherche une lésion"],
108
  ["examples/T0011.jpg", "disque optique, cupule optique"],
109
  ["examples/C3_EndoCV2021_00462.jpg", "Trouve moi le polyp"],
110
  ["examples/covid_1585.png", "Qu'est ce qui ne va pas ici ?"],
@@ -113,11 +221,15 @@ def setup_gradio_interface(model):
113
  )
114
 
115
  def main():
116
- """Point d'entrée principal de l'application."""
117
- init_huggingface()
118
- model = setup_model()
119
- interface = setup_gradio_interface(model)
120
- interface.launch(debug=True)
 
 
 
 
121
 
122
  if __name__ == "__main__":
123
- main()
 
8
  import subprocess
9
  import sys
10
 
11
+ # Installation des dépendances nécessaires
12
+ subprocess.run(['apt-get', 'update'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
13
+ packages = ['openmpi-bin', 'libopenmpi-dev']
14
+ command = ['apt-get', 'install', '-y'] + packages
15
+ subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
16
+ subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'mpi4py'])
17
+ subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'pydicom'])
18
+ subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'SimpleITK'])
19
+
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
 
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."""
36
  hf_token = os.getenv('HF_TOKEN')
37
  if hf_token is None:
38
  raise ValueError("Hugging Face token not found. Please set the HF_TOKEN environment variable.")
39
  login(hf_token)
40
+
41
+ pretrained_path = hf_hub_download(
 
 
 
 
 
 
 
 
 
 
 
 
42
  repo_id="microsoft/BiomedParse",
43
  filename="biomedparse_v1.pt",
44
  local_dir="pretrained"
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:
196
+ print(f"Error in process_image: {str(e)}")
197
+ raise
198
 
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"),
 
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"],
217
  ["examples/C3_EndoCV2021_00462.jpg", "Trouve moi le polyp"],
218
  ["examples/covid_1585.png", "Qu'est ce qui ne va pas ici ?"],
 
221
  )
222
 
223
  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:
231
+ print(f"Error during initialization: {str(e)}")
232
+ raise
233
 
234
  if __name__ == "__main__":
235
+ main()
requirements.txt CHANGED
@@ -14,7 +14,7 @@ sentencepiece==0.1.99
14
  ftfy==6.1.1
15
  regex==2023.10.3
16
  nltk==3.8.1
17
- mpi4py==3.1.5
18
  vision-datasets==0.2.2
19
  cython==3.0.2
20
  pycocotools==2.0.7
@@ -30,7 +30,8 @@ deepspeed==0.10.3
30
  #wandb==0.15.12
31
  infinibatch==0.1.1
32
  open-clip-torch==2.26.1
33
- git+https://github.com/MaureenZOU/detectron2-xyz.git
 
34
  gradio
35
  #torch==2.3.1 #2.0.1
36
  #torchvision==0.15.2
 
14
  ftfy==6.1.1
15
  regex==2023.10.3
16
  nltk==3.8.1
17
+ #mpi4py
18
  vision-datasets==0.2.2
19
  cython==3.0.2
20
  pycocotools==2.0.7
 
30
  #wandb==0.15.12
31
  infinibatch==0.1.1
32
  open-clip-torch==2.26.1
33
+ nibabel==5.1.0
34
+ git+https://github.com/facebookresearch/detectron2
35
  gradio
36
  #torch==2.3.1 #2.0.1
37
  #torchvision==0.15.2