def main(sysargs): args = EasyArgs(sysargs) cfg = EasyConfig(args.config, group="chessboard_extract") if "help" in args: usage() return 0 # test args if len(args) <= 2: usage() return 1 # video settings, etc window_name = "Chessboard Extractor" side = Theta.resolve(args.split) rotate = BuffSplitCap.r0 crop = (0, 0, 0, 0) font = cv2.FONT_HERSHEY_SIMPLEX # image stuff image_path = os.path.join(args[2], args.prefix or 'frame_') if not os.path.exists(args[2]): os.makedirs(args[2]) cv2.namedWindow(window_name) cap = BuffSplitCap(args[1], side=side, rotate=rotate, crop=crop, buff_max=cfg.buffer_size) # loop video file while cap.isOpened(): frame = cap.frame() # display status textframe = frame.copy() displayText(textframe, cap.status(), top=True) cv2.imshow(window_name, textframe) # controls key = cv2.waitKey(0) if key == Key.right: cap.next() elif key == Key.left: cap.back() elif key == Key.enter: print "Snapped at: ", cap.at() cv2.imwrite("{}{:02d}.jpg".format(image_path, cap.at()), frame) elif key == Key.esc: print "Quitting." break # clean up cap.release() cv2.destroyAllWindows() print "\nDone." return 0
def main(sysargs): args = EasyArgs(sysargs) cfg = EasyConfig(args.config, group="chessboard_extract") if "help" in args: usage() return 0 # test args if len(args) <= 2: usage() return 1 # video settings, etc window_name = "Chessboard Extractor" side = Theta.resolve(args.split) rotate = BuffSplitCap.r0 crop = (0,0,0,0) font = cv2.FONT_HERSHEY_SIMPLEX # image stuff image_path = os.path.join(args[2], args.prefix or 'frame_') if not os.path.exists(args[2]): os.makedirs(args[2]) cv2.namedWindow(window_name) cap = BuffSplitCap(args[1], side=side, rotate=rotate, crop=crop, buff_max=cfg.buffer_size) # loop video file while cap.isOpened(): frame = cap.frame() # display status textframe = frame.copy() displayText(textframe, cap.status(), top=True) cv2.imshow(window_name, textframe) # controls key = cv2.waitKey(0) if key == Key.right: cap.next() elif key == Key.left: cap.back() elif key == Key.enter: print "Snapped at: ", cap.at() cv2.imwrite("{}{:02d}.jpg".format(image_path, cap.at()), frame) elif key == Key.esc: print "Quitting." break # clean up cap.release() cv2.destroyAllWindows() print "\nDone." return 0
def writeCSV(frames, path): with open(path, "wb") as csvFile: c = csv.writer(csvFile) for f in frames.keys(): for key in frames[f]: c.writerow([f, # frame number frames[f][key]["map_x"], # mapped centroid x frames[f][key]["map_y"], # mapped centroid y frames[f][key]["ann_x"], # annotated centroid x frames[f][key]["ann_y"], # annotated centroid y Theta.name(frames[f][key]["lens"]), # lens - {buttonside, backside, both} frames[f][key]["err"]]) # reprojection error
def writeXML(frames, path, args): out_xml = XMLWriter(path) out_xml.declaration() doc = out_xml.start("AnnotationEvaluation") # source information out_xml.element("video", mark_in=str(args[4]), mark_out=str(args[5])) out_xml.element("mapper", os.path.basename(args[1])) out_xml.element("annotation", os.path.basename(args[2])) out_xml.element("comparison", mean_err=str(calMean(frames))) # compared points out_xml.start("frames", total=str((args[5]-1) - (args[4]+1)+1), compared=str(len(frames))) for f in frames.keys(): out_xml.start("frame", num=str(f)) for key in frames[f]: out_xml.start("object", lens=Theta.name(frames[f][key]["lens"]), name=key, err=str(frames[f][key]["err"])) out_xml.element("annotatedCentroid", x=str(frames[f][key]["ann_x"]), y=str(frames[f][key]["ann_y"])) out_xml.element("mappedCentroid", x=str(frames[f][key]["map_x"]), y=str(frames[f][key]["map_y"])) out_xml.end() # object out_xml.end() # frames # clean up out_xml.close(doc)
def main(sysargs): args = EasyArgs(sysargs) cfg = EasyConfig(args.config, group="mapper") if "help" in args: usage() return 0 if ["calib", "trainer", "output"] not in args: print "Must specify: -calib, -trainer, -output files" usage() return 1 if len(args) == 1: print "Not enough input CSV files" usage() return 1 if len(args) > 2 and args.map_trainer_mode: print "Too many CSV for trainer-mapping mode" usage() return 1 if "force_side" in args: side = Theta.resolve(args.force_side) if side == Theta.NonDual: print "Invalid force_side argument:", args.force_side usage() return 1 # set side overrides force_button = (side == Theta.Buttonside) force_back = not force_button else: force_button = force_back = False # working vars csvs = {} frame_num = 0 # open source CSV datasets for i in range(1, len(args)): print args[i] csvs[i] = Memset(args[i]) # reel all the files up to their first flash for i in csvs: csvs[i].restrict() if len(csvs[i].row()) < 10: print "CSV file:", args[i], "contains no marker data!\nAborting." return 1 # override csv name if args.map_trainer_mode: csvs[1]._name = cfg.trainer_target # open calib files try: buttonside = Mapper(args.calib, args.trainer, cfg, Theta.Buttonside) backside = Mapper(args.calib, args.trainer, cfg, Theta.Backside) except Exception as e: print e.message return 1 count = {'bts': 0, 'bks': 0, 'rej': 0} # open destination XML with open(args.output, "w") as xmlfile: w = XMLWriter(xmlfile) w.declaration() xmlfile.write( "<!DOCTYPE dataset SYSTEM \"http://storage.gwillz.com.au/eagleeye_v2.dtd\">" ) doc = w.start("dataset") # iterates until all vicon csvs reach eof while True: w.start("frameInformation") w.element("frame", number=str(frame_num)) #iterates through each vicon csv at the current row for i in csvs: c = csvs[i] # determine marker quality try: max_reflectors = int(c.row()[8]) visible_reflectors = int(c.row()[9]) except: print "Error in reading quality at row {}".format(i) return 1 try: # read VICON data x = float(c.row()[2]) y = float(c.row()[3]) z = float(c.row()[4]) # TODO: is this necessary? We never use the object's rotation rx = float(c.row()[5]) ry = float(c.row()[6]) rz = float(c.row()[7]) except: print "Error occurred when converting VICON data at row {}".format( i) return 1 # run projection/mapping on VICON data if backside.isVisible((x, y, z)): points = backside.reprojpts((x, y, z)) side = 'backside' count['bks'] += 1 elif buttonside.isVisible((x, y, z)): points = buttonside.reprojpts((x, y, z)) points[ 0] += 960 # add 960 to x for rightside points (Ricoh video is both frames side by side) side = 'buttonside' count['bts'] += 1 # TODO don't write non visible dots? else: points = [0., 0.] count['rej'] += 1 # TODO: Change DTD and double check with Manjung w.start("object", id=str(i), name=c.name(), lens=Theta.name(side)) w.element("boxinfo", height="99", width="99", x=str(points[0] - 50), y=str(points[1] - 50)) w.element("centroid", x=str(points[0]), y=str(points[1]), rx=str(rx), ry=str(ry), rz=str(rz)) w.element("visibility", visible=str(visible_reflectors), visibleMax=str(max_reflectors)) w.end() w.end() # test end of files eofs = 0 for i in csvs: if csvs[i].eof(): eofs += 1 if len(csvs) == eofs: print "end of all datasets" break # load next vicon frame frame_num += 1 for i in csvs: csvs[i].next() w.close(doc) print "\nbuttonside", count['bts'] print "backside", count['bks'] print "rejected", count['rej'] return 0
def main(sysargs): args = EasyArgs(sysargs) global scale, img_h if 'help' in args: usage() return 0 # arg sanity checks if len(args) < 3: usage() return 1 # default args height = args.height or 3000 # milimetres width = args.width or 8000 # milimetres max_height = args.max_height or 400 # pixels cfg = EasyConfig(args.config, group="mapper") # working vars scale = float(max_height) / height img_h = int(height * scale) img_w = int(width * scale) # open window window_name = "Tracer" cv2.namedWindow(window_name) # settings font = cv2.FONT_HERSHEY_SIMPLEX text_size = 0.5 colour = (255, 255, 255) # a frame to paste the trace on baseframe = np.zeros((img_h, img_w, 3), np.uint8) # load appropriate mappers if not args.singlemode: mappers = [ Mapper(args[1], args[2], cfg, Theta.Buttonside), Mapper(args[1], args[2], cfg, Theta.Backside) ] else: mappers = [Mapper(args[1], args[2], cfg, Theta.NonDual)] for m in mappers: colour = (55 + random.random() * 200, 55 + random.random() * 200, 55 + random.random() * 200) # calculate world camera pos Rt = np.matrix(m.R).T tv = -Rt.dot(np.matrix(m.tv)) dir = unit(cv2.Rodrigues(-Rt)[0]) #dir = unit(-Rt.dot(np.array([[0.], [0.], [1.]]))) unvis = 0 pts = m.obj_pts for i in pts: # draw circle around it if not-visible x, y, z = i p = (int(x * scale), img_h - int(y * scale)) cv2.circle(baseframe, p, 1, colour, 2) # circle the point if not visible if not m.isVisible((x, y, z)): unvis += 1 cv2.circle(baseframe, p, 6, colour, 1) x, y, z = tv pt1 = (int(x * scale), img_h - int(y * scale)) cv2.circle(baseframe, pt1, 1, colour, 2) cv2.circle(baseframe, pt1, 10, colour, 1) # draw direction of lens #draw_arrow(baseframe, tv, dir[0], colour) # and it's FOV #draw_arrow(baseframe, tv, dir.dot(m.half_fov), colour, length=375) #draw_arrow(baseframe, tv, dir.dot(-m.half_fov), colour, length=375) # and some text data stuff displayText(baseframe, "{}: {}, {}, {}".format(Theta.name(m.mode), *tv), colour=colour) displayText(baseframe, " visible: {}/{}".format(len(pts) - unvis, len(pts)), endl=True, colour=colour) # clean up cv2.imshow(window_name, baseframe) cv2.waitKey(0) if args.export: cv2.imwrite(args.export, baseframe) cv2.destroyAllWindows() print "\ndone" return 0
def main(sysargs): args = EasyArgs(sysargs) cfg = EasyConfig(args.cfg, group="compare_trainer") window_name = "EagleEye Comparator" if "help" in args: usage() return 0 # grab marks from args if len(args) > 5: mark_in = args[4] mark_out = args[5] # test integer-ness try: int(mark_in) and int(mark_out) except: usage() return 1 # or grab them from a marker tool elif len(args) > 3: ret, mark_in, mark_out = marker_tool(args[1], 50, window_name) if not ret: print "Not processing - exiting." return 1 else: usage() return 1 # determine sides side = Theta.resolve(args.side or 'buttonside') # open inouts files vid = BuffSplitCap(args[1], buff_max=cfg.buffer_size, side=Theta.Both) mapper_xml = Xmlset(args[2], offset=cfg.offset, offmode=Xmlset.offset_mode(cfg.offset_mode)) trainer_xml = Xmltrainer(args[3], side=side) reprojerror_list = {} # list of reprojection error of all frames lastframe = False # reject mapper_xml if it doesn't contain the trainer_target if cfg.trainer_target not in mapper_xml.data(0): print "Mapping file must contain training target:", cfg.trainer_target print "Target names in mapping file:", mapper_xml.data(0) print "Please specifiy correct target name in config" return 1 # also reject if it's lens data doesn't match the trainer_xml _test_lens = mapper_xml.data(0)[cfg.trainer_target]['lens'] if (_test_lens == Theta.NonDual and side != Theta.NonDual) \ or (side != Theta.NonDual and _test_lens == Theta.NonDual): print "Mapping file doesn't match training file" print "map:", Theta.name(_test_lens), "trainer:", Theta.name(side) return 1 # sync the video and xml vid.restrict(mark_in, mark_out) cropped_total = mark_out - mark_in mapper_xml.setRatio(cropped_total) # status print "ratio at:", mapper_xml.ratio() print "offset by:", cfg.offset, "in", cfg.offset_mode, "mode" print "" # open export (if specified) if args.video_export: in_fps = vid.get(cv2.CAP_PROP_FPS) in_size = (int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)), int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT))) out_vid = cv2.VideoWriter(args.video_export, cv2.VideoWriter_fourcc(*cfg.fourcc), in_fps, vid.shape[:2]) print "exporting to:", args.video_export else: cv2.namedWindow(window_name) print "interactive mode" # main loop while vid.isOpened(): frame = vid.frame() reprojerror_list = compareReproj(frame, vid.at(), mapper_xml, trainer_xml, reprojerror_list, cfg) # export or navigate if args.video_export: sys.stdout.write("Reading Video Frame: {} / {}\r".format(vid.at(), mark_out)) sys.stdout.flush() out_vid.write(frame) if vid.next(): reprojerror_list = compareReproj(frame, vid.at(), mapper_xml, trainer_xml, reprojerror_list, cfg) mapper_xml.next() else: calReprojList(reprojerror_list) print "\nend of video" break else: cv2.imshow(window_name, frame) key = cv2.waitKey(0) showAll = False # toggle to show all training points in one frame # controls if key == Key.esc: print "\nexiting." break elif key == Key.right: if vid.next(): mapper_xml.next() else: if lastframe is False: print "\nEnd of video" calReprojList(reprojerror_list) lastframe = True elif key == Key.left: if vid.back(): mapper_xml.back() elif key == Key.enter: while True: reprojerror_list = compareReproj(frame, vid.at(), mapper_xml, trainer_xml, reprojerror_list, cfg) cv2.imshow(window_name, frame) if vid.next(): mapper_xml.next() frame = vid.frame() # break when over else: break calReprojList(reprojerror_list) print "\nFast forwarded to end of video" if args.compare_export: print "Output to file" writeFile(args.compare_export, reprojerror_list) break elif key == Key.space: ''' TODO: display all training points, may be abandoned problems: frame is not refreshed after imshow if showAll is False: displayTrainPts(frame, mark_in, mark_out, trainer_xml, cfg) # #except: # print "Error in displaying training points. Exiting..." # return 1 # showAll = True else: frame, reprojerror_list = compareReproj(frame, vid.at(), mapper_xml, trainer_xml, reprojerror_list, cfg) showAll = False ''' pass # clean up vid.release() if args.video_export: out_vid.release() else: cv2.destroyAllWindows() return 0
def compareReproj(cvframe, vidframe_no, mapper_xml, trainer_xml, reprojerror_list, cfg): xmlframe_no = mapper_xml.at() sys.stdout.write("Reading Video Frame: {}".format(vidframe_no) + " | XML Frame number: {}\r".format(xmlframe_no)) sys.stdout.flush() mapped_object = mapper_xml.data(xmlframe_no)[cfg.trainer_target] # Prepare Repojected Point pt1 = (int(float(mapped_object['box']['x'])), int(float(mapped_object['box']['y']))) pt2 = (pt1[0] + int(float(mapped_object['box']['width'])), pt1[1] + int(float(mapped_object['box']['height']))) centre = (int(float(mapped_object['centre']['x'])), int(float(mapped_object['centre']['y']))) visible = int(mapped_object['visibility']['visible']) max_visible = int(mapped_object['visibility']['visibleMax']) lens_side = mapped_object['lens'] # Render Reprojected Point cv2.rectangle(cvframe, pt1, pt2, cfg.mapper_colour, 1) cv2.circle(cvframe, centre, 1, cfg.mapper_colour, 2) # Get trainer point if it exists at current frame vicon_txt = "VICON - x: ?, y: ?, z: ?" trainer_txt = "Trained Point: x: ?, y: ?" reprojErr_txt = "Reprojection Error: No Data" if vidframe_no in trainer_xml.data() and lens_side == trainer_xml.side: trainer_frame = trainer_xml.data()[vidframe_no] # fix buttonside trainer points rightside_offset = 960 if trainer_xml.side == Theta.Right else 0 vicon_txt = "VICON - x: {:.4f}, y: {:.4f}, z: {:.4f}".format( float(trainer_frame["vicon"]["x"]), float(trainer_frame["vicon"]["y"]), float(trainer_frame["vicon"]["z"])) trainer_txt = "Trained Point: x: {}, y: {}".format( int(float(trainer_frame["plane"]["x"]) + rightside_offset), int(float(trainer_frame["plane"]["y"]))) # visualise trainer point trainer_pt = (int(float(trainer_frame["plane"]["x"]) + rightside_offset), int(float(trainer_frame["plane"]["y"]))) cv2.circle(cvframe, trainer_pt, 1, cfg.trainer_colour, 2) # Calculate Reprojection Error at this frame # Still display bad data reprojection error but not used in calculation of mean reprojErr = calReprojError(centre, trainer_pt) reprojErr_txt = "Reprojection Error: {} pixels".format(str(reprojErr)) if cfg.ignore_baddata: if visible >= cfg.min_reflectors: reprojerror_list.update({vidframe_no: { "rms": reprojErr, "x1": trainer_pt[0], "y1": trainer_pt[1], "x2": pt1[0], "y2": pt1[1]}}) # Display Object Info frameObj_Txt = "Frame: {} | Trained Object: {} | Comparing: {}".format( vidframe_no, cfg.trainer_target, Theta.name(trainer_xml.side)) reprojCentroid_txt = "Reprojected Centroid - x: {}, y: {}, on: {}".format( centre[0], centre[1], Theta.name(lens_side)) visibility_txt = "Visible: {} , Max Visible: {}".format(visible, max_visible) displayText(cvframe, frameObj_Txt, top=True) displayText(cvframe, reprojCentroid_txt) displayText(cvframe, visibility_txt) dataText = " - Good data!!" dataText_colour = (0, 255, 0) # green if visible < cfg.min_reflectors: # for when there isn't a matching trainer dataText = " - Bad data!!" dataText_colour = (0, 0, 255) # red if cfg.ignore_baddata: dataText += " Ignored." displayText(cvframe, dataText, endl=True, colour=dataText_colour) displayText(cvframe, trainer_txt) displayText(cvframe, vicon_txt) displayText(cvframe, reprojErr_txt) return reprojerror_list
def main(sysargs): args = EasyArgs(sysargs) cfg = EasyConfig(args.config, group="mapper") if "help" in args: usage() return 0 if ["calib", "trainer", "output"] not in args: print "Must specify: -calib, -trainer, -output files" usage() return 1 if len(args) == 1: print "Not enough input CSV files" usage() return 1 if len(args) > 2 and args.map_trainer_mode: print "Too many CSV for trainer-mapping mode" usage() return 1 if "force_side" in args: side = Theta.resolve(args.force_side) if side == Theta.NonDual: print "Invalid force_side argument:", args.force_side usage() return 1 # set side overrides force_button = (side == Theta.Buttonside) force_back = not force_button else: force_button = force_back = False # working vars csvs = {} frame_num = 0 # open source CSV datasets for i in range(1, len(args)): print args[i] csvs[i] = Memset(args[i]) # reel all the files up to their first flash for i in csvs: csvs[i].restrict() if len(csvs[i].row()) < 10: print "CSV file:", args[i], "contains no marker data!\nAborting." return 1 # override csv name if args.map_trainer_mode: csvs[1]._name = cfg.trainer_target # open calib files try: buttonside = Mapper(args.calib, args.trainer, cfg, Theta.Buttonside) backside = Mapper(args.calib, args.trainer, cfg, Theta.Backside) except Exception as e: print e.message return 1 count = {'bts':0, 'bks':0, 'rej':0} # open destination XML with open(args.output, "w") as xmlfile: w = XMLWriter(xmlfile) w.declaration() xmlfile.write("<!DOCTYPE dataset SYSTEM \"http://storage.gwillz.com.au/eagleeye_v2.dtd\">") doc = w.start("dataset") # main loop while True: w.start("frameInformation") w.element("frame", number=str(frame_num)) for i in csvs: c = csvs[i] # determine marker quality try: max_reflectors = int(c.row()[8]) visible_reflectors = int(c.row()[9]) except: print "Error in reading quality at row {}".format(i) return 1 try: # read VICON data x = float(c.row()[2]) y = float(c.row()[3]) z = float(c.row()[4]) # TODO: is this necessary? We never use the object's rotation rx = float(c.row()[5]) ry = float(c.row()[6]) rz = float(c.row()[7]) except: print "Error occurred when converting VICON data at row {}".format(i) return 1 # run projection/mapping on VICON data if backside.isVisible((x,y,z)): points = backside.reprojpts((x, y, z)) side = 'backside' count['bks'] += 1 elif buttonside.isVisible((x,y,z)): points = buttonside.reprojpts((x, y, z)) points[0] += 960 # add 960 to x for rightside points side = 'buttonside' count['bts'] += 1 # TODO don't write non visible dots? else: points = [0.,0.] count['rej'] += 1 # TODO: Change DTD and double check with Manjung w.start("object", id=str(i), name=c.name(), lens=Theta.name(side)) w.element("boxinfo", height="99", width="99", x=str(points[0]-50), y=str(points[1]-50)) w.element("centroid", x=str(points[0]), y=str(points[1]), rx=str(rx), ry=str(ry), rz=str(rz)) w.element("visibility", visible=str(visible_reflectors), visibleMax=str(max_reflectors)) w.end() w.end() # test end of files eofs = 0 for i in csvs: if csvs[i].eof(): eofs += 1 if len(csvs) == eofs: print "end of all datasets" break # load next frame frame_num += 1 for i in csvs: csvs[i].next() w.close(doc) print "\nbuttonside", count['bts'] print "backside", count['bks'] print "rejected", count['rej'] return 0
def main(sysargs): args = EasyArgs(sysargs) cfg = EasyConfig(args.cfg, group="compare_trainer") window_name = "EagleEye Comparator" if "help" in args: usage() return 0 # grab marks from args if len(args) > 5: mark_in = args[4] mark_out = args[5] # test integer-ness try: int(mark_in) and int(mark_out) except: usage() return 1 # or grab them from a marker tool elif len(args) > 3: ret, mark_in, mark_out = marker_tool(args[1], 50, window_name) if not ret: print "Not processing - exiting." return 1 else: usage() return 1 # determine sides side = Theta.resolve(args.side or 'buttonside') # open inouts files vid = BuffSplitCap(args[1], buff_max=cfg.buffer_size, side=Theta.Both) mapper_xml = Xmlset(args[2], offset=cfg.offset, offmode=Xmlset.offset_mode(cfg.offset_mode)) trainer_xml = Xmltrainer(args[3], side=side) reprojerror_list = {} # list of reprojection error of all frames lastframe = False # reject mapper_xml if it doesn't contain the trainer_target if cfg.trainer_target not in mapper_xml.data(0): print "Mapping file must contain training target:", cfg.trainer_target print "Target names in mapping file:", mapper_xml.data(0) print "Please specifiy correct target name in config" return 1 # also reject if it's lens data doesn't match the trainer_xml _test_lens = mapper_xml.data(0)[cfg.trainer_target]['lens'] if (_test_lens == Theta.NonDual and side != Theta.NonDual) \ or (side != Theta.NonDual and _test_lens == Theta.NonDual): print "Mapping file doesn't match training file" print "map:", Theta.name(_test_lens), "trainer:", Theta.name(side) return 1 # sync the video and xml vid.restrict(mark_in, mark_out) cropped_total = mark_out - mark_in mapper_xml.setRatio(cropped_total) # status print "ratio at:", mapper_xml.ratio() print "offset by:", cfg.offset, "in", cfg.offset_mode, "mode" print "" # open export (if specified) if args.video_export: in_fps = vid.get(cv2.CAP_PROP_FPS) in_size = (int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)), int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT))) out_vid = cv2.VideoWriter(args.video_export, cv2.VideoWriter_fourcc(*cfg.fourcc), in_fps, vid.shape[:2]) print "exporting to:", args.video_export else: cv2.namedWindow(window_name) print "interactive mode" # main loop while vid.isOpened(): frame = vid.frame() reprojerror_list = compareReproj(frame, vid.at(), mapper_xml, trainer_xml, reprojerror_list, cfg) # export or navigate if args.video_export: sys.stdout.write("Reading Video Frame: {} / {}\r".format( vid.at(), mark_out)) sys.stdout.flush() out_vid.write(frame) if vid.next(): reprojerror_list = compareReproj(frame, vid.at(), mapper_xml, trainer_xml, reprojerror_list, cfg) mapper_xml.next() else: calReprojList(reprojerror_list) print "\nend of video" break else: cv2.imshow(window_name, frame) key = cv2.waitKey(0) showAll = False # toggle to show all training points in one frame # controls if key == Key.esc: print "\nexiting." break elif key == Key.right: if vid.next(): mapper_xml.next() else: if lastframe is False: print "\nEnd of video" calReprojList(reprojerror_list) lastframe = True elif key == Key.left: if vid.back(): mapper_xml.back() elif key == Key.enter: while True: reprojerror_list = compareReproj(frame, vid.at(), mapper_xml, trainer_xml, reprojerror_list, cfg) cv2.imshow(window_name, frame) if vid.next(): mapper_xml.next() frame = vid.frame() # break when over else: break calReprojList(reprojerror_list) print "\nFast forwarded to end of video" if args.compare_export: print "Output to file" writeFile(args.compare_export, reprojerror_list) break elif key == Key.space: ''' TODO: display all training points, may be abandoned problems: frame is not refreshed after imshow if showAll is False: displayTrainPts(frame, mark_in, mark_out, trainer_xml, cfg) # #except: # print "Error in displaying training points. Exiting..." # return 1 # showAll = True else: frame, reprojerror_list = compareReproj(frame, vid.at(), mapper_xml, trainer_xml, reprojerror_list, cfg) showAll = False ''' pass # clean up vid.release() if args.video_export: out_vid.release() else: cv2.destroyAllWindows() return 0
def compareReproj(cvframe, vidframe_no, mapper_xml, trainer_xml, reprojerror_list, cfg): xmlframe_no = mapper_xml.at() sys.stdout.write("Reading Video Frame: {}".format(vidframe_no) + " | XML Frame number: {}\r".format(xmlframe_no)) sys.stdout.flush() mapped_object = mapper_xml.data(xmlframe_no)[cfg.trainer_target] # Prepare Repojected Point pt1 = (int(float(mapped_object['box']['x'])), int(float(mapped_object['box']['y']))) pt2 = (pt1[0] + int(float(mapped_object['box']['width'])), pt1[1] + int(float(mapped_object['box']['height']))) centre = (int(float(mapped_object['centre']['x'])), int(float(mapped_object['centre']['y']))) visible = int(mapped_object['visibility']['visible']) max_visible = int(mapped_object['visibility']['visibleMax']) lens_side = mapped_object['lens'] # Render Reprojected Point cv2.rectangle(cvframe, pt1, pt2, cfg.mapper_colour, 1) cv2.circle(cvframe, centre, 1, cfg.mapper_colour, 2) # Get trainer point if it exists at current frame vicon_txt = "VICON - x: ?, y: ?, z: ?" trainer_txt = "Trained Point: x: ?, y: ?" reprojErr_txt = "Reprojection Error: No Data" if vidframe_no in trainer_xml.data() and lens_side == trainer_xml.side: trainer_frame = trainer_xml.data()[vidframe_no] # fix buttonside trainer points rightside_offset = 960 if trainer_xml.side == Theta.Right else 0 vicon_txt = "VICON - x: {:.4f}, y: {:.4f}, z: {:.4f}".format( float(trainer_frame["vicon"]["x"]), float(trainer_frame["vicon"]["y"]), float(trainer_frame["vicon"]["z"])) trainer_txt = "Trained Point: x: {}, y: {}".format( int(float(trainer_frame["plane"]["x"]) + rightside_offset), int(float(trainer_frame["plane"]["y"]))) # visualise trainer point trainer_pt = ( int(float(trainer_frame["plane"]["x"]) + rightside_offset), int(float(trainer_frame["plane"]["y"]))) cv2.circle(cvframe, trainer_pt, 1, cfg.trainer_colour, 2) # Calculate Reprojection Error at this frame # Still display bad data reprojection error but not used in calculation of mean reprojErr = calReprojError(centre, trainer_pt) reprojErr_txt = "Reprojection Error: {} pixels".format(str(reprojErr)) if cfg.ignore_baddata: if visible >= cfg.min_reflectors: reprojerror_list.update({ vidframe_no: { "rms": reprojErr, "x1": trainer_pt[0], "y1": trainer_pt[1], "x2": pt1[0], "y2": pt1[1] } }) # Display Object Info frameObj_Txt = "Frame: {} | Trained Object: {} | Comparing: {}".format( vidframe_no, cfg.trainer_target, Theta.name(trainer_xml.side)) reprojCentroid_txt = "Reprojected Centroid - x: {}, y: {}, on: {}".format( centre[0], centre[1], Theta.name(lens_side)) visibility_txt = "Visible: {} , Max Visible: {}".format( visible, max_visible) displayText(cvframe, frameObj_Txt, top=True) displayText(cvframe, reprojCentroid_txt) displayText(cvframe, visibility_txt) dataText = " - Good data!!" dataText_colour = (0, 255, 0) # green if visible < cfg.min_reflectors: # for when there isn't a matching trainer dataText = " - Bad data!!" dataText_colour = (0, 0, 255) # red if cfg.ignore_baddata: dataText += " Ignored." displayText(cvframe, dataText, endl=True, colour=dataText_colour) displayText(cvframe, trainer_txt) displayText(cvframe, vicon_txt) displayText(cvframe, reprojErr_txt) return reprojerror_list
def main(sysargs): args = EasyArgs(sysargs) global scale, img_h if 'help' in args: usage() return 0 # arg sanity checks if len(args) < 3: usage() return 1 # default args height = args.height or 3000 # milimetres width = args.width or 8000 # milimetres max_height = args.max_height or 400 # pixels cfg = EasyConfig(args.config, group="mapper") # working vars scale = float(max_height) / height img_h = int(height * scale) img_w = int(width * scale) # open window window_name = "Tracer" cv2.namedWindow(window_name) # settings font = cv2.FONT_HERSHEY_SIMPLEX text_size = 0.5 colour = (255,255,255) # a frame to paste the trace on baseframe = np.zeros((img_h,img_w,3), np.uint8) # load appropriate mappers if not args.singlemode: mappers = [Mapper(args[1], args[2], cfg, Theta.Buttonside), Mapper(args[1], args[2], cfg, Theta.Backside)] else: mappers = [Mapper(args[1], args[2], cfg, Theta.NonDual)] for m in mappers: colour = (55+random.random()*200, 55+random.random()*200, 55+random.random()*200) # calculate world camera pos Rt = np.matrix(m.R).T tv = -Rt.dot(np.matrix(m.tv)) dir = unit(cv2.Rodrigues(-Rt)[0]) #dir = unit(-Rt.dot(np.array([[0.], [0.], [1.]]))) unvis = 0 pts = m.obj_pts for i in pts: # draw circle around it if not-visible x, y, z = i p = (int(x*scale), img_h-int(y*scale)) cv2.circle(baseframe, p, 1, colour, 2) # circle the point if not visible if not m.isVisible((x,y,z)): unvis += 1 cv2.circle(baseframe, p, 6, colour, 1) x, y, z = tv pt1 = (int(x*scale), img_h-int(y*scale)) cv2.circle(baseframe, pt1, 1, colour, 2) cv2.circle(baseframe, pt1, 10, colour, 1) # draw direction of lens #draw_arrow(baseframe, tv, dir[0], colour) # and it's FOV #draw_arrow(baseframe, tv, dir.dot(m.half_fov), colour, length=375) #draw_arrow(baseframe, tv, dir.dot(-m.half_fov), colour, length=375) # and some text data stuff displayText(baseframe, "{}: {}, {}, {}".format(Theta.name(m.mode), *tv), colour=colour) displayText(baseframe, " visible: {}/{}".format(len(pts)-unvis, len(pts)), endl=True, colour=colour) # clean up cv2.imshow(window_name, baseframe) cv2.waitKey(0) if args.export: cv2.imwrite(args.export, baseframe) cv2.destroyAllWindows() print "\ndone" return 0