Jordan Pierce
commited on
Commit
•
6300104
1
Parent(s):
0dd9a9d
updated app
Browse files- .idea/workspace.xml +2 -3
- app.py +5 -186
.idea/workspace.xml
CHANGED
@@ -4,9 +4,7 @@
|
|
4 |
<option name="SCOPE_TYPE" value="3" />
|
5 |
</component>
|
6 |
<component name="ChangeListManager">
|
7 |
-
<list default="true" id="e4d9959f-0c5b-4a80-8b43-a006df26f93a" name="Changes" comment=""
|
8 |
-
<change beforePath="$PROJECT_DIR$/app.py" beforeDir="false" afterPath="$PROJECT_DIR$/app.py" afterDir="false" />
|
9 |
-
</list>
|
10 |
<option name="SHOW_DIALOG" value="false" />
|
11 |
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
12 |
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
@@ -54,6 +52,7 @@
|
|
54 |
<updated>1666646148268</updated>
|
55 |
<workItem from="1666646160771" duration="3554000" />
|
56 |
<workItem from="1666649813029" duration="426000" />
|
|
|
57 |
</task>
|
58 |
<servers />
|
59 |
</component>
|
|
|
4 |
<option name="SCOPE_TYPE" value="3" />
|
5 |
</component>
|
6 |
<component name="ChangeListManager">
|
7 |
+
<list default="true" id="e4d9959f-0c5b-4a80-8b43-a006df26f93a" name="Changes" comment="" />
|
|
|
|
|
8 |
<option name="SHOW_DIALOG" value="false" />
|
9 |
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
10 |
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
|
|
52 |
<updated>1666646148268</updated>
|
53 |
<workItem from="1666646160771" duration="3554000" />
|
54 |
<workItem from="1666649813029" duration="426000" />
|
55 |
+
<workItem from="1666707251602" duration="12000" />
|
56 |
</task>
|
57 |
<servers />
|
58 |
</component>
|
app.py
CHANGED
@@ -1,200 +1,19 @@
|
|
1 |
-
|
2 |
-
import detectron2
|
3 |
-
except:
|
4 |
-
import os
|
5 |
-
os.system('pip install git+https://github.com/facebookresearch/detectron2.git')
|
6 |
-
|
7 |
-
import glob
|
8 |
-
|
9 |
-
import numpy as np
|
10 |
-
import detectron2
|
11 |
-
import torchvision
|
12 |
-
import cv2
|
13 |
-
import torch
|
14 |
-
|
15 |
-
from detectron2 import model_zoo
|
16 |
-
from detectron2.data import Metadata
|
17 |
-
from detectron2.structures import BoxMode
|
18 |
-
from detectron2.utils.visualizer import Visualizer
|
19 |
-
from detectron2.config import get_cfg
|
20 |
-
from detectron2.utils.visualizer import ColorMode
|
21 |
-
from detectron2.modeling import build_model
|
22 |
-
import detectron2.data.transforms as T
|
23 |
-
from detectron2.checkpoint import DetectionCheckpointer
|
24 |
-
|
25 |
import gradio as gr
|
26 |
-
|
27 |
-
|
28 |
-
# -----------------------------------------------------------------------------
|
29 |
-
# CONFIGS - loaded just the one time when script is first ran to save time.
|
30 |
-
#
|
31 |
-
# This is where you will set all the relevant config file and weight file
|
32 |
-
# variables:
|
33 |
-
# CONFIG_FILE - Training specific config file for fathomnet
|
34 |
-
# WEIGHTS_FILE - Path to the model with fathomnet weights
|
35 |
-
# NMS_THRESH - Set a nms threshold for the all boxes results
|
36 |
-
# SCORE_THRESH - This is where you can set the model score threshold
|
37 |
-
|
38 |
-
CONFIG_FILE = "fathomnet_config_v2_1280.yaml"
|
39 |
-
WEIGHTS_FILE = "model_final.pth"
|
40 |
-
NMS_THRESH = 0.45 #
|
41 |
-
SCORE_THRESH = 0.3 #
|
42 |
-
|
43 |
-
# A metadata object that contains metadata on each class category; used with
|
44 |
-
# Detectron for linking predictions to names and for visualizations.
|
45 |
-
fathomnet_metadata = Metadata(
|
46 |
-
name='fathomnet_val',
|
47 |
-
thing_classes=[
|
48 |
-
'Anemone',
|
49 |
-
'Fish',
|
50 |
-
'Eel',
|
51 |
-
'Gastropod',
|
52 |
-
'Sea star',
|
53 |
-
'Feather star',
|
54 |
-
'Sea cucumber',
|
55 |
-
'Urchin',
|
56 |
-
'Glass sponge',
|
57 |
-
'Sea fan',
|
58 |
-
'Soft coral',
|
59 |
-
'Sea pen',
|
60 |
-
'Stony coral',
|
61 |
-
'Ray',
|
62 |
-
'Crab',
|
63 |
-
'Shrimp',
|
64 |
-
'Squat lobster',
|
65 |
-
'Flatfish',
|
66 |
-
'Sea spider',
|
67 |
-
'Worm']
|
68 |
-
)
|
69 |
-
|
70 |
-
# This is where the model parameters are instantiated. There is a LOT of
|
71 |
-
# nested arguments in these yaml files, and the merging of baseline defaults
|
72 |
-
# plus dataset specific parameters.
|
73 |
-
base_model_path = "COCO-Detection/retinanet_R_50_FPN_3x.yaml"
|
74 |
-
|
75 |
-
cfg = get_cfg()
|
76 |
-
cfg.MODEL.DEVICE = 'cpu'
|
77 |
-
cfg.merge_from_file(model_zoo.get_config_file(base_model_path))
|
78 |
-
cfg.merge_from_file(CONFIG_FILE)
|
79 |
-
cfg.MODEL.RETINANET.SCORE_THRESH_TEST = SCORE_THRESH
|
80 |
-
cfg.MODEL.WEIGHTS = WEIGHTS_FILE
|
81 |
-
|
82 |
-
# Loading of the model weights, but more importantly this is where the model
|
83 |
-
# is actually instantiated as something that can take inputs and provide
|
84 |
-
# outputs. There is a lot of documentation about this, but not much in the
|
85 |
-
# way of straightforward tutorials.
|
86 |
-
model = build_model(cfg)
|
87 |
-
checkpointer = DetectionCheckpointer(model)
|
88 |
-
checkpointer.load(cfg.MODEL.WEIGHTS)
|
89 |
-
model.eval()
|
90 |
-
|
91 |
-
# Create two augmentations and make a list to iterate over
|
92 |
-
aug1 = T.ResizeShortestEdge(short_edge_length=[cfg.INPUT.MIN_SIZE_TEST],
|
93 |
-
max_size=cfg.INPUT.MAX_SIZE_TEST,
|
94 |
-
sample_style="choice")
|
95 |
-
|
96 |
-
aug2 = T.ResizeShortestEdge(short_edge_length=[1080],
|
97 |
-
max_size=1980,
|
98 |
-
sample_style="choice")
|
99 |
-
|
100 |
-
augmentations = [aug1, aug2]
|
101 |
-
|
102 |
-
# We use a separate NMS layer because initially detectron only does nms intra
|
103 |
-
# class, so we want to do nms on all boxes.
|
104 |
-
post_process_nms = torchvision.ops.nms
|
105 |
-
# -----------------------------------------------------------------------------
|
106 |
-
|
107 |
-
|
108 |
-
def run_inference(test_image):
|
109 |
-
"""This function runs through inference pipeline, taking in a single
|
110 |
-
image as input. The image will be opened, augmented, ran through the
|
111 |
-
model, which will output bounding boxes and class categories for each
|
112 |
-
object detected. These are then passed back to the calling function."""
|
113 |
-
|
114 |
-
# Load the image, get the height and width. Iterate over each
|
115 |
-
# augmentation: do the augmentation, run the model, perform nms
|
116 |
-
# thresholding, instantiate a useful object for visualizing the outputs.
|
117 |
-
# Saves a list of outputs objects
|
118 |
-
img = cv2.imread(test_image)
|
119 |
-
im_height, im_width, _ = img.shape
|
120 |
-
v_inf = Visualizer(img[:, :, ::-1],
|
121 |
-
metadata=fathomnet_metadata,
|
122 |
-
scale=1.0,
|
123 |
-
instance_mode=ColorMode.IMAGE_BW)
|
124 |
-
|
125 |
-
insts = []
|
126 |
-
|
127 |
-
# iterate over input augmentations (apply resizing)
|
128 |
-
for augmentation in augmentations:
|
129 |
-
im = augmentation.get_transform(img).apply_image(img)
|
130 |
-
|
131 |
-
# pre-process image by reshaping and converting to tensor
|
132 |
-
# pass to model, which outputs a dict containing info on all detections
|
133 |
-
with torch.no_grad():
|
134 |
-
im = torch.as_tensor(im.astype("float32").transpose(2, 0, 1))
|
135 |
-
model_outputs = model([{"image": im,
|
136 |
-
"height": im_height,
|
137 |
-
"width": im_width}])[0]
|
138 |
-
|
139 |
-
# populate list with all outputs
|
140 |
-
for _ in range(len(model_outputs['instances'])):
|
141 |
-
insts.append(model_outputs['instances'][_])
|
142 |
-
|
143 |
-
# TODO explore the outputs to determine what needs to be passed to tator.py
|
144 |
-
# Concatenate the model outputs and run NMS thresholding on all output;
|
145 |
-
# instantiate a dummy Instance object to concatenate the instances
|
146 |
-
model_inst = detectron2.structures.instances.Instances([im_height,
|
147 |
-
im_width])
|
148 |
|
149 |
-
|
150 |
-
|
151 |
-
model_inst.cat(insts).scores,
|
152 |
-
NMS_THRESH).to("cpu").tolist()]
|
153 |
|
154 |
-
|
155 |
-
out_pil = Image.fromarray(out_inf_raw.get_image()).convert('RGB')
|
156 |
|
157 |
return out_pil
|
158 |
|
159 |
|
160 |
-
def convert_predictions(xx, thing_classes):
|
161 |
-
"""Helper funtion to post-process the predictions made by Detectron2
|
162 |
-
codebase to work with TATOR input requirements."""
|
163 |
-
|
164 |
-
predictions = []
|
165 |
-
|
166 |
-
for _ in range(len(xx)):
|
167 |
-
|
168 |
-
# Obtain the first prediction, instance
|
169 |
-
instance = xx.__getitem__(_)
|
170 |
-
|
171 |
-
# Map the coordinates to the variables
|
172 |
-
x, y, x2, y2 = map(float, instance.pred_boxes.tensor[0])
|
173 |
-
w, h = x2 - x, y2 - y
|
174 |
-
|
175 |
-
# Use class list to get the common name (string); get confidence score.
|
176 |
-
class_category = thing_classes[int(instance.pred_classes[0])]
|
177 |
-
confidence_score = float(instance.scores[0])
|
178 |
-
|
179 |
-
# Create a spec dict for TATOR
|
180 |
-
prediction = {'x': x,
|
181 |
-
'y': y,
|
182 |
-
'width': w,
|
183 |
-
'height': h,
|
184 |
-
'class_category': class_category,
|
185 |
-
'confidence': confidence_score}
|
186 |
-
|
187 |
-
predictions.append(prediction)
|
188 |
-
|
189 |
-
return predictions
|
190 |
-
|
191 |
-
|
192 |
# -----------------------------------------------------------------------------
|
193 |
# GRADIO APP
|
194 |
# -----------------------------------------------------------------------------
|
195 |
|
196 |
-
examples = [glob.glob("images/*.png")]
|
197 |
-
|
198 |
title = "MBARI Monterey Bay Benthic Supercategory"
|
199 |
description = "Gradio demo for MBARI Monterey Bay Benthic Supercategory: This " \
|
200 |
"is a RetinaNet model fine-tuned from the Detectron2 object " \
|
|
|
1 |
+
from inference import *
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
import gradio as gr
|
3 |
+
import glob
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
+
def gradio_app(image_path):
|
6 |
+
"""Helper function to run inference on provided image"""
|
|
|
|
|
7 |
|
8 |
+
predictions, out_pil = run_inference(image_path)
|
|
|
9 |
|
10 |
return out_pil
|
11 |
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
# -----------------------------------------------------------------------------
|
14 |
# GRADIO APP
|
15 |
# -----------------------------------------------------------------------------
|
16 |
|
|
|
|
|
17 |
title = "MBARI Monterey Bay Benthic Supercategory"
|
18 |
description = "Gradio demo for MBARI Monterey Bay Benthic Supercategory: This " \
|
19 |
"is a RetinaNet model fine-tuned from the Detectron2 object " \
|