Esempio n. 1
0
    def setFrameScore(self, frameScoreData):

        if not (self.on): return

        if frameScoreData is None: return
        if len(frameScoreData) != 2: return

        frameType, frameScore = frameScoreData

        objScoring = ScoreSchema()
        objScoring.load(frameScore)
        circleDataObj0 = objScoring.getData(objEnum=0)

        if frameType == "training":

            datum = self.buildTrainingDatum(circleDataObj0, self.currentFrame)

            if datum is not None:
                self.trainingData.append(datum)

                if self.bPerformTrainOnNewData:
                    self.trainProc()

        if frameType == "scoring":
            pass
Esempio n. 2
0
def test_checkHasValid_1():

    score = {
        "0": {
            "type": "circle",
            "data": [20, 40, 50, 60]
        },
        "1": {
            "type": "circle",
            "data": [-10, -20, 40, 40]
        }
    }

    ss = ScoreSchema()
    ss.load(score)

    assert ss.checkHasValid()

    score = {
        "0": {
            "type": "circle",
            "data": [-10, 20, 40, 40]
        },
        "1": {
            "type": "circle",
            "data": [10, 20, -40, 40]
        }
    }

    ss = ScoreSchema()
    ss.load(score)

    assert ss.checkHasValid() == False
Esempio n. 3
0
def test_getObjRect_1():

    score = {
        "0": {
            "type": "ray",
            "data": [[100, 50], [200, 75]]
        },
        "1": {
            "type": "ray",
            "data": [[200, 75], [100, 50]]
        }
    }

    ss = ScoreSchema()
    ss.load(score)

    assert ss.getObjRect(0) == ss.getObjRect(1)

    assert ss.getObjRect(0) == (100, 50, 100, 25)

    score = {"0": {"type": "ray", "data": [[100, 50], [200, 25]]}}

    ss.load(score)

    ss.getObjRect(0) == (100, 25, 100, 25)
Esempio n. 4
0
 def getFrameScoreCurrent(self):
     ''' return the score or None. '''
     try:
         objScoring = ScoreSchema()
         objScoring.load(self.getFrameNoteCurrent().get('scoring', None))
         return objScoring.getAll()
     except:
         return None
Esempio n. 5
0
def test_getObjRect_2():

    score = {"1": {"type": "circle", "data": [100, 50, 99, 99]}}

    ss = ScoreSchema()
    ss.load(score)

    assert ss.getObjRect(1) == (100, 50, 99, 99)
Esempio n. 6
0
def test_ScoreSchema_load_number_type():

    # test that we coerce all data into int

    # circle
    inp_data = {'0': {'type': 'circle', 'data': [1.1, 2, float(15), 0.9999]}}
    ss = ScoreSchema()
    ss.load(inp_data)
    ret_data = ss.getAll()['0']['data']
    assert ret_data == [1, 2, 15, 0]
    assert all(map(lambda elem: type(elem) is int, ret_data))

    # ray
    inp_data = {'0': {'type': 'ray', 'data': [[1.1, 2], [float(15), 0.9999]]}}
    ss = ScoreSchema()
    ss.load(inp_data)
    ret_data = ss.getAll()['0']['data']
    assert ret_data == [[1, 2], [15, 0]]
    assert all(map(lambda elem: type(elem) is int, ret_data[0]))
    assert all(map(lambda elem: type(elem) is int, ret_data[1]))
Esempio n. 7
0
class NotesFactory:
    ''' handle non-timelog data associated with each video, and and each frame '''
    def __init__(self):
        self.metalog = MetaDataLog()
        self.vidIsLoaded = False
        self.isProcessed = False
        self.dataVid = {}
        self.frameNoteFailed = False

        self.orientation = 0
        self.compression = -1

        self.bOverideFramenote = False
        self.framesDataExisting = []
        self.frameInd = None
        self.displayFrameScoring = ScoreSchema()

        self.frameLogInputPathFn = None
        self.defaultLogFrameInputPathFn = "notes/guiview.jsonc"
        self.defaultFrameNotePathFn = "notes/framenote.json"
        self.defaultFrameNoteOveridePathFn = "notes/framenote-override.jsonc"

    def setFrameLogInput(self, frameLogPathFn):
        ''' set the path to framelog input which is json template for creation
            of frameData-dict'''

        if frameLogPathFn == "":
            self.frameLogInputPathFn = self.defaultLogFrameInputPathFn
        else:
            self.frameLogInputPathFn = frameLogPathFn

        try:
            _f = open(self.frameLogInputPathFn, 'r')
            _f.close()
        except:
            print 'couldnt open frameLogInput at: ', frameLogPathFn
            self.frameLogInputPathFn = None

    def setFrameCurrent(self, frameInd):
        self.frameInd = frameInd

    def setDisplayScoring(self, scoringData):
        self.displayFrameScoring.load(scoringData)
        # if scoringData is None, displayFrameScoring get's reset

    def getOrientation(self):
        return self.orientation  #degrees clockwise

    def getCompression(self):
        if self.compression == 0:  # this is the code for lossless
            return 1
        return 0

    def getBallColor(self):
        try:
            return self.dataVid['notes']['details']['ball_color']
        except:
            return None

    def setCmd(self, switchOverideNote=None):

        if switchOverideNote is not None:
            self.bOverideFramenote = switchOverideNote
            # note: still need to read this below in
            # output.setCmd, don't alter global here.

    def loadMetaLog(self, metalogPathFn):

        try:
            self.dataVid = self.metalog.get_log_data(metalogPathFn)

            self.orientation = self.dataVid.get('notes',
                                                0).get('orientation', 0)

            self.compression = self.dataVid.get('fourcc_enum', -1)

            if isinstance(self.metalog.data, dict):
                if len(self.metalog.data.keys()) > 0:
                    self.vidIsLoaded = True

            if self.dataVid.get('processed', False):
                self.isProcessed = True
                self.loadFrameNotes()
            else:
                self.dataVid['processed'] = True
                self.dataVid['proc-data'] = {}  #e.g. datetime of processing

        except:
            self.dataVid = {}

    def getBaseMetaLog(self):

        fullLog = copy.deepcopy(self.dataVid)

        try:
            del fullLog["frames"]
        except:
            pass

        return fullLog

    def loadFrameNotes(self):
        ''' if video is processed it already has frame notes, load those '''
        try:
            assert len(self.dataVid['frames']) > 0
            assert isinstance(self.dataVid['frames'][0], dict)
            self.framesDataExisting = self.dataVid['frames']
        except:
            self.framesDataExisting = []

    def getFrameNoteCurrent(self):
        ''' return a dict representing frame data '''
        try:
            return self.framesDataExisting[self.frameInd]
        except:
            return {}

    def getFrameScoreCurrent(self):
        ''' return the score or None. '''
        try:
            objScoring = ScoreSchema()
            objScoring.load(self.getFrameNoteCurrent().get('scoring', None))
            return objScoring.getAll()
        except:
            return None

    def getFrameScoreCurrentDict(self):
        ''' return the score or empty dict; like a wrapper for getFrameScoreCurrent'''
        result = self.getFrameScoreCurrent()
        if result is None:
            return {}
        return result

    def checkFrameHasScore(self):
        ''' return True is there's anything stored in framenote.scoring '''
        return self.getFrameNoteCurrent().get('scoring', None) is not None

    def getFrameType(self):
        try:
            frameNote = self.getFrameNoteCurrent()
            return frameNote['frame_type']
        except:
            return None

    def getFrameScoreForTrack(self):
        ''' returns relevant params from metalog to tracking module '''
        try:
            return self.getFrameType(), self.getFrameScoreCurrent()
        except:
            return None, None

    def loadFrameLogCurrent(self):
        ''' load data from notepad '''
        if self.frameLogInputPathFn is not None:
            try:
                with open(self.frameLogInputPathFn, "r") as f:
                    lines = f.readlines()
                input_str = ''.join(lines)

                #remove comments
                input_str = re.sub(r'\\\n', '', input_str)
                input_str = re.sub(r'//.*\n', '\n', input_str)

                return json.loads(input_str)
            except:
                print 'couldnt parse framelog jsonc'
                return {}
        else:
            return {}

    def outputFrameNote(self):
        ''' write out current frame note into a text file; edit if needed'''
        if not (self.isProcessed):
            return
        try:
            with open(self.defaultFrameNotePathFn, 'w') as f:
                json.dump(self.getFrameNoteCurrent(), f, indent=4)

            self.frameNoteFailed = False

        except:
            self.frameNoteFailed = True

    def loadFrameNoteInput(self):
        ''' read in frame note input, this will absorb any edits you made'''
        if not (self.isProcessed):
            return
        try:
            with open(self.defaultFrameNotePathFn, 'r') as f:
                lines = f.readlines()
            lines = "".join(lines)

            frameNote = json.loads(lines)
            return frameNote
        except:
            return self.getFrameNoteCurrent()

    def loadFramenoteOveride(self):
        if not (self.isProcessed):
            return
        try:
            with open(self.defaultFrameNoteOveridePathFn, 'r') as f:
                lines = f.readlines()
            lines = "".join(lines)

            lines = re.sub(r'\\\n', '', lines)
            lines = re.sub(r'//.*\n', '\n', lines)

            return json.loads(lines)
        except:
            print 'failed to load ', str(self.defaultFrameNoteOveridePathFn)
            return {}

    def getFrameData(self):
        ''' Return frameData. If no existing data, create new frameData-dict. If 
            frameData already exists and was loaded; there are multiple opportunites
            to update/add/delete the existing data here, based on gui-cmd's and
            editing files in an editor. Data is ultimately consumed by output.
        '''

        if self.isProcessed:

            if not (self.frameNoteFailed):
                #override any param for this frame in notepad
                frameData = self.loadFrameNoteInput()
            else:
                #couldnt find/open txt file; keep the same
                frameData = self.getFrameNoteCurrent()

            if self.displayFrameScoring.checkHasContents():

                #gui-cmd: writeFrame+Score - update/add-to scoring dict
                #note: if gui-cmd is not called, displayFrameScoring has no contents

                frameData['scoring'] = self.mergeDicts(
                    main=self.getFrameScoreCurrentDict(),
                    update=self.displayFrameScoring.getAll(),
                    b_add=True)

            if self.bOverideFramenote:

                #gui-cmd: writeFrame+Override - add/overwrite params from notepad

                frameData = self.mergeDicts(main=frameData,
                                            update=self.loadFramenoteOveride(),
                                            b_add=False)

        else:

            #frameData is new; load the framedata from txt file
            frameData = self.loadFrameLogCurrent()

            frameData['orig_vid_index'] = self.frameInd

            frameData['scoring'] = self.displayFrameScoring.getAll()

        return frameData

    def getBaseNote(self):

        baseNote = copy.deepcopy(self.dataVid)
        try:
            del baseNote['frames']
        except:
            pass  #some metalogs don't have frames
        assert 'frames' not in baseNote.keys()
        return baseNote

    def getBaseFrameNote(self, frameNote):

        baseFrameNote = copy.deepcopy(frameNote)
        try:
            del baseFrameNote['scoring']
        except:
            pass  #some frameNotes don't have scoring
        assert 'scoring' not in baseFrameNote.keys()
        return baseFrameNote

    #TODO - refactor to separate module
    @classmethod
    def mergeDicts(cls, main, update, b_add=False):
        ''' 
            with terminal nodes in update(dict) overwrite the value at those
            nodes in main(dict) if they exist, or add them if b_add=True:
            
            b_add=False:
                main:   {"a": 1, "b": 2, "inner": {"z":1}} 
                update: {"b":99, "inner":{"z": -99}, "x":-55}
                ->      {"a": 1, "b": 99, "inner":{"z": -99}}
            b_add=True:
                main:   {"a": 1, "b": 2, "inner": {"z":1}} 
                update: {"b":99, "inner":{"z": -99}, "x":-55}
                ->      {"a": 1, "b": 99, "inner":{"z": -99}, "x":-55}
            
            (output should have updates and (possibly) adds but never deletes)
        '''

        try:
            assert isinstance(main, dict)
            assert isinstance(update, dict)
        except Exception as e:
            print e.message
            return main

        updateKeys, updateVals = cls.recurseKeys(update)

        newMain = cls.recurseUpdate(copy.deepcopy(main), updateKeys,
                                    updateVals)

        if b_add:

            newMain = cls.recurseAdd(copy.deepcopy(main), updateKeys,
                                     updateVals)

        return newMain

    @classmethod
    def recurseKeys(cls, inputDict):
        ''' build [nested] list for keys and vals in inputDict:
                inputDict:  {"a":1, "b":2, "c": {"c_a":17}}
                ->:         ["a", "b", ["c", "c_a"]],   [1, [None, 17], 2])
        '''
        keyList, valList = [], []

        for k in inputDict.keys():

            if isinstance(inputDict[k], dict):

                tmpKey, tmpVal = cls.recurseKeys(inputDict[k])

                nestedKey = [k]
                nestedVal = [None]

                if len(tmpKey) > 0:
                    nestedKey.extend(tmpKey)
                    nestedVal.extend(tmpVal)

                keyList.append(nestedKey)
                valList.append(nestedVal)

            else:
                keyList.append(k)
                valList.append(inputDict[k])

        return keyList, valList

    @classmethod
    def recurseUpdate(cls, inputDict, listKeys, listVals):
        ''' only update if key is in inputDict '''

        if inputDict is None:
            return None

        for _key, _val in zip(listKeys, listVals):

            if isinstance(_key, list):

                _dict = cls.recurseUpdate(
                    copy.deepcopy(inputDict.get(_key[0], None)), _key[1:],
                    _val[1:])

                inputDict[_key[0]] = _dict

            else:

                if inputDict.has_key(_key):
                    inputDict[_key] = _val
                else:
                    # main doesn't have that key
                    pass

        return inputDict

    @classmethod
    def recurseAdd(cls, inputDict, listKeys, listVals):

        if inputDict is None:
            inputDict = {}

        for _key, _val in zip(listKeys, listVals):

            if isinstance(_key, list):

                _dict = cls.recurseAdd(
                    copy.deepcopy(inputDict.get(_key[0], None)), _key[1:],
                    _val[1:])

                inputDict[_key[0]] = _dict

            else:

                inputDict[_key] = _val

        return inputDict
Esempio n. 8
0
def test_toScalars():

    # test basic method
    score = {"0": {"type": "circle", "data": [100, 150, 60, 58]}}
    ss = ScoreSchema()
    ss.load(score)
    scalarsDict = ss.toScalars()

    ANSWER = {
        'obj_exists_0': True,
        'obj_type_0': 'circle',
        'data0_0': 100,
        'data1_0': 150,
        'data2_0': 60,
        'data3_0': 58
    }
    assert cmp(scalarsDict, ANSWER) == 0

    # test method on ray-type object
    score = {"0": {"type": "ray", "data": [[100, 150], [60, 58]]}}
    ss = ScoreSchema()
    ss.load(score)
    scalarsDict = ss.toScalars()

    ANSWER = {
        'obj_exists_0': True,
        'obj_type_0': 'ray',
        'data0_0': 100,
        'data1_0': 150,
        'data2_0': 60,
        'data3_0': 58
    }
    assert cmp(scalarsDict, ANSWER) == 0

    # test multi-obj's + non-traditional objEnums
    score = {
        "1": {
            "type": "circle",
            "data": [100, 150, 60, 58]
        },
        "3": {
            "type": "ray",
            "data": [[100, 150], [60, 58]]
        }
    }
    ss = ScoreSchema()
    ss.load(score)
    scalarsDict = ss.toScalars()

    ANSWER = {
        'obj_exists_1': True,
        'obj_type_1': 'circle',
        'data0_1': 100,
        'data1_1': 150,
        'data2_1': 60,
        'data3_1': 58,
        'obj_exists_3': True,
        'obj_type_3': 'ray',
        'data0_3': 100,
        'data1_3': 150,
        'data2_3': 60,
        'data3_3': 58
    }
    assert cmp(scalarsDict, ANSWER) == 0

    # test non-default num_data_cols argument
    score = {"0": {"type": "circle", "data": [100, 150, 60, 58]}}
    ss = ScoreSchema()
    ss.load(score)
    scalarsDict = ss.toScalars(num_data_cols=6)

    ANSWER = {
        'obj_exists_0': True,
        'obj_type_0': 'circle',
        'data0_0': 100,
        'data1_0': 150,
        'data2_0': 60,
        'data3_0': 58,
        'data4_0': None,
        'data5_0': None
    }
    assert cmp(scalarsDict, ANSWER) == 0
Esempio n. 9
0
def scoring_annotate_obj(input_test_child_dir, b_rebench=False):
    ''' test that we annotate score objects in main_display

            note: we can't initialize with annotateObjEnum=True or we get unhandled err
            
            input params:  - different scores (stored as json file in test dir)
    '''

    # setup ------
    TEST_CHILD_DIR = input_test_child_dir

    stub_frame = cv2.imread(
        os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "stubframe.png"))
    bench_main = cv2.imread(
        os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "bench_main.png"))
    bench_score = cv2.imread(
        os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "bench_score.png"))
    bench_naframe = cv2.imread(
        os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "naframe.png"))

    stub_score_obj = ScoreSchema()

    with open(os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "stubscore.json"),
              "r") as f:
        stub_score_obj.load(json.load(f))

    stub_score = stub_score_obj.getAll()

    diff = ImgDiff(log_path=DIFF_LOG_DIR)

    # run test -----

    stage = StagingDisplay()
    stage.some_display_methods(
        p_all=True,
        stub_frame=stub_frame.copy(),
        stub_scorecurrent=copy.deepcopy(stub_score),
        b_showscoring=True,
        annotateObjEnum=False  #note
    )
    stage.some_display_methods(p_all_byframe=True,
                               p_input=True,
                               stub_frame=stub_frame.copy(),
                               stub_scorecurrent=copy.deepcopy(stub_score),
                               b_showscoring=True,
                               annotateObjEnum=True)
    main1 = stage.mock_get_frame()
    score1 = stage.mock_get_score_frame()

    #rebench ---
    if b_rebench:

        if verifyAction(prefix="\nrebench:" + input_test_child_dir):
            return

        cv2.imwrite(
            os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "bench_main.png"),
            main1)

        cv2.imwrite(
            os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "bench_score.png"),
            score1)
        return

    # verify ----

    assert diff.diffImgs(bench_main, main1)
    assert diff.diffImgs(bench_score, score1)
Esempio n. 10
0
def scoring_obj_enum(input_test_child_dir,
                     input_obj_enum,
                     b_wrong=False,
                     b_rebench=False):
    ''' test that showscoring with properly formed is drawn to main_display and
        score_display
            
            input params:  - different scores (stored as json file in test dir)
                           - different scoringenum's to focus on with score_display
                           - b_wrong: if True, then there is no score with that
                                       input_obj_enum, thus no score_display
    '''

    # setup ------
    TEST_CHILD_DIR = input_test_child_dir

    stub_frame = cv2.imread(
        os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "stubframe.png"))
    bench_main = cv2.imread(
        os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "bench_main.png"))
    bench_score = cv2.imread(
        os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "bench_score.png"))
    bench_naframe = cv2.imread(
        os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "naframe.png"))

    stub_score_obj = ScoreSchema()

    with open(os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "stubscore.json"),
              "r") as f:
        stub_score_obj.load(json.load(f))

    stub_score = stub_score_obj.getAll()

    diff = ImgDiff(log_path=DIFF_LOG_DIR)

    # run test -----

    stage = StagingDisplay()
    stage.all_display_methods(
        stub_frame=stub_frame.copy(),
        stub_scorecurrent=copy.deepcopy(stub_score),
        b_showscoring=True,
        i_scoringenum=input_obj_enum  #test-variable
    )
    main1 = stage.mock_get_frame()
    score1 = stage.mock_get_score_frame()

    #rebench ---
    if b_rebench:

        if verifyAction(prefix="\nrebench:" + input_test_child_dir):
            return

        cv2.imwrite(
            os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "bench_main.png"),
            main1)

        if b_wrong:

            cv2.imwrite(
                os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR, "naframe.png"),
                score1)
        else:

            cv2.imwrite(
                os.path.join(TEST_PARENT_DIR, TEST_CHILD_DIR,
                             "bench_score.png"), score1)
        return

    # verify ----

    assert diff.diffImgs(bench_main, main1)

    if b_wrong:
        assert diff.diffImgs(bench_naframe, score1)
    else:
        assert diff.diffImgs(bench_score, score1)