def outputState(self, display, frameFactory, trackFactory, timeFactory, notesFactory): if self.db is None: self.db = DBInterface(self.dbPathFn) if self.bDeleteState: self.db.deleteAll() print 'deleting all states...' bProceed = False if self.bBatchState: bProceed = self.checkCriteriaOutput(display, frameFactory, trackFactory, timeFactory, notesFactory) if bProceed: self.batchOutputCounter += 1 if self.bOutputState or bProceed: state = GuiviewState() state.setState(display, frameFactory, trackFactory, timeFactory, notesFactory) s_state = state.save() self.db.insertState(s_state) if not (bProceed): print 'outputting state...'
def test_applyTracker_2(): ''' test applyTracker; roiSelectFunc=None ''' #load data tracker = TrackFactory(on=True) tracker.setAlgoEnum(0) tracker.setInit(ballColor="green") test_data = "applyTracker.db" test_dir = os.path.join(TEST_PARENT_DIR, 'applyTracker') testDB = DBInterface(os.path.join(test_dir, test_data)) listGS = [pickle.loads(record[1]) for record in testDB.selectAll()] #check input data validity assert [_gs.frameCounter for _gs in listGS] == [0, 189, 312] assert tracker.getTrackParams()['thresh_lo'] == (29, 86, 6) assert tracker.getTrackParams()['repair_iterations'] == 1 #test function data = applyTracker(listGS, tracker) #check outcome assert len(data['listPlts']) == 3 assert len(data['listPlts'][0]) == 3 assert data['listPlts'][0][0].shape == (480, 640, 3) assert data['listPlts'][0][1].shape == (480, 640) assert data['listTransformTitles'] == ['img_t', 'img_mask', 'img_repair'] assert data['listFrameTitles'] == ['0', '189', '312'] assert len(data['listScore']) == 3 assert data['listScore'][0]['0']['data'] == [209, 168, 35, 35] assert data['listScore'][1] == None
def test_applyTracker_3(): ''' test applyTracker; roiSelectFunc=roiSelectZoomWindow. test_data has guiview states with a zoomRect ''' #load data tracker = TrackFactory(on=True) tracker.setAlgoEnum(0) tracker.setInit(ballColor="green") test_data = "applyTracker.db" test_dir = os.path.join(TEST_PARENT_DIR, 'applyTracker') testDB = DBInterface(os.path.join(test_dir, test_data)) listGS = [pickle.loads(record[1]) for record in testDB.selectAll()] #check input data validity assert [_gs.frameCounter for _gs in listGS] == [0, 189, 312] #test function data = applyTracker(listGS, tracker, roiSelectZoomWindow) #check outcome assert data['listPlts'][0][0].shape == (68, 66, 3) assert data['listPlts'][0][1].shape == (68, 66) assert data['listPlts'][1][0].shape == (22, 22, 3) assert data['listPlts'][1][1].shape == (22, 22) assert len(data['listScore']) == 3 assert data['listScore'][0]['0']['data'] == [17, 18, 35, 35] assert data['listScore'][1] == None
def setBatchState(self, bBatchState, iEnumBatchCriteria, lBatchIndexList=None, sBatchDbPathFn=""): self.bBatchState = bBatchState self.enumBatchCriteria = iEnumBatchCriteria if lBatchIndexList is not None: self.batchIndexList = copy.copy(lBatchIndexList) if sBatchDbPathFn != "": self.dbPathFn = sBatchDbPathFn if bBatchState: print '\nSTART - running batch output ...' try: if self.db is None: self.db = DBInterface(self.dbPathFn) self.db.deleteAll() self.db = None print '...deleting all exisiting %s records...' % str( self.dbPathFn) except: print 'failed to delete exisitng records'
def test_load_gs_1(): path_test = '''data/test/evalhelpers/EvalDataset_2/''' path_gs = os.path.join('..', path_test, 'input_gs.db') db = DBInterface(path_gs) listGS = [pickle.loads(d[1]) for d in db.selectAll()] #validate frameCounter ANSWER = [0, 1, 5] assert [gs.frameCounter for gs in listGS] == ANSWER #validate frame/origFrame exists assert listGS[0].getOrigFrame().shape == (480, 640, 3) assert listGS[1].getOrigFrame().shape == (480, 640, 3) #validate displayInputScore exists in some/ not in others ANSWER = { u'0': { u'data': [107, 214, 54, 52], u'type': u'circle' }, u'1': { u'data': [111, 218, 46, 44], u'type': u'circle' } } assert cmp(listGS[0].displayInputScore, ANSWER) == 0 assert listGS[1].displayInputScore is None
def test_EvalDataset_buildDataset_2(): # unlike previous test, this listGS has some non-inputframes gs's. path_test = '''data/test/evalhelpers/EvalDataset_2/''' path_gs = os.path.join('..', path_test, 'input_gs.db') path_answer = os.path.join('..', path_test, 'answer_outcome.pickle') #load listGS db = DBInterface(path_gs) listGS = [pickle.loads(d[1]) for d in db.selectAll()] print[_gs.frameCounter for _gs in listGS] # init tracker my_tracker = TrackFactory(on=True) my_tracker.setInit(ballColor="orange") my_tracker.setAlgoEnum(0) # apply method evd = EvalDataset() evd.buildDataset(listGS, my_tracker) output = evd.df.copy() answer = pd.read_pickle(path_answer) # validate try: assert output.equals(answer) except: print diff_pd(output, answer) raise Exception
def test_EvalDataset_buildDataset(): ''' rebenched 2.10.19''' path_test = '''data/test/evalhelpers/EvalDataset/''' path_gs = os.path.join('..', path_test, 'input_gs.db') path_answer = os.path.join('..', path_test, 'answer_outcome.pickle') #load listGS db = DBInterface(path_gs) listGS = [pickle.loads(d[1]) for d in db.selectAll()] print[_gs.frameCounter for _gs in listGS] # init tracker my_tracker = TrackFactory(on=True) my_tracker.setInit(ballColor="orange") my_tracker.setAlgoEnum(0) # apply method evd = EvalDataset() evd.buildDataset(listGS, my_tracker) output = evd.df.copy() # validate answer = pd.read_pickle(path_answer) d_output, d_answer = output.to_dict(), answer.to_dict() assert cmp(d_output, d_answer) == 0
def test_compareTrackers_1(): ''' functionality test for: basic functionality roiSelectWindow bMarkedFrame success calling multiPlot multiplot_params ''' # build listTrackers listTrackers = [] for _algoenum in [0, 1]: _tracker = TrackFactory(on=True) _tracker.setAlgoEnum(_algoenum) _tracker.setInit(ballColor="orange") listTrackers.append(_tracker) # build listGS test_data = "compareTrackers_orange.db" test_dir = os.path.join(TEST_PARENT_DIR, 'compareTrackers') testDB = DBInterface(os.path.join(test_dir, test_data)) listGS = [pickle.loads(record[1]) for record in testDB.selectAll()] # run method with test_mock flag data_dict = compareTrackers(listGS, listTrackers, test_stub=True) # checks print data_dict['row_titles'] assert data_dict['row_titles'] == [ 'marked_frame', 'img_t', 'img_mask', 'img_repair', 'img_terminal' ] assert data_dict['col_titles'] == ['AlgoEnum=0', 'AlgoEnum=1'] assert data_dict['plot_data'][0][1].shape == (480, 640, 3 ) # since roiSelectFunc=None # run 1. without markedFrame at the top, 2. with selectRoiFunc data_dict = compareTrackers(listGS, listTrackers, roiSelectFunc=True, bMarkedFrame=False, test_stub=True) assert data_dict['row_titles'] == [ 'img_t', 'img_mask', 'img_repair', 'img_terminal' ] assert data_dict['plot_data'][0][1].shape != (480, 640, 3) # don't run with test_stub; thus sending data into multiPlot() to see # if any exceptions are thrown. use bSupressDisplay to prevent matplotlib output # from popping-up during the tests compareTrackers(listGS, listTrackers, test_stub=False, multiplot_params={ 'figsize': (20, 20), 'bSupressDisplay': True })
def test_compareTrackers_3(): ''' test functionality: aligning algo's with different num of diagnostic-plots ''' # build listTrackers listTrackers = [] for _algoenum in [2, 3]: _tracker = TrackFactory(on=True) _tracker.setAlgoEnum(_algoenum) _tracker.setInit(ballColor="orange") listTrackers.append(_tracker) # build listGS test_data = "compareTrackers_orange.db" test_dir = os.path.join(TEST_PARENT_DIR, 'compareTrackers') testDB = DBInterface(os.path.join(test_dir, test_data)) listGS = [pickle.loads(record[1]) for record in testDB.selectAll()] # run two separate functions with different params, compare their output data_dict_1 = compareTrackers(listGS, listTrackers, roiSelectFunc=True, test_stub=True) data_dict_2 = compareTrackers(listGS, listTrackers, roiSelectFunc=True, expand_factor=0.5, blend_rowtitles=True, test_stub=True) # checks assert data_dict_1['row_titles'] == [ 'marked_frame', 'img_t', 'img_mask', 'img_repair', 'img_dummy', 'img_dummy_2', 'img_terminal', 'img_terminal_2' ] print data_dict_2['row_titles'] assert data_dict_2['row_titles'] == [ 'marked_frame\nmarked_frame', 'img_t\nimg_t', 'img_mask\nimg_mask', 'img_repair\nimg_repair', 'img_terminal\nimg_dummy', 'n/a\nimg_dummy_2', 'n/a\nimg_terminal', 'n/a\nimg_terminal_2' ] assert sum(sum(sum(data_dict_1['plot_dict']['img_t'][0]))) > 0 assert data_dict_1['plot_dict']['img_dummy'][0] is None assert sum(sum(sum(data_dict_1['plot_dict']['img_dummy'][1]))) > 0 assert data_dict_2['plot_dict']['img_dummy'][0] is None assert sum(sum(sum(data_dict_2['plot_dict']['img_dummy'][1]))) > 0 assert data_dict_1['plot_data'][0][7] is None
def test_compareTrackers_5(): ''' test functionality: blend_rowtitles ''' # build listTrackers listTrackers = [] for _algoenum in [2, 3]: _tracker = TrackFactory(on=True) _tracker.setAlgoEnum(_algoenum) _tracker.setInit(ballColor="orange") listTrackers.append(_tracker) # build listGS test_data = "compareTrackers_orange.db" test_dir = os.path.join(TEST_PARENT_DIR, 'compareTrackers') testDB = DBInterface(os.path.join(test_dir, test_data)) listGS = [pickle.loads(record[1]) for record in testDB.selectAll()] # run with blend_rowtitles data_dict_2 = compareTrackers(listGS, listTrackers, roiSelectFunc=True, expand_factor=0.5, blend_rowtitles=True, test_stub=True) # checks print data_dict_2['row_titles'] assert data_dict_2['row_titles'] == [ 'marked_frame\nmarked_frame', 'img_t\nimg_t', 'img_mask\nimg_mask', 'img_repair\nimg_repair', 'img_terminal\nimg_dummy', 'n/a\nimg_dummy_2', 'n/a\nimg_terminal', 'n/a\nimg_terminal_2' ] # verify plots in blend_rowtitles is in correct order data_dict_2['plot_data'][0][4] is not None try: data_dict_2['plot_data'][0][5] is None assert False # this should be out-of-index except: pass data_dict_2['plot_data'][1][4] is not None data_dict_2['plot_data'][1][5] is not None
def test_compareTrackers_4(): ''' test functionality: bFirstTrackerRoi ''' # build listTrackers: place algo_enum=2 in first position listTrackers = [] for _algoenum in [2, 0]: _tracker = TrackFactory(on=True) _tracker.setAlgoEnum(_algoenum) _tracker.setInit(ballColor="orange") listTrackers.append(_tracker) # build listGS - these foi's are specifically chosen as the roi from track_score # from algo_enum=0 and algo_enum=2 are very different test_data = "compareTrackers_disparateRoi.db" test_dir = os.path.join(TEST_PARENT_DIR, 'compareTrackers') testDB = DBInterface(os.path.join(test_dir, test_data)) listGS = [pickle.loads(record[1]) for record in testDB.selectAll()] # run two separate functions with different params, compare their output data_indv_roi = compareTrackers( listGS, listTrackers, roiSelectFunc=True, bTrackScore=True, bFirstTrackerRoi=False # var-of-interest , expand_factor=2.0, test_stub=True) data_first_roi = compareTrackers( listGS, listTrackers, roiSelectFunc=True, bTrackScore=True, bFirstTrackerRoi=True # var-of-interest , expand_factor=2.0, test_stub=True) #compare col_titles - extract window-roi from string assert data_indv_roi['col_titles'] == [ 'AlgoEnum=2\n(373, 277, 10, 10)', 'AlgoEnum=0\n(395, -7, 16, 16)' ] assert data_first_roi['col_titles'] == [ 'AlgoEnum=2\n(373, 277, 10, 10)', 'AlgoEnum=0\n(373, 277, 10, 10)' ] #make sure empty plot is in correct position - the second position plot_row = data_indv_roi['plot_dict']['img_terminal'] assert sum(sum(plot_row[0])) > 0 assert plot_row[1] is None plot_row = data_first_roi['plot_dict']['img_terminal'] assert sum(sum(plot_row[0])) > 0 assert plot_row[1] is None # use shape to verify the same roi is being applied across all trackers assert (data_indv_roi['plot_dict']['img_t'][0].shape != data_indv_roi['plot_dict']['img_t'][1].shape) assert (data_first_roi['plot_dict']['img_t'][0].shape == data_first_roi['plot_dict']['img_t'][1].shape)
def test_compareTrackers_2(): ''' test functionality: col_titles expand_factor blend_rowtitles pixel-comparison ''' # build listTrackers listTrackers = [] for _algoenum in [0, 1]: _tracker = TrackFactory(on=True) _tracker.setAlgoEnum(_algoenum) _tracker.setInit(ballColor="orange") listTrackers.append(_tracker) # build listGS test_data = "compareTrackers_orange.db" test_dir = os.path.join(TEST_PARENT_DIR, 'compareTrackers') testDB = DBInterface(os.path.join(test_dir, test_data)) listGS = [pickle.loads(record[1]) for record in testDB.selectAll()] # run two separate functions with different params, compare their output data_dict_1 = compareTrackers(listGS, listTrackers, roiSelectFunc=True, col_titles=['my_col_1', 'my_col_2'], test_stub=True) data_dict_2 = compareTrackers(listGS, listTrackers, roiSelectFunc=True, expand_factor=0.5, blend_rowtitles=True, test_stub=True) # checks assert data_dict_1['row_titles'] == [ 'marked_frame', 'img_t', 'img_mask', 'img_repair', 'img_terminal' ] assert data_dict_2['row_titles'] == [ 'marked_frame\nmarked_frame', 'img_t\nimg_t', 'img_mask\nimg_mask', 'img_repair\nimg_repair', 'n/a\nimg_terminal' ] assert data_dict_1['col_titles'] == ['my_col_1', 'my_col_2'] assert data_dict_2['col_titles'] == ['AlgoEnum=0', 'AlgoEnum=1'] assert (data_dict_1['plot_dict']['img_t'][0].shape[0] < data_dict_2['plot_dict']['img_t'][0].shape[0]) # verify plots in blend_rowtitles is in correct order # data_dict_2['plot_data'][col][row] is None # data_dict_2['plot_data'][col][row] is not None # pixel-wise comparison DIFF_LOG_DIR = "../data/test/guiview/displayclass/log/" diff = ImgDiff(log_path=DIFF_LOG_DIR) loaded_mf1 = cv2.imread( os.path.join(test_dir, 'benchmark_markedframe_1.png')) loaded_mf2 = cv2.imread( os.path.join(test_dir, 'benchmark_markedframe_2.png')) mf1 = data_dict_1['plot_dict']['marked_frame'][0] mf2 = data_dict_2['plot_dict']['marked_frame'][0] assert diff.diffImgs(mf1, loaded_mf1) assert diff.diffImgs(mf2, loaded_mf2)
class OutputFactory: ''' Handles logic for outputting a video ''' def __init__(self): self.outputDir = "" self.vidwriter = None self.timewriter = None self.metawriter = None self.writeVidFn = None self.writeTimeFn = None self.writeMetaFn = None self.bWriteVidOn = False self.bWriteFrameCmd = False self.bWriteFrameSnap = False self.bWriteScoreSnap = False self.bAllowDuplicates = False self.bInitWriteVid = False self.bOutputState = False self.bDeleteState = False self.bBatchState = False self.enumBatchCriteria = 0 self.batchIndexList = None self.batchOutputCounter = 0 self.advanceFrame = False self.compressionEnum = 0 self.framesData = [] self.framesInd = [] self.frameCounter = None self.db = None self.dbPathFn = "data/usr/interproc.db" def setOutputDir(self, outputDir): self.outputDir = outputDir def resetFramesData(self): self.framesData = [] def resetFramesInd(self): self.framesInd = [] self.frameCounter = None def setBatchState(self, bBatchState, iEnumBatchCriteria, lBatchIndexList=None, sBatchDbPathFn=""): self.bBatchState = bBatchState self.enumBatchCriteria = iEnumBatchCriteria if lBatchIndexList is not None: self.batchIndexList = copy.copy(lBatchIndexList) if sBatchDbPathFn != "": self.dbPathFn = sBatchDbPathFn if bBatchState: print '\nSTART - running batch output ...' try: if self.db is None: self.db = DBInterface(self.dbPathFn) self.db.deleteAll() self.db = None print '...deleting all exisiting %s records...' % str( self.dbPathFn) except: print 'failed to delete exisitng records' def checkBatchExit(self): ''' return True to exit guiview inner loop; for once-thru batch-output / batch-eval runs ''' if self.bBatchState: print 'FINISH - batch output with %s outputs.' % str( self.batchOutputCounter) return True return False def setCmd(self, duplicatesEnum=None, initWriteVid=None, compressionEnum=None, writevidOn=None, switchWriteFrame=None, switchWriteScoring=None, switchOverideNote=None, switchOutputState=None, switchDeleteState=None): if duplicatesEnum is not None: self.bAllowDuplicates = True if duplicatesEnum == 1 else False if initWriteVid: self.bInitWriteVid = True g.initWriteVid = False else: self.bInitWriteVid = False if compressionEnum is not None: self.compressionEnum = compressionEnum if writevidOn is not None: self.bWriteVidOn = writevidOn self.advanceFrame = False if switchWriteFrame is not None: self.bWriteFrameSnap = switchWriteFrame if switchWriteFrame: g.switchWriteVid = False self.advanceFrame = True if switchWriteScoring is not None: self.bWriteScoreSnap = switchWriteScoring if switchWriteScoring: g.switchWriteScoring = False self.advanceFrame = True if switchOverideNote is not None: self.bWriteOverideSnap = switchOverideNote if switchOverideNote: g.switchOverideNote = False self.advanceFrame = True if switchOutputState is not None: self.bOutputState = switchOutputState if switchOutputState: g.switchOutputState = False if switchDeleteState is not None: self.bDeleteState = switchDeleteState if switchDeleteState: g.switchDeleteState = False def getAdvanceFrame(self): return self.advanceFrame def checkWriteVid(self): return self.bInitWriteVid def setWriteFrameCmd(self, bWriteFrame): self.bWriteFrameCmd = bWriteFrame def setFrameCounter(self, iFrameCounter): self.frameCounter = iFrameCounter def checkDuplicateFrame(self): ''' return True if not duplicate / "already in output" ''' if self.frameCounter not in self.framesInd: self.framesInd.append(self.frameCounter) return True else: return False def isDuplicate(self): ''' return False if it's not-duplicate or you allow duplicates ''' if self.bAllowDuplicates: return False else: if self.checkDuplicateFrame(): return False else: return True def checkWriteFrame(self): if ((self.bWriteVidOn and self.bWriteFrameCmd) or self.bWriteFrameSnap or self.bWriteScoreSnap or self.bWriteOverideSnap): return True return False def needScore(self): ''' return true if this frames notes should include scoring ''' return self.bWriteScoreSnap def checkOutputState(self): if self.bOutputState or self.bDeleteState or self.bBatchState: return True return False def checkCriteriaOutput(self, display, frameFactory, trackFactory, timeFactory, notesFactory): ''' evaluate if criteria is met and return if so''' if self.enumBatchCriteria == 0: return False elif self.enumBatchCriteria == 1: # check the list if ((display.origFrame is not None) and (self.batchIndexList is not None) and (len(self.batchIndexList) > 0) and (frameFactory.frameCounter in self.batchIndexList)): return True elif self.enumBatchCriteria == 2: # example criteria using objects if ((display.origFrame is not None) and (frameFactory.frameCounter > -1) and (frameFactory.frameCounter < 20)): return True elif self.enumBatchCriteria == 3: # all frames that contain a scoring if ((display.origFrame is not None) and (frameFactory.frameCounter > -1) and (display.inputScore.checkHasContents())): return True return False def outputState(self, display, frameFactory, trackFactory, timeFactory, notesFactory): if self.db is None: self.db = DBInterface(self.dbPathFn) if self.bDeleteState: self.db.deleteAll() print 'deleting all states...' bProceed = False if self.bBatchState: bProceed = self.checkCriteriaOutput(display, frameFactory, trackFactory, timeFactory, notesFactory) if bProceed: self.batchOutputCounter += 1 if self.bOutputState or bProceed: state = GuiviewState() state.setState(display, frameFactory, trackFactory, timeFactory, notesFactory) s_state = state.save() self.db.insertState(s_state) if not (bProceed): print 'outputting state...' @staticmethod def stripExt(fn): return ".".join(fn.split(".")[:-1]) def initVidWriter(self, frameSize, vidFn): ext = "avi" fourcc = "h264" if self.compressionEnum == 1: fourcc = 0 #request lossless encoding if self.vidwriter is not None: self.vidwriter.release() self.vidwriter = None fnBase = self.stripExt(vidFn) self.writeVidFn = uniqueFn(fn_base=fnBase + ".proc", fn_dir=self.outputDir, fn_ext=ext) self.vidwriter = VidWriter(savefn=os.path.join(self.outputDir, self.writeVidFn), fourcc=fourcc, outshape=frameSize) if self.timewriter is not None: self.timewriter.close() self.timewriter = None self.writeTimeFn = self.stripExt(self.writeVidFn) + ".txt" self.timewriter = open(os.path.join(self.outputDir, self.writeTimeFn), 'w') self.writeMetaFn = self.stripExt(self.writeVidFn) + ".metalog" _f = open(os.path.join(self.outputDir, self.writeMetaFn), 'w') _f.close() self.metawriter = True def getWritevidFn(self): return self.writeVidFn def writeFrame(self, frame, timelogEntry, baseNote, frameData): ''' on advance or play, write previous frame ''' _bDuplicate = self.isDuplicate() if self.vidwriter is not None and not (_bDuplicate): self.vidwriter.write(frame) if self.timewriter is not None and not (_bDuplicate): self.timewriter.write(str(timelogEntry) + "\n") if self.metawriter is not None: # overwrite existing framenote. only for new score; other # framenote attr are not updated. to update other framenote # attr's use a new output. if _bDuplicate: try: currentFrameData = self.framesData[self.frameCounter] except: currentFrameData = {} #TODO-SS if (currentFrameData.get('scoring', None) is not None and frameData.get('scoring', -1) in (None, -1)): # The problem here is frameData is already populated with score # before this function, we want score as a separate arg here # if there's already a score, don't update this record return else: try: self.framesData[self.frameCounter] = frameData except: self.framesData.append(frameData) else: self.framesData.append(frameData) fullNotes = baseNote proc_data = fullNotes.get('proc-data', {}) proc_data['last_write_compression_enum'] = g.compressionEnum fullNotes['proc-data'] = proc_data fullNotes['frames'] = self.framesData fullNotes = self.orderDict(copy.copy(fullNotes), last_keys=["frames"]) metalogEntire = json.dumps(fullNotes, indent=4) _f = open(os.path.join(self.outputDir, self.writeMetaFn), 'w') _f.truncate(0) _f.write(metalogEntire) _f.close() @staticmethod def orderDict(dict, first_keys=[], last_keys=[]): _keys = [k for k in dict.keys()] _order = [0 for _ in range(len(_keys))] for i in range(len(_keys)): if _keys[i] in first_keys: _order[i] = -1 if _keys[i] in last_keys: _order[i] = 1 _temp = [(a, b) for a, b in zip(_keys, _order)] _temp.sort(key=lambda tup: tup[1]) sorted_keys = [elem[0] for elem in _temp] output = OrderedDict() for k in sorted_keys: output[k] = dict[k] return output