Spaces:
Running
Running
# Copyright Oliver Zendel, AIT Austrian Institute of Technology Gmbh 2019 | |
# Example visualization tool to illustrate interpretation of RailSem19 data usage | |
import sys, os, glob, math, argparse | |
import numpy as np | |
import cv2, json | |
import matplotlib.pyplot as plt | |
rs19_label2bgr = {"buffer-stop": (70,70,70), | |
"crossing": (128,64,128), | |
"guard-rail": (0,255,0), | |
"train-car" : (100,80,0), | |
"platform" : (232,35,244), | |
"rail": (255,255,0), | |
"switch-indicator": (127,255,0), | |
"switch-left": (255,255,0), | |
"switch-right": (127,127,0), | |
"switch-unknown": (191,191,0), | |
"switch-static": (0,255,127), | |
"track-sign-front" : (0,220,220), | |
"track-signal-front" : (30,170,250), | |
"track-signal-back" : (0,85,125), | |
#rail occluders | |
"person-group" : (60,20,220), | |
"car" : (142,0,0), | |
"fence" : (153,153,190), | |
"person" : (60,20,220), | |
"pole" : (153,153,153), | |
"rail-occluder" : (255,255,255), | |
"truck" : (70,0,0) | |
} | |
def files_in_subdirs(start_dir, pattern = ["*.png","*.jpg","*.jpeg"]): | |
files = [] | |
for p in pattern: | |
for dir,_,_ in os.walk(start_dir): | |
files.extend(glob.glob(os.path.join(dir,p))) | |
return files | |
def config_to_rgb(inp_path_config_json, default_col = [255,255,255]): | |
lut = [] | |
inp_json = json.load(open(inp_path_config_json, 'r')) | |
for c in range(3): #for each color channel | |
lut_c =[l["color"][c] for l in inp_json["labels"]]+[default_col[c]]*(256-len(inp_json["labels"])) | |
lut.append(np.asarray(lut_c, dtype=np.uint8)) | |
return lut | |
def corss_hatch_rail(im_vis, coords, color_left=(255,255,0), color_right=(127,127,0)): | |
ml = min(len(coords[0]), len(coords[1])) | |
for i in range(ml): | |
midpnt = ((coords[0][i][0]+coords[1][i][0])//2, (coords[0][i][1]+coords[1][i][1])//2) | |
cv2.line(im_vis, tuple(coords[0][i]), midpnt, color_left) | |
cv2.line(im_vis, midpnt, tuple(coords[1][i]), color_right) | |
def json_to_img(inp_path_json, line_thickness=2): | |
inp_json = json.load(open(inp_path_json, 'r')) | |
im_json = np.zeros((inp_json["imgHeight"], inp_json["imgWidth"],3), dtype=np.uint8) | |
for obj in inp_json["objects"]: | |
col = rs19_label2bgr.get(obj["label"],[255,255,255]) | |
if "boundingbox" in obj: | |
cv2.rectangle(im_json, tuple(obj["boundingbox"][0:2]), tuple(obj["boundingbox"][2:4]), col, line_thickness) | |
elif "polygon" in obj: | |
pnts_draw = np.around(np.array(obj["polygon"])).astype(np.int32) | |
cv2.polylines(im_json, [pnts_draw], True, col, line_thickness) | |
elif "polyline-pair" in obj: | |
#left rail of a rail pair has index 0, right rail of a rail pair has index 1 | |
rails_draw = [np.around(np.array(obj["polyline-pair"][i])).astype(np.int32) for i in range(2)] | |
corss_hatch_rail(im_json, obj["polyline-pair"], rs19_label2bgr['switch-left'], rs19_label2bgr['switch-right']) | |
cv2.polylines(im_json, rails_draw, False, col) | |
elif "polyline" in obj: | |
rail_draw = np.around(np.array(obj["polyline"])).astype(np.int32) | |
cv2.polylines(im_json, [rail_draw], False, col, line_thickness) | |
return im_json, inp_json["frame"] | |
def get_joined_img(inp_path_json, jpg_folder, uint8_folder, lut_bgr, blend_vals=[0.65,0.25,0.1]): | |
im_json, frameid = json_to_img(inp_path_json, line_thickness=2) #visualize geometric annotations | |
inp_path_jpg = os.path.join(jpg_folder,frameid+".jpg") | |
inp_path_uint8 = os.path.join(uint8_folder,frameid+".png") | |
im_jpg = cv2.imread(inp_path_jpg) #add intensity image as background | |
im_id_map = cv2.imread(inp_path_uint8,cv2.IMREAD_GRAYSCALE) #get semantic label map | |
im_id_col = np.zeros((im_id_map.shape[0], im_id_map.shape[1], 3), np.uint8) | |
for c in range(3): | |
im_id_col[:,:,c] = lut_bgr[c][im_id_map] #apply color coding | |
#plt.imshow(im_id_col) | |
#plt.show() | |
blend_sources = (im_jpg*blend_vals[0]+im_id_col*blend_vals[1]+im_json*blend_vals[2]).astype(np.uint8) | |
return (blend_sources) #blend all three data sources | |
def vis_all_json(json_folder, jpg_folder, uint8_folder, inp_path_config_json): | |
all_json = files_in_subdirs(json_folder, pattern = ["*.json"]) | |
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 | |
curr_idx, retKey = 0, ord('a') | |
while retKey > ord(' '): | |
im_vis = get_joined_img(all_json[curr_idx], jpg_folder, uint8_folder, lut_bgr) | |
cv2.putText(im_vis, all_json[curr_idx],(0,25), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0,0,255), 2) | |
cv2.imshow("RailSem19 Annotation Visualization (use 'a' or 'd' to navigate, ESC to quit)",im_vis) | |
retKey = cv2.waitKey(-1) #use 'a' and 'd' to scroll through frames | |
curr_idx = curr_idx - 1 if retKey == ord('a') else curr_idx + 1 | |
curr_idx = (curr_idx + len(all_json)) % len(all_json) #wrap around | |
return 0 | |
def main(argv=sys.argv[1:]): | |
parser = argparse.ArgumentParser() | |
parser.add_argument('--jpgs', type=str, default="RailNet_DT/rs19_val/jpgs/rs19_val", | |
help="Folder containing all RGB intensity images") | |
parser.add_argument('--jsons', type=str, default="RailNet_DT/rs19_val/jsons/rs19_val", | |
help="Folder containing all geometry-based annotation files") | |
parser.add_argument('--uint8', type=str, default="RailNet_DT/rs19_val/uint8/rs19_val", | |
help="Folder containing all dense semantic segm. id maps") | |
parser.add_argument('--config', type=str, default="RailNet_DT/rs19_val/rs19-config.json", | |
help="Path to config json for dense label map interpretation") | |
args = parser.parse_args(argv) | |
return vis_all_json(args.jsons, args.jpgs, args.uint8, args.config) | |
if __name__ == "__main__": | |
sys.exit(main()) | |