Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -1,63 +1,65 @@
|
|
1 |
import os
|
2 |
-
import shutil
|
3 |
from pathlib import Path
|
4 |
-
|
5 |
-
import gradio as gr
|
6 |
-
import torch
|
7 |
import numpy as np
|
|
|
8 |
from PIL import Image as PILImage
|
9 |
-
|
|
|
|
|
|
|
10 |
from detectron2.config import get_cfg
|
|
|
11 |
from detectron2.engine import DefaultPredictor
|
12 |
from detectron2.data import DatasetCatalog, MetadataCatalog
|
13 |
from detectron2.utils.visualizer import ColorMode, Visualizer
|
14 |
-
from tqdm import tqdm
|
15 |
-
import uuid
|
16 |
-
import cv2
|
17 |
-
import pickle
|
18 |
from math import ceil
|
19 |
-
|
20 |
-
from
|
21 |
|
22 |
-
|
|
|
|
|
23 |
debug_str = f"_debug{int(debug)}"
|
24 |
cache_path = Path(".") / f"dataset_dicts_cache_test{debug_str}.pkl"
|
25 |
if not use_cache or not cache_path.exists():
|
|
|
26 |
if debug:
|
27 |
test_meta = test_meta.iloc[:500] # For debug
|
28 |
|
29 |
-
# Load 1 image to get image size
|
30 |
image_id = test_meta.loc[0, "image_id"]
|
31 |
-
image_path = imgdir
|
32 |
-
image = cv2.imread(
|
33 |
resized_height, resized_width, ch = image.shape
|
34 |
|
35 |
dataset_dicts = []
|
36 |
for index, test_meta_row in tqdm(test_meta.iterrows(), total=len(test_meta)):
|
37 |
record = {}
|
38 |
image_id, height, width = test_meta_row.values
|
39 |
-
filename = imgdir
|
40 |
-
record["file_name"] =
|
41 |
record["image_id"] = image_id
|
42 |
record["height"] = resized_height
|
43 |
record["width"] = resized_width
|
44 |
dataset_dicts.append(record)
|
45 |
-
|
46 |
with open(cache_path, mode="wb") as f:
|
47 |
pickle.dump(dataset_dicts, f)
|
48 |
|
|
|
49 |
with open(cache_path, mode="rb") as f:
|
50 |
dataset_dicts = pickle.load(f)
|
51 |
return dataset_dicts
|
52 |
|
53 |
-
def format_pred(labels: ndarray, boxes: ndarray, scores: ndarray) -> str:
|
54 |
pred_strings = []
|
55 |
for label, score, bbox in zip(labels, scores, boxes):
|
56 |
xmin, ymin, xmax, ymax = bbox.astype(np.int64)
|
57 |
pred_strings.append(f"{label} {score} {xmin} {ymin} {xmax} {ymax}")
|
58 |
return " ".join(pred_strings)
|
59 |
|
60 |
-
def predict_batch(predictor: DefaultPredictor, im_list:
|
61 |
with torch.no_grad():
|
62 |
inputs_list = []
|
63 |
for original_image in im_list:
|
@@ -92,15 +94,18 @@ def csv_create(new_image_path, image_id):
|
|
92 |
test_meta_path = os.path.join(directory, 'test_meta.csv')
|
93 |
test_meta_df.to_csv(test_meta_path, index=False)
|
94 |
|
|
|
95 |
return sample_submission_path, test_meta_path
|
96 |
|
97 |
def prediction(image_id_main, local_image_path, model_path):
|
98 |
thing_classes = [
|
99 |
-
"Aortic enlargement", "Atelectasis", "Calcification", "Cardiomegaly",
|
100 |
-
"ILD", "Infiltration", "Lung Opacity", "Nodule/Mass",
|
101 |
-
"Pleural thickening", "Pneumothorax", "Pulmonary fibrosis"
|
102 |
]
|
|
|
103 |
|
|
|
104 |
outdir = 'result_images'
|
105 |
os.makedirs(outdir, exist_ok=True)
|
106 |
|
@@ -108,7 +113,7 @@ def prediction(image_id_main, local_image_path, model_path):
|
|
108 |
os.makedirs(imgdir, exist_ok=True)
|
109 |
shutil.copy(local_image_path, imgdir)
|
110 |
new_image_path = os.path.join(imgdir, os.path.basename(local_image_path))
|
111 |
-
|
112 |
sample_submission, test_meta = csv_create(new_image_path, image_id_main)
|
113 |
|
114 |
cfg = get_cfg()
|
@@ -116,24 +121,24 @@ def prediction(image_id_main, local_image_path, model_path):
|
|
116 |
cfg.merge_from_file(model_zoo.get_config_file("COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml"))
|
117 |
cfg.DATASETS.TEST = ()
|
118 |
cfg.DATALOADER.NUM_WORKERS = 2
|
119 |
-
cfg.MODEL.WEIGHTS =
|
120 |
cfg.SOLVER.IMS_PER_BATCH = 2
|
121 |
cfg.SOLVER.BASE_LR = 0.001
|
122 |
cfg.SOLVER.MAX_ITER = 30000
|
123 |
cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 512
|
124 |
cfg.MODEL.ROI_HEADS.NUM_CLASSES = len(thing_classes)
|
125 |
-
|
126 |
cfg.MODEL.WEIGHTS = model_path
|
127 |
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.0
|
128 |
-
predictor = DefaultPredictor(cfg)
|
129 |
|
|
|
130 |
unique_id = f"bigdata2_{uuid.uuid4().hex[:8]}"
|
131 |
-
DatasetCatalog.register(
|
132 |
-
unique_id, lambda: get_vinbigdata_dicts_test(imgdir, pd.read_csv(test_meta), debug=False)
|
133 |
-
)
|
134 |
MetadataCatalog.get(unique_id).set(thing_classes=thing_classes)
|
135 |
metadata = MetadataCatalog.get(unique_id)
|
136 |
-
dataset_dicts = get_vinbigdata_dicts_test(imgdir, pd.read_csv(test_meta), debug=
|
|
|
|
|
|
|
137 |
|
138 |
results_list = []
|
139 |
batch_size = 4
|
@@ -145,19 +150,16 @@ def prediction(image_id_main, local_image_path, model_path):
|
|
145 |
outputs_list = predict_batch(predictor, im_list)
|
146 |
|
147 |
for im, outputs, d in zip(im_list, outputs_list, dataset_dicts_batch):
|
148 |
-
|
149 |
|
150 |
-
|
151 |
-
|
152 |
-
result = {"image_id": image_id, "PredictionString": "14 1.0 0 0 1 1"}
|
153 |
-
else:
|
154 |
-
fields: Dict[str, Any] = instances.get_fields()
|
155 |
pred_classes = fields["pred_classes"]
|
156 |
pred_scores = fields["scores"]
|
157 |
pred_boxes = fields["pred_boxes"].tensor
|
158 |
|
159 |
-
h_ratio =
|
160 |
-
w_ratio =
|
161 |
pred_boxes[:, [0, 2]] *= w_ratio
|
162 |
pred_boxes[:, [1, 3]] *= h_ratio
|
163 |
|
@@ -166,11 +168,12 @@ def prediction(image_id_main, local_image_path, model_path):
|
|
166 |
pred_scores_array = pred_scores.cpu().numpy()
|
167 |
|
168 |
result = {
|
169 |
-
"image_id": image_id,
|
170 |
-
"PredictionString": format_pred(
|
171 |
-
pred_classes_array, pred_boxes_array, pred_scores_array
|
172 |
-
),
|
173 |
}
|
|
|
|
|
|
|
174 |
results_list.append(result)
|
175 |
|
176 |
submission_det = pd.DataFrame(results_list, columns=['image_id', 'PredictionString'])
|
@@ -179,18 +182,19 @@ def prediction(image_id_main, local_image_path, model_path):
|
|
179 |
|
180 |
return submission_det_path
|
181 |
|
182 |
-
|
183 |
-
|
184 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
submission_det_path = prediction(image_id, local_image_path, model_path)
|
186 |
-
return submission_det_path
|
187 |
|
188 |
-
|
189 |
-
fn=process_image,
|
190 |
-
inputs=[gr.Image(type="pil"), gr.Textbox(label="Image ID")],
|
191 |
-
outputs=gr.File(label="submission_det.csv"),
|
192 |
-
title="ECG Image Processing",
|
193 |
-
description="Upload an image and get the resulting CSV file."
|
194 |
-
)
|
195 |
|
196 |
-
|
|
|
|
1 |
import os
|
|
|
2 |
from pathlib import Path
|
3 |
+
from tqdm.notebook import tqdm
|
|
|
|
|
4 |
import numpy as np
|
5 |
+
import pandas as pd
|
6 |
from PIL import Image as PILImage
|
7 |
+
import torch
|
8 |
+
import cv2
|
9 |
+
import pickle
|
10 |
+
import shutil
|
11 |
from detectron2.config import get_cfg
|
12 |
+
from detectron2 import model_zoo
|
13 |
from detectron2.engine import DefaultPredictor
|
14 |
from detectron2.data import DatasetCatalog, MetadataCatalog
|
15 |
from detectron2.utils.visualizer import ColorMode, Visualizer
|
|
|
|
|
|
|
|
|
16 |
from math import ceil
|
17 |
+
import uuid
|
18 |
+
from flask import Flask, request, send_file
|
19 |
|
20 |
+
app = Flask(__name__)
|
21 |
+
|
22 |
+
def get_vinbigdata_dicts_test(imgdir: Path, test_meta: pd.DataFrame, use_cache: bool = True, debug: bool = True):
|
23 |
debug_str = f"_debug{int(debug)}"
|
24 |
cache_path = Path(".") / f"dataset_dicts_cache_test{debug_str}.pkl"
|
25 |
if not use_cache or not cache_path.exists():
|
26 |
+
print("Creating data...")
|
27 |
if debug:
|
28 |
test_meta = test_meta.iloc[:500] # For debug
|
29 |
|
30 |
+
# Load 1 image to get image size.
|
31 |
image_id = test_meta.loc[0, "image_id"]
|
32 |
+
image_path = os.path.join(imgdir, f"{image_id}.png")
|
33 |
+
image = cv2.imread(image_path)
|
34 |
resized_height, resized_width, ch = image.shape
|
35 |
|
36 |
dataset_dicts = []
|
37 |
for index, test_meta_row in tqdm(test_meta.iterrows(), total=len(test_meta)):
|
38 |
record = {}
|
39 |
image_id, height, width = test_meta_row.values
|
40 |
+
filename = os.path.join(imgdir, f"{image_id}.png")
|
41 |
+
record["file_name"] = filename
|
42 |
record["image_id"] = image_id
|
43 |
record["height"] = resized_height
|
44 |
record["width"] = resized_width
|
45 |
dataset_dicts.append(record)
|
46 |
+
|
47 |
with open(cache_path, mode="wb") as f:
|
48 |
pickle.dump(dataset_dicts, f)
|
49 |
|
50 |
+
print(f"Load from cache {cache_path}")
|
51 |
with open(cache_path, mode="rb") as f:
|
52 |
dataset_dicts = pickle.load(f)
|
53 |
return dataset_dicts
|
54 |
|
55 |
+
def format_pred(labels: np.ndarray, boxes: np.ndarray, scores: np.ndarray) -> str:
|
56 |
pred_strings = []
|
57 |
for label, score, bbox in zip(labels, scores, boxes):
|
58 |
xmin, ymin, xmax, ymax = bbox.astype(np.int64)
|
59 |
pred_strings.append(f"{label} {score} {xmin} {ymin} {xmax} {ymax}")
|
60 |
return " ".join(pred_strings)
|
61 |
|
62 |
+
def predict_batch(predictor: DefaultPredictor, im_list: list) -> list:
|
63 |
with torch.no_grad():
|
64 |
inputs_list = []
|
65 |
for original_image in im_list:
|
|
|
94 |
test_meta_path = os.path.join(directory, 'test_meta.csv')
|
95 |
test_meta_df.to_csv(test_meta_path, index=False)
|
96 |
|
97 |
+
print("CSV files have been generated successfully.")
|
98 |
return sample_submission_path, test_meta_path
|
99 |
|
100 |
def prediction(image_id_main, local_image_path, model_path):
|
101 |
thing_classes = [
|
102 |
+
"Aortic enlargement", "Atelectasis", "Calcification", "Cardiomegaly",
|
103 |
+
"Consolidation", "ILD", "Infiltration", "Lung Opacity", "Nodule/Mass",
|
104 |
+
"Other lesion", "Pleural effusion", "Pleural thickening", "Pneumothorax", "Pulmonary fibrosis"
|
105 |
]
|
106 |
+
category_name_to_id = {class_name: index for index, class_name in enumerate(thing_classes)}
|
107 |
|
108 |
+
debug = False
|
109 |
outdir = 'result_images'
|
110 |
os.makedirs(outdir, exist_ok=True)
|
111 |
|
|
|
113 |
os.makedirs(imgdir, exist_ok=True)
|
114 |
shutil.copy(local_image_path, imgdir)
|
115 |
new_image_path = os.path.join(imgdir, os.path.basename(local_image_path))
|
116 |
+
|
117 |
sample_submission, test_meta = csv_create(new_image_path, image_id_main)
|
118 |
|
119 |
cfg = get_cfg()
|
|
|
121 |
cfg.merge_from_file(model_zoo.get_config_file("COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml"))
|
122 |
cfg.DATASETS.TEST = ()
|
123 |
cfg.DATALOADER.NUM_WORKERS = 2
|
124 |
+
cfg.MODEL.WEIGHTS = model_path
|
125 |
cfg.SOLVER.IMS_PER_BATCH = 2
|
126 |
cfg.SOLVER.BASE_LR = 0.001
|
127 |
cfg.SOLVER.MAX_ITER = 30000
|
128 |
cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 512
|
129 |
cfg.MODEL.ROI_HEADS.NUM_CLASSES = len(thing_classes)
|
|
|
130 |
cfg.MODEL.WEIGHTS = model_path
|
131 |
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.0
|
|
|
132 |
|
133 |
+
predictor = DefaultPredictor(cfg)
|
134 |
unique_id = f"bigdata2_{uuid.uuid4().hex[:8]}"
|
135 |
+
DatasetCatalog.register(unique_id, lambda: get_vinbigdata_dicts_test(imgdir, pd.read_csv(test_meta), debug=debug))
|
|
|
|
|
136 |
MetadataCatalog.get(unique_id).set(thing_classes=thing_classes)
|
137 |
metadata = MetadataCatalog.get(unique_id)
|
138 |
+
dataset_dicts = get_vinbigdata_dicts_test(imgdir, pd.read_csv(test_meta), debug=debug)
|
139 |
+
|
140 |
+
if debug:
|
141 |
+
dataset_dicts = dataset_dicts[:100]
|
142 |
|
143 |
results_list = []
|
144 |
batch_size = 4
|
|
|
150 |
outputs_list = predict_batch(predictor, im_list)
|
151 |
|
152 |
for im, outputs, d in zip(im_list, outputs_list, dataset_dicts_batch):
|
153 |
+
resized_height, resized_width, ch = im.shape
|
154 |
|
155 |
+
if outputs["instances"].has("pred_classes"):
|
156 |
+
fields = outputs["instances"].get_fields()
|
|
|
|
|
|
|
157 |
pred_classes = fields["pred_classes"]
|
158 |
pred_scores = fields["scores"]
|
159 |
pred_boxes = fields["pred_boxes"].tensor
|
160 |
|
161 |
+
h_ratio = d["height"] / resized_height
|
162 |
+
w_ratio = d["width"] / resized_width
|
163 |
pred_boxes[:, [0, 2]] *= w_ratio
|
164 |
pred_boxes[:, [1, 3]] *= h_ratio
|
165 |
|
|
|
168 |
pred_scores_array = pred_scores.cpu().numpy()
|
169 |
|
170 |
result = {
|
171 |
+
"image_id": d["image_id"],
|
172 |
+
"PredictionString": format_pred(pred_classes_array, pred_boxes_array, pred_scores_array)
|
|
|
|
|
173 |
}
|
174 |
+
else:
|
175 |
+
result = {"image_id": d["image_id"], "PredictionString": "14 1 0 0 1 1"}
|
176 |
+
|
177 |
results_list.append(result)
|
178 |
|
179 |
submission_det = pd.DataFrame(results_list, columns=['image_id', 'PredictionString'])
|
|
|
182 |
|
183 |
return submission_det_path
|
184 |
|
185 |
+
@app.route('/predict', methods=['POST'])
|
186 |
+
def predict():
|
187 |
+
image_id = request.form['image_id']
|
188 |
+
image_file = request.files['image']
|
189 |
+
model_path = request.form['model_path']
|
190 |
+
|
191 |
+
local_image_path = os.path.join("input_images", image_file.filename)
|
192 |
+
os.makedirs("input_images", exist_ok=True)
|
193 |
+
image_file.save(local_image_path)
|
194 |
+
|
195 |
submission_det_path = prediction(image_id, local_image_path, model_path)
|
|
|
196 |
|
197 |
+
return send_file(submission_det_path, as_attachment=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
|
199 |
+
if __name__ == '__main__':
|
200 |
+
app.run(host='0.0.0.0', port=8000)
|