oValach commited on
Commit
6af76da
1 Parent(s): d2eab27

Initial commit #2

Browse files
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