Spaces:
Runtime error
Runtime error
xinwei89
commited on
Commit
•
6825ad3
1
Parent(s):
52981c1
update app
Browse files- app.py +41 -21
- backend.py +86 -57
app.py
CHANGED
@@ -1,26 +1,46 @@
|
|
1 |
-
import gradio as gr
|
2 |
-
from backend import visualize_image
|
3 |
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
|
|
|
|
|
|
8 |
|
9 |
-
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
-
#
|
13 |
-
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
16 |
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
outputs=output_image,
|
22 |
-
title=title,
|
23 |
-
description=description
|
24 |
-
)
|
25 |
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
2 |
+
import os
|
3 |
+
os.system("python -m pip install --upgrade pip")
|
4 |
+
os.system("pip uninstall -y gradio")
|
5 |
+
os.system("pip install gradio==4.1.2")
|
6 |
+
|
7 |
+
import gradio as gr
|
8 |
+
from backend import *
|
9 |
|
10 |
+
with gr.Blocks() as demo:
|
11 |
+
gr.Markdown(
|
12 |
+
"""
|
13 |
+
# Aerial Image Segmentation
|
14 |
+
An instance segmentation demo for identifying boundaries of buildings and trees in aerial images using DETR (End-to-End Object Detection) model with MaskRCNN-101 backbone
|
15 |
+
"""
|
16 |
+
)
|
17 |
+
with gr.Row(equal_height=True):
|
18 |
+
with gr.Column():
|
19 |
+
image_input = gr.components.Image(type="pil", label="Input Image")
|
20 |
+
with gr.Column():
|
21 |
+
mode_dropdown = gr.Dropdown(choices=["Trees", "Buildings", "Both"], label="Detection Mode", value="Both")
|
22 |
+
color_mode_select = gr.components.Radio(choices=["Black/white", "Random", "Segmentation"], label="Color Mode", value="Segmentation")
|
23 |
|
24 |
+
# split tree and building into two rows side by side
|
25 |
+
tree_row, building_row = gr.Row(), gr.Row()
|
26 |
+
# tree_col, building_col = gr.Column(elem_id="tree_col"), gr.Column(elem_id="building_col")
|
27 |
+
with tree_row as tree_options:
|
28 |
+
tree_version_dropdown = gr.Dropdown(choices=["treev1", "treev2"], label="Tree Detection Version", value="treev2", visible=True, interactive=True)
|
29 |
+
tree_pth_dropdown = gr.Dropdown(choices=list_pth_files_in_directory("tree_model_weights", "v2"), label="Select a tree model file", visible=True, interactive=True)
|
30 |
+
tree_threshold_slider = gr.Slider(minimum=0, maximum=1, step=0.1, value=0.7, label='Set confidence threshold "%" for trees', visible=True, interactive=True)
|
31 |
|
32 |
+
with building_row as building_options:
|
33 |
+
building_version_dropdown = gr.Dropdown(choices=["buildingv1", "buildingv2"], label="Building Detection Version", value="buildingv1", visible=True, interactive=True)
|
34 |
+
building_pth_dropdown = gr.Dropdown(choices=list_pth_files_in_directory("building_model_weight", "v1"), label="Select a building model file", visible=True, interactive=True)
|
35 |
+
building_threshold_slider = gr.Slider(minimum=0, maximum=1, step=0.1, value=0.7, label='Set confidence threshold "%" for buildings', visible=True, interactive=True)
|
|
|
|
|
|
|
|
|
36 |
|
37 |
+
# mode_dropdown.change(update_visibility, inputs=[mode_dropdown], outputs=[tree_version_dropdown, tree_pth_dropdown, tree_threshold_slider, building_version_dropdown, building_pth_dropdown, building_threshold_slider])
|
38 |
+
mode_dropdown.change(update_row_visibility, inputs=[mode_dropdown], outputs=[tree_row, building_row])
|
39 |
+
tree_version_dropdown.change(update_path_options, inputs=[tree_version_dropdown], outputs=[tree_pth_dropdown])
|
40 |
+
building_version_dropdown.change(update_path_options, inputs=[building_version_dropdown], outputs=[building_pth_dropdown])
|
41 |
+
|
42 |
+
output_image = gr.components.Image(type="pil", label="Output Image")
|
43 |
+
run_model = gr.Button("Upload Image and Run Model")
|
44 |
+
|
45 |
+
run_model.click(visualize_image, inputs=[image_input, mode_dropdown, tree_threshold_slider, building_threshold_slider, color_mode_select, tree_version_dropdown, tree_pth_dropdown, building_version_dropdown, building_pth_dropdown], outputs=[output_image])
|
46 |
+
demo.launch()
|
backend.py
CHANGED
@@ -3,6 +3,8 @@ aerial-segmentation
|
|
3 |
Proof of concept showing effectiveness of a fine tuned instance segmentation model for detecting trees.
|
4 |
"""
|
5 |
import os
|
|
|
|
|
6 |
import cv2
|
7 |
os.system("pip install 'git+https://github.com/facebookresearch/detectron2.git'")
|
8 |
from transformers import DetrFeatureExtractor, DetrForSegmentation
|
@@ -28,33 +30,67 @@ from detectron2.utils.visualizer import ColorMode
|
|
28 |
from detectron2.structures import Instances
|
29 |
|
30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
# Model for trees
|
32 |
-
|
33 |
-
tree_cfg
|
34 |
-
tree_cfg.
|
35 |
-
tree_cfg.MODEL.
|
36 |
-
tree_cfg.MODEL.
|
37 |
-
|
|
|
|
|
|
|
38 |
|
39 |
# Model for buildings
|
40 |
-
|
41 |
-
building_cfg
|
42 |
-
building_cfg.
|
43 |
-
building_cfg.MODEL.
|
44 |
-
building_cfg.MODEL.
|
45 |
-
|
|
|
|
|
|
|
46 |
|
47 |
# A function that runs the buildings model on an given image and confidence threshold
|
48 |
-
def segment_building(im,
|
49 |
-
building_cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = confidence_threshold
|
50 |
outputs = building_predictor(im)
|
51 |
building_instances = outputs["instances"].to("cpu")
|
52 |
|
53 |
return building_instances
|
54 |
|
55 |
# A function that runs the trees model on an given image and confidence threshold
|
56 |
-
def segment_tree(im,
|
57 |
-
tree_cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = confidence_threshold
|
58 |
outputs = tree_predictor(im)
|
59 |
tree_instances = outputs["instances"].to("cpu")
|
60 |
|
@@ -69,50 +105,43 @@ def map_color_mode(color_mode):
|
|
69 |
elif color_mode == "Segmentation" or color_mode == None:
|
70 |
return ColorMode.SEGMENTATION
|
71 |
|
72 |
-
def
|
73 |
-
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
75 |
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
instances = segment_building(im, building_threshold)
|
80 |
-
elif mode == "Both" or mode == None:
|
81 |
-
tree_instances = segment_tree(im, tree_threshold)
|
82 |
-
building_instances = segment_building(im, building_threshold)
|
83 |
-
instances = Instances.cat([tree_instances, building_instances])
|
84 |
-
|
85 |
-
metadata = MetadataCatalog.get("urban-trees-fdokv_train")
|
86 |
-
print("metadata", type(metadata), metadata)
|
87 |
-
print('metadata.get("thing_classes")', type(metadata.get("thing_classes")), metadata.get("thing_classes"))
|
88 |
-
|
89 |
-
visualizer = Visualizer(im[:, :, ::-1],
|
90 |
-
metadata=metadata,
|
91 |
-
scale=0.5,
|
92 |
-
instance_mode=color_mode)
|
93 |
-
|
94 |
-
dataset_names = MetadataCatalog.list()
|
95 |
-
print(dataset_names)
|
96 |
-
|
97 |
-
metadata = MetadataCatalog.get("urban-small_train")
|
98 |
-
category_names = metadata.get("thing_classes")
|
99 |
-
print(category_names)
|
100 |
-
with open("building_model_weight/_annotations.coco.json", "r") as f:
|
101 |
coco = json.load(f)
|
102 |
-
|
103 |
-
print("categories", categories)
|
104 |
metadata.thing_classes = [c["name"] for c in categories]
|
105 |
-
|
106 |
-
# visualizer = Visualizer(im[:, :, ::-1],
|
107 |
-
# metadata=metadata,
|
108 |
-
# scale=0.5,
|
109 |
-
# instance_mode=color_mode)
|
110 |
-
# # in the visualizer, add category label names to detected instances
|
111 |
-
# for instance in instances:
|
112 |
-
# label = category_names[instance["category_id"]]
|
113 |
-
# visualizer.draw_text(label, instance["bbox"][:2])
|
114 |
|
115 |
-
|
|
|
|
|
116 |
|
117 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
|
|
|
|
3 |
Proof of concept showing effectiveness of a fine tuned instance segmentation model for detecting trees.
|
4 |
"""
|
5 |
import os
|
6 |
+
import gradio as gr
|
7 |
+
|
8 |
import cv2
|
9 |
os.system("pip install 'git+https://github.com/facebookresearch/detectron2.git'")
|
10 |
from transformers import DetrFeatureExtractor, DetrForSegmentation
|
|
|
30 |
from detectron2.structures import Instances
|
31 |
|
32 |
|
33 |
+
def list_pth_files_in_directory(directory, version="v1"):
|
34 |
+
files = os.listdir(directory)
|
35 |
+
version = version.split("v")[1]
|
36 |
+
# return files that contains substring version and end with .pth
|
37 |
+
pth_files = [f for f in files if version in f and f.endswith(".pth")]
|
38 |
+
return pth_files
|
39 |
+
|
40 |
+
def get_version_cfg_yml(path):
|
41 |
+
directory = path.split("/")[0]
|
42 |
+
version = path.split("/")[1]
|
43 |
+
files = os.listdir(directory)
|
44 |
+
cfg_file = [f for f in files if (f.endswith(".yml") or f.endswith(".yaml")) and version in f]
|
45 |
+
return directory + "/" + cfg_file[0]
|
46 |
+
|
47 |
+
def update_row_visibility(mode):
|
48 |
+
visibility = {
|
49 |
+
"tree": mode in ["Trees", "Both"],
|
50 |
+
"building": mode in ["Buildings", "Both"]
|
51 |
+
}
|
52 |
+
tree_row, building_row = gr.Row(visible=visibility["tree"]), gr.Row(visible=visibility["building"])
|
53 |
+
|
54 |
+
return tree_row, building_row
|
55 |
+
|
56 |
+
def update_path_options(version):
|
57 |
+
if "tree" in version:
|
58 |
+
directory = "tree_model_weights"
|
59 |
+
else:
|
60 |
+
directory = "building_model_weight"
|
61 |
+
return gr.Dropdown(choices=list_pth_files_in_directory(directory, version), label=f"Select a {version.split('v')[0]} model file", visible=True, interactive=True)
|
62 |
+
|
63 |
# Model for trees
|
64 |
+
def tree_model(tree_version_dropdown, tree_pth_dropdown, tree_threshold, device="cpu"):
|
65 |
+
tree_cfg = get_cfg()
|
66 |
+
tree_cfg.merge_from_file(get_version_cfg_yml(f"tree_model_weights/{tree_version_dropdown}"))
|
67 |
+
tree_cfg.MODEL.DEVICE=device
|
68 |
+
tree_cfg.MODEL.WEIGHTS = f"tree_model_weights/{tree_pth_dropdown}"
|
69 |
+
tree_cfg.MODEL.ROI_HEADS.NUM_CLASSES = 2 # TODO change this
|
70 |
+
tree_cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = tree_threshold
|
71 |
+
tree_predictor = DefaultPredictor(tree_cfg)
|
72 |
+
return tree_predictor
|
73 |
|
74 |
# Model for buildings
|
75 |
+
def building_model(building_version_dropdown, building_pth_dropdown, building_threshold, device="cpu"):
|
76 |
+
building_cfg = get_cfg()
|
77 |
+
building_cfg.merge_from_file(get_version_cfg_yml(f"building_model_weight/{building_version_dropdown}"))
|
78 |
+
building_cfg.MODEL.DEVICE=device
|
79 |
+
building_cfg.MODEL.WEIGHTS = f"building_model_weight/{building_pth_dropdown}"
|
80 |
+
building_cfg.MODEL.ROI_HEADS.NUM_CLASSES = 8 # TODO change this
|
81 |
+
building_cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = building_threshold
|
82 |
+
building_predictor = DefaultPredictor(building_cfg)
|
83 |
+
return building_predictor
|
84 |
|
85 |
# A function that runs the buildings model on an given image and confidence threshold
|
86 |
+
def segment_building(im, building_predictor):
|
|
|
87 |
outputs = building_predictor(im)
|
88 |
building_instances = outputs["instances"].to("cpu")
|
89 |
|
90 |
return building_instances
|
91 |
|
92 |
# A function that runs the trees model on an given image and confidence threshold
|
93 |
+
def segment_tree(im, tree_predictor):
|
|
|
94 |
outputs = tree_predictor(im)
|
95 |
tree_instances = outputs["instances"].to("cpu")
|
96 |
|
|
|
105 |
elif color_mode == "Segmentation" or color_mode == None:
|
106 |
return ColorMode.SEGMENTATION
|
107 |
|
108 |
+
def load_predictor(model, version, pth, threshold):
|
109 |
+
return model(version, pth, threshold)
|
110 |
+
|
111 |
+
def load_instances(image, predictor, segment_function):
|
112 |
+
return segment_function(image, predictor)
|
113 |
+
|
114 |
+
def combine_instances(tree_instances, building_instances):
|
115 |
+
return Instances.cat([tree_instances, building_instances])
|
116 |
|
117 |
+
def get_metadata(dataset_name, coco_file):
|
118 |
+
metadata = MetadataCatalog.get(dataset_name)
|
119 |
+
with open(coco_file, "r") as f:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
coco = json.load(f)
|
121 |
+
categories = coco["categories"]
|
|
|
122 |
metadata.thing_classes = [c["name"] for c in categories]
|
123 |
+
return metadata
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
|
125 |
+
def visualize_image(im, mode, tree_threshold, building_threshold, color_mode, tree_version, tree_pth, building_version, building_pth):
|
126 |
+
im = np.array(im)
|
127 |
+
color_mode = map_color_mode(color_mode)
|
128 |
|
129 |
+
instances = None
|
130 |
+
|
131 |
+
if mode in {"Trees", "Both"}:
|
132 |
+
tree_predictor = load_predictor(tree_model, tree_version, tree_pth, tree_threshold)
|
133 |
+
tree_instances = load_instances(im, tree_predictor, segment_tree)
|
134 |
+
instances = tree_instances
|
135 |
+
|
136 |
+
if mode in {"Buildings", "Both"}:
|
137 |
+
building_predictor = load_predictor(building_model, building_version, building_pth, building_threshold)
|
138 |
+
building_instances = load_instances(im, building_predictor, segment_building)
|
139 |
+
instances = building_instances if mode == "Buildings" else combine_instances(instances, building_instances)
|
140 |
+
|
141 |
+
# Assuming 'urban-small_train' is intended for both Trees and Buildings
|
142 |
+
metadata = get_metadata("urban-small_train", "building_model_weight/_annotations.coco.json")
|
143 |
+
visualizer = Visualizer(im[:, :, ::-1], metadata=metadata, scale=0.5, instance_mode=color_mode)
|
144 |
+
|
145 |
+
output_image = visualizer.draw_instance_predictions(instances)
|
146 |
|
147 |
+
return Image.fromarray(output_image.get_image()[:, :, ::-1])
|