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): # settings args = EasyArgs(sysargs) cfg = EasyConfig(args.config, group="trainer") max_clicks = args.clicks or cfg.default_clicks window_name = "EagleEye Trainer" 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 elif len(args) > 3: ret, mark_in, mark_out = marker_tool(args[1], cfg.buffer_size, window_name) if not ret: print "Not processing - exiting." return 1 else: usage() return 1 ## clicking time! cropped_total = mark_out - mark_in print "video cropped at:", mark_in, "to", mark_out, "- ({} frames)".format( cropped_total) # clicking function def on_mouse(event, x, y, flags, params): # left click to mark if event == cv2.EVENT_LBUTTONDOWN: params['pos'] = (x, y) params['status'] = Status.record # right click to skip elif event == cv2.EVENT_RBUTTONDOWN: params['status'] = Status.skip # working variables params = {'status': Status.wait, 'pos': None} write_xml = False textstatus = "" dataQuality = 0 # 0 = good, >0 = bad/potentially bad # default right side (buttonside) if cfg.dual_mode: lens = Theta.Right trainer_points = {Theta.Right: {}, Theta.Left: {}} else: # both sides otherwise lens = Theta.Both trainer_points = {Theta.Both: {}} print "Minimum reflectors: {} | Ignore Negative xyz: {}".format( cfg.min_reflectors, cfg.check_negatives) # load video (again) in_vid = BuffSplitCap(args[1], crop=(0, 0, 0, 0), rotate=BuffSplitCap.r0, buff_max=cfg.buffer_size) in_vid.restrict(mark_in, mark_out) # load csv (with appropriate ratio) in_csv = Memset(args[2]) in_csv.restrict() in_csv.setRatio(cropped_total) # test for marker data if len(in_csv.row()) < 10: print "This CSV contains no marker data!\nAborting." return 1 # status print "" print "Writing to:", args[3] print "Number of clicks at:", max_clicks print "" cv2.namedWindow(window_name) cv2.setMouseCallback(window_name, on_mouse, params) # grab clicks (Process 2) while in_vid.isOpened(): frame = in_vid.frame(side=lens) sys.stdout.write(in_vid.status() + " | Clicks {} / {}\r".format( len(trainer_points[lens]), max_clicks)) sys.stdout.flush() # prepare CSV data, click data tx = float(in_csv.row()[2]) ty = float(in_csv.row()[3]) tz = float(in_csv.row()[4]) rx = float(in_csv.row()[5]) ry = float(in_csv.row()[6]) rz = float(in_csv.row()[7]) # data quality status visible = int(in_csv.row()[9]) max_visible = int(in_csv.row()[8]) # status text to write textrow = "VICON - x: {:.4f} y: {:.4f} z: {:.4f} | rx: {:.4f} ry: {:.4f} rz: {:.4f}".format( tx, ty, tz, rx, ry, rz) textquality = "Visible: {} , Max Visible: {}".format( visible, max_visible) textstatus = "{} | {}/{} clicks".format(in_vid.status(), len(trainer_points[lens]), max_clicks) if lens == Theta.Left: textstatus += " - back side" elif lens == Theta.Right: textstatus += " - button side" #else none, no lens split # if data is qualified bad, reduce timeout by one if dataQuality > 0: dataQuality -= 1 if dataQuality == 0: dataStatus = " - Good data!!" dataStatus_colour = (0, 255, 0) # green else: dataStatus = " - Potentially bad data (wait {})".format( dataQuality) dataStatus_colour = (0, 255, 255) # yellow # Data tests # values must be above 0 and minimum reflectors if (cfg.check_negatives and (tx <= 0 or ty <= 0 or tz <= 0)) \ or visible < cfg.min_reflectors: dataStatus = " - Bad data!!" dataStatus_colour = (0, 0, 255) # red if cfg.ignore_baddata: dataStatus += " Ignored." dataQuality = 1 + cfg.quality_delay # draw the trainer dot (if applicable) if in_vid.at() in trainer_points[lens]: cv2.circle(frame, trainer_points[lens][in_vid.at()][0], 1, cfg.dot_colour, 2) cv2.circle(frame, trainer_points[lens][in_vid.at()][0], 15, cfg.dot_colour, 1) # draw text and show displayText(frame, textrow, top=True) displayText(frame, textquality) displayText(frame, textstatus) displayText(frame, dataStatus, endl=True, colour=dataStatus_colour) cv2.imshow(window_name, frame) # pause for input while params['status'] == Status.wait: key = cv2.waitKey(10) if key == Key.esc: params['status'] = Status.stop elif key == Key.enter: write_xml = True params['status'] = Status.stop elif key == Key.right: params['status'] = Status.skip elif key == Key.left: params['status'] = Status.back elif key == Key.backspace: params['status'] = Status.remove elif Key.char(key, '1') and cfg.dual_mode: params['status'] = Status.still lens = Theta.Left elif Key.char(key, '2') and cfg.dual_mode: params['status'] = Status.still lens = Theta.Right # catch exit status if params['status'] == Status.stop: print "\nprocess aborted!" break # write data if params['status'] == Status.record \ and len(trainer_points[lens]) != max_clicks: # TODO: does this disable recording clicks on the last frame if dataQuality == 0: trainer_points[lens][in_vid.at()] = (params['pos'], in_csv.row()[2:5], in_csv.row()[8:10]) params['status'] = Status.skip # or remove it elif params['status'] == Status.remove \ and in_vid.at() in trainer_points[lens]: del trainer_points[lens][in_vid.at()] print "\nremoved dot" # load next csv frame if params['status'] == Status.skip: if in_vid.next(): in_csv.next() else: write_xml = True print "\nend of video: {}/{}".format(in_vid.at() - 1, mark_out - 1) break # or load previous csv frame elif params['status'] == Status.back: if in_vid.back(): in_csv.back() # reset status params['status'] = Status.wait # clean up cv2.destroyAllWindows() ## write xml if write_xml: out_xml = XMLWriter(args[3]) out_xml.declaration() doc = out_xml.start("TrainingSet") # source information out_xml.start("video", mark_in=str(mark_in), mark_out=str(mark_out)) out_xml.data(os.path.basename(args[1])) out_xml.end() out_xml.element("csv", os.path.basename(args[2])) # training point data for lens in trainer_points: if lens == Theta.Right: out_xml.start("buttonside", points=str(len(trainer_points[lens]))) elif lens == Theta.Left: out_xml.start("backside", points=str(len(trainer_points[lens]))) else: # non dualmode out_xml.start("frames", points=str(len(trainer_points[lens]))) for i in trainer_points[lens]: pos, row, markers = trainer_points[lens][i] x, y = pos out_xml.start("frame", num=str(i)) out_xml.element("plane", x=str(x), y=str(y)) out_xml.element("vicon", x=str(row[0]), y=str(row[1]), z=str(row[2])) out_xml.element("visibility", visibleMax=str(markers[0]), visible=str(markers[1])) out_xml.end() out_xml.end() # frames # clean up out_xml.close(doc) print "Data was written." else: print "No data was written" print "\nDone." return 0
def main(sysargs): args = EasyArgs(sysargs) cfg = EasyConfig(args.cfg, group="compare") 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 # open video files vid = BuffSplitCap(args[1], buff_max=cfg.buffer_size) xml1 = Xmlset(args[2]) xml2 = Xmlset(args[3]) # trim the video vid.restrict(mark_in, mark_out) # trim the CSV cropped_total = mark_out - mark_in xml1.setRatio(cropped_total) xml2.setRatio(cropped_total ) # should be 1.0 (total frames should be the same as video) print 'xml1 ratio:', xml1.ratio() print 'xml2 ratio:', xml2.ratio() # open export (if specified) if 'export' in args: 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.export, cv2.VideoWriter_fourcc(*cfg.fourcc), in_fps, in_size) else: cv2.namedWindow(window_name) while vid.isOpened(): sys.stdout.write(vid.status() + "\r") sys.stdout.flush() frame = vid.frame() # draw objects from each dataset for name in xml1.data(): draw(frame, xml1.data()[name], cfg.xml1_colour) for name in xml2.data(): draw(frame, xml2.data()[name], cfg.xml2_colour) # print status to screen displayText(frame, vid.status(), top=True) displayText(frame, "{}: {}".format(os.path.basename(args[2]), xml1.status()), colour=cfg.xml1_colour) displayText(frame, "{}: {}".format(os.path.basename(args[3]), xml2.status()), colour=cfg.xml2_colour) # export or navigate if 'export' in args: sys.stdout.write("{}/{}\r".format(vid.at(), cropped_total)) sys.stdout.flush() out_vid.write(frame) if vid.next(): xml1.next() xml2.next() else: print "\nend of video" break else: cv2.imshow(window_name, frame) key = cv2.waitKey(0) # controls if key == Key.esc: print "\nexiting." break elif key == Key.right: if vid.next(): xml1.next() xml2.next() elif key == Key.left: if vid.back(): xml1.back() xml2.back() # clean up vid.release() if 'export' in args: out_vid.release() else: cv2.destroyAllWindows() 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