Spaces:
Sleeping
Sleeping
Initial commit #2
Browse files- SegFormer_B3_1024_finetuned.pth +3 -0
- example_vis.py +118 -0
- metrics_filtered_cls.py +133 -0
- yolov8s.pt +3 -0
SegFormer_B3_1024_finetuned.pth
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:ab92f8baab8b0b2b30a5b408d4d3a87c9a0f53139e66dd6ffb102cbdbc62a029
|
3 |
+
size 109653114
|
example_vis.py
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright Oliver Zendel, AIT Austrian Institute of Technology Gmbh 2019
|
2 |
+
# Example visualization tool to illustrate interpretation of RailSem19 data usage
|
3 |
+
|
4 |
+
import sys, os, glob, math, argparse
|
5 |
+
import numpy as np
|
6 |
+
import cv2, json
|
7 |
+
import matplotlib.pyplot as plt
|
8 |
+
|
9 |
+
rs19_label2bgr = {"buffer-stop": (70,70,70),
|
10 |
+
"crossing": (128,64,128),
|
11 |
+
"guard-rail": (0,255,0),
|
12 |
+
"train-car" : (100,80,0),
|
13 |
+
"platform" : (232,35,244),
|
14 |
+
"rail": (255,255,0),
|
15 |
+
"switch-indicator": (127,255,0),
|
16 |
+
"switch-left": (255,255,0),
|
17 |
+
"switch-right": (127,127,0),
|
18 |
+
"switch-unknown": (191,191,0),
|
19 |
+
"switch-static": (0,255,127),
|
20 |
+
"track-sign-front" : (0,220,220),
|
21 |
+
"track-signal-front" : (30,170,250),
|
22 |
+
"track-signal-back" : (0,85,125),
|
23 |
+
#rail occluders
|
24 |
+
"person-group" : (60,20,220),
|
25 |
+
"car" : (142,0,0),
|
26 |
+
"fence" : (153,153,190),
|
27 |
+
"person" : (60,20,220),
|
28 |
+
"pole" : (153,153,153),
|
29 |
+
"rail-occluder" : (255,255,255),
|
30 |
+
"truck" : (70,0,0)
|
31 |
+
}
|
32 |
+
|
33 |
+
def files_in_subdirs(start_dir, pattern = ["*.png","*.jpg","*.jpeg"]):
|
34 |
+
files = []
|
35 |
+
for p in pattern:
|
36 |
+
for dir,_,_ in os.walk(start_dir):
|
37 |
+
files.extend(glob.glob(os.path.join(dir,p)))
|
38 |
+
return files
|
39 |
+
|
40 |
+
def config_to_rgb(inp_path_config_json, default_col = [255,255,255]):
|
41 |
+
lut = []
|
42 |
+
inp_json = json.load(open(inp_path_config_json, 'r'))
|
43 |
+
for c in range(3): #for each color channel
|
44 |
+
lut_c =[l["color"][c] for l in inp_json["labels"]]+[default_col[c]]*(256-len(inp_json["labels"]))
|
45 |
+
lut.append(np.asarray(lut_c, dtype=np.uint8))
|
46 |
+
return lut
|
47 |
+
|
48 |
+
def corss_hatch_rail(im_vis, coords, color_left=(255,255,0), color_right=(127,127,0)):
|
49 |
+
ml = min(len(coords[0]), len(coords[1]))
|
50 |
+
for i in range(ml):
|
51 |
+
midpnt = ((coords[0][i][0]+coords[1][i][0])//2, (coords[0][i][1]+coords[1][i][1])//2)
|
52 |
+
cv2.line(im_vis, tuple(coords[0][i]), midpnt, color_left)
|
53 |
+
cv2.line(im_vis, midpnt, tuple(coords[1][i]), color_right)
|
54 |
+
|
55 |
+
def json_to_img(inp_path_json, line_thickness=2):
|
56 |
+
inp_json = json.load(open(inp_path_json, 'r'))
|
57 |
+
im_json = np.zeros((inp_json["imgHeight"], inp_json["imgWidth"],3), dtype=np.uint8)
|
58 |
+
for obj in inp_json["objects"]:
|
59 |
+
col = rs19_label2bgr.get(obj["label"],[255,255,255])
|
60 |
+
if "boundingbox" in obj:
|
61 |
+
cv2.rectangle(im_json, tuple(obj["boundingbox"][0:2]), tuple(obj["boundingbox"][2:4]), col, line_thickness)
|
62 |
+
elif "polygon" in obj:
|
63 |
+
pnts_draw = np.around(np.array(obj["polygon"])).astype(np.int32)
|
64 |
+
cv2.polylines(im_json, [pnts_draw], True, col, line_thickness)
|
65 |
+
elif "polyline-pair" in obj:
|
66 |
+
#left rail of a rail pair has index 0, right rail of a rail pair has index 1
|
67 |
+
rails_draw = [np.around(np.array(obj["polyline-pair"][i])).astype(np.int32) for i in range(2)]
|
68 |
+
corss_hatch_rail(im_json, obj["polyline-pair"], rs19_label2bgr['switch-left'], rs19_label2bgr['switch-right'])
|
69 |
+
cv2.polylines(im_json, rails_draw, False, col)
|
70 |
+
elif "polyline" in obj:
|
71 |
+
rail_draw = np.around(np.array(obj["polyline"])).astype(np.int32)
|
72 |
+
cv2.polylines(im_json, [rail_draw], False, col, line_thickness)
|
73 |
+
return im_json, inp_json["frame"]
|
74 |
+
|
75 |
+
def get_joined_img(inp_path_json, jpg_folder, uint8_folder, lut_bgr, blend_vals=[0.65,0.25,0.1]):
|
76 |
+
im_json, frameid = json_to_img(inp_path_json, line_thickness=2) #visualize geometric annotations
|
77 |
+
inp_path_jpg = os.path.join(jpg_folder,frameid+".jpg")
|
78 |
+
inp_path_uint8 = os.path.join(uint8_folder,frameid+".png")
|
79 |
+
im_jpg = cv2.imread(inp_path_jpg) #add intensity image as background
|
80 |
+
im_id_map = cv2.imread(inp_path_uint8,cv2.IMREAD_GRAYSCALE) #get semantic label map
|
81 |
+
im_id_col = np.zeros((im_id_map.shape[0], im_id_map.shape[1], 3), np.uint8)
|
82 |
+
for c in range(3):
|
83 |
+
im_id_col[:,:,c] = lut_bgr[c][im_id_map] #apply color coding
|
84 |
+
|
85 |
+
#plt.imshow(im_id_col)
|
86 |
+
#plt.show()
|
87 |
+
|
88 |
+
blend_sources = (im_jpg*blend_vals[0]+im_id_col*blend_vals[1]+im_json*blend_vals[2]).astype(np.uint8)
|
89 |
+
return (blend_sources) #blend all three data sources
|
90 |
+
|
91 |
+
def vis_all_json(json_folder, jpg_folder, uint8_folder, inp_path_config_json):
|
92 |
+
all_json = files_in_subdirs(json_folder, pattern = ["*.json"])
|
93 |
+
lut_bgr = config_to_rgb(inp_path_config_json, default_col = [255,255,255])[::-1] #we need to swap color channels as opencv uses BGR
|
94 |
+
curr_idx, retKey = 0, ord('a')
|
95 |
+
while retKey > ord(' '):
|
96 |
+
im_vis = get_joined_img(all_json[curr_idx], jpg_folder, uint8_folder, lut_bgr)
|
97 |
+
cv2.putText(im_vis, all_json[curr_idx],(0,25), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0,0,255), 2)
|
98 |
+
cv2.imshow("RailSem19 Annotation Visualization (use 'a' or 'd' to navigate, ESC to quit)",im_vis)
|
99 |
+
retKey = cv2.waitKey(-1) #use 'a' and 'd' to scroll through frames
|
100 |
+
curr_idx = curr_idx - 1 if retKey == ord('a') else curr_idx + 1
|
101 |
+
curr_idx = (curr_idx + len(all_json)) % len(all_json) #wrap around
|
102 |
+
return 0
|
103 |
+
|
104 |
+
def main(argv=sys.argv[1:]):
|
105 |
+
parser = argparse.ArgumentParser()
|
106 |
+
parser.add_argument('--jpgs', type=str, default="RailNet_DT/rs19_val/jpgs/rs19_val",
|
107 |
+
help="Folder containing all RGB intensity images")
|
108 |
+
parser.add_argument('--jsons', type=str, default="RailNet_DT/rs19_val/jsons/rs19_val",
|
109 |
+
help="Folder containing all geometry-based annotation files")
|
110 |
+
parser.add_argument('--uint8', type=str, default="RailNet_DT/rs19_val/uint8/rs19_val",
|
111 |
+
help="Folder containing all dense semantic segm. id maps")
|
112 |
+
parser.add_argument('--config', type=str, default="RailNet_DT/rs19_val/rs19-config.json",
|
113 |
+
help="Path to config json for dense label map interpretation")
|
114 |
+
args = parser.parse_args(argv)
|
115 |
+
return vis_all_json(args.jsons, args.jpgs, args.uint8, args.config)
|
116 |
+
|
117 |
+
if __name__ == "__main__":
|
118 |
+
sys.exit(main())
|
metrics_filtered_cls.py
ADDED
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
from sklearn.metrics import average_precision_score
|
3 |
+
from skimage import morphology
|
4 |
+
|
5 |
+
|
6 |
+
def image_morpho(mask_prediction):
|
7 |
+
selem2 = morphology.disk(2)
|
8 |
+
closed = morphology.closing(mask_prediction, selem2)
|
9 |
+
|
10 |
+
return closed
|
11 |
+
|
12 |
+
def remap_mask(mask1, mask2): # not used
|
13 |
+
classes_mask1 = np.unique(mask1)
|
14 |
+
classes_mask2 = np.unique(mask2)
|
15 |
+
|
16 |
+
# mapping between class indices in mask2 to mask1
|
17 |
+
class_mapping = {}
|
18 |
+
for class1 in classes_mask1:
|
19 |
+
intersection = list()
|
20 |
+
for class2 in classes_mask2:
|
21 |
+
intersection.append((np.sum((mask1 == class1) & (mask2 == class2)), class1, class2))
|
22 |
+
|
23 |
+
most_sim_cls = max(intersection, key=lambda x: x[0])
|
24 |
+
class_mapping[class1] = most_sim_cls[2]
|
25 |
+
|
26 |
+
# remapping the prediction mask
|
27 |
+
for class_old, class_new in class_mapping.items():
|
28 |
+
mask2[mask2==class_new] = class_old
|
29 |
+
|
30 |
+
return mask1, mask2
|
31 |
+
|
32 |
+
def compute_ap_for_cls(gt_mask, pred_mask, cls_id):
|
33 |
+
# flatten to binary
|
34 |
+
gt_flat = (gt_mask.flatten() == cls_id).astype(int)
|
35 |
+
pred_flat = (pred_mask.flatten() == cls_id).astype(int)
|
36 |
+
|
37 |
+
#if there is no occurences return 0 for the class
|
38 |
+
if np.sum(gt_flat) == 0:
|
39 |
+
return 0
|
40 |
+
else:
|
41 |
+
ap = average_precision_score(gt_flat, pred_flat)
|
42 |
+
return ap
|
43 |
+
|
44 |
+
def compute_map_cls(gt_mask, pred_mask, classes_ap, major = False, treshold=150):
|
45 |
+
|
46 |
+
if major: # compute mAP just from the major classes in the image (more than 150 pixels in each mask)
|
47 |
+
classes = get_major_classes(gt_mask, pred_mask, treshold)
|
48 |
+
else:
|
49 |
+
classes = np.unique(np.concatenate((np.unique(gt_mask),np.unique(pred_mask))))
|
50 |
+
classes = classes[np.isin(classes, np.unique(gt_mask)) & np.isin(classes, np.unique(pred_mask))]
|
51 |
+
|
52 |
+
if np.all(classes==12):
|
53 |
+
return 0, classes_ap
|
54 |
+
|
55 |
+
# compute the AP for individual classes
|
56 |
+
ap_values = []
|
57 |
+
dict_ap_values = {}
|
58 |
+
for class_index in classes:
|
59 |
+
if class_index != 12: # exclude background class 12
|
60 |
+
ap = compute_ap_for_cls(gt_mask, pred_mask, class_index)
|
61 |
+
ap_values.append(ap) # save for per picture evaluation
|
62 |
+
dict_ap_values[class_index] = ap # save for per class evaluation
|
63 |
+
|
64 |
+
# add the values for the per class evaluation
|
65 |
+
for cls, value in dict_ap_values.items():
|
66 |
+
if cls not in classes_ap:
|
67 |
+
classes_ap[cls] = [value,1]
|
68 |
+
else:
|
69 |
+
classes_ap[cls] = np.add(classes_ap[cls], [value,1])
|
70 |
+
|
71 |
+
return np.mean(ap_values), classes_ap
|
72 |
+
|
73 |
+
|
74 |
+
def get_major_classes(gt_mask,pred_mask,treshold):
|
75 |
+
classes = np.unique(np.concatenate((np.unique(gt_mask),np.unique(pred_mask))))
|
76 |
+
|
77 |
+
occurrences1 = {num: np.count_nonzero(gt_mask == num) for num in np.unique(gt_mask)}
|
78 |
+
occurrences2 = {num: np.count_nonzero(pred_mask == num) for num in np.unique(pred_mask)}
|
79 |
+
|
80 |
+
classes = classes[[i for i, key in enumerate(classes) if occurrences1.get(key, 0) > treshold and occurrences2.get(key, 0) > treshold]]
|
81 |
+
|
82 |
+
return classes
|
83 |
+
|
84 |
+
def compute_IoU(gt_mask, pred_mask, classes_stats, major=False, treshold=144):
|
85 |
+
if major: # compute mAP just from the major classes in the image (more than 144 pixels in each mask)
|
86 |
+
classes = get_major_classes(gt_mask, pred_mask, treshold)
|
87 |
+
else:
|
88 |
+
classes = np.unique(np.concatenate((np.unique(gt_mask),np.unique(pred_mask))))
|
89 |
+
classes = classes[np.isin(classes, np.unique(gt_mask)) & np.isin(classes, np.unique(pred_mask))]
|
90 |
+
|
91 |
+
if np.all(classes==12):
|
92 |
+
return(0, 0, 0, 0, classes_stats)
|
93 |
+
|
94 |
+
stats_image = {}
|
95 |
+
|
96 |
+
for cls in classes:
|
97 |
+
if cls != 12: # excluding background
|
98 |
+
|
99 |
+
intersection = np.sum((gt_mask == cls) & (pred_mask == cls))
|
100 |
+
union = np.sum((gt_mask == cls) | (pred_mask == cls))
|
101 |
+
IoU = intersection / union
|
102 |
+
|
103 |
+
tp = np.sum((gt_mask == cls) & (pred_mask == cls))
|
104 |
+
tn = np.sum((gt_mask != cls) & (pred_mask != cls))
|
105 |
+
fp = np.sum((gt_mask != cls) & (pred_mask == cls))
|
106 |
+
fn = np.sum((gt_mask == cls) & (pred_mask != cls))
|
107 |
+
|
108 |
+
acc = (tp+tn)/(tp+tn+fp+fn)
|
109 |
+
if tp != 0:
|
110 |
+
precision = tp/(tp+fp)
|
111 |
+
recall = tp/(tp+fn)
|
112 |
+
else:
|
113 |
+
precision = 0
|
114 |
+
recall = 0
|
115 |
+
|
116 |
+
stats_image[cls] = [IoU,acc,precision,recall]
|
117 |
+
|
118 |
+
for cls, value in stats_image.items():
|
119 |
+
if cls not in classes_stats:
|
120 |
+
classes_stats[cls] = [value,1]
|
121 |
+
else:
|
122 |
+
classes_stats[cls][0] = np.add(classes_stats[cls][0], value)
|
123 |
+
classes_stats[cls][1] = np.add(classes_stats[cls][1], 1)
|
124 |
+
|
125 |
+
stats = list(stats_image.values())
|
126 |
+
stats = np.array(stats).reshape(-1, len(stats[0]))
|
127 |
+
|
128 |
+
IoU_img = np.mean(stats[:,0])
|
129 |
+
acc_img = np.mean(stats[:,1])
|
130 |
+
precision_img = np.mean(stats[:,2])
|
131 |
+
recall_img = np.mean(stats[:,3])
|
132 |
+
|
133 |
+
return(IoU_img, acc_img, precision_img, recall_img, classes_stats)
|
yolov8s.pt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:268e5bb54c640c96c3510224833bc2eeacab4135c6deb41502156e39986b562d
|
3 |
+
size 22573363
|