def cook_append(self, test, refs):
        '''called by constructor and __iadd__ to avoid creating new instances.'''

        if refs is not None:
            self.crefs.append(cook_refs(refs))
            if test is not None:
                cooked_test = cook_test(test, self.crefs[-1])
                self.ctest.append(cooked_test) ## N.B.: -1
            else:
                self.ctest.append(None) # lens of crefs and ctest have to match

        self._score = None

def
cook_append
(
self
,
test
,
refs
)
:
if
refs
is
not
:
self
.
crefs
.
append
(
cook_refs
(
refs
)
)
if
test
is
not
:
cooked_test
=
cook_test
(
test
,
self
.
crefs
[
1
]
)
self
.
ctest
.
append
(
cooked_test
)
## N.B.: -1
else
:
self
.
ctest
.
append
(
)
# lens of crefs and ctest have to match
self
.
_score
=


def score_ratio(self, option=None):
        '''return (bleu, len_ratio) pair'''
        return (self.fscore(option=option), self.ratio(option=option))

def score_ratio ( self , option = None ) : return ( self . fscore ( option = option ) , self . ratio ( option = option ) )


replace test ( s ) with new test ( s ) and returns the new score .

def rescore(self, new_test):
        ''' replace test(s) with new test(s), and returns the new score.'''

        return self.retest(new_test).compute_score()

def rescore ( self , new_test ) : return self . retest ( new_test ) . compute_score ( )


add an instance ( e . g . from another sentence ) .

def __iadd__(self, other):
        '''add an instance (e.g., from another sentence).'''

        if type(other) is tuple:
            ## avoid creating new BleuScorer instances
            self.cook_append(other[0], other[1])
        else:
            assert self.compatible(other), "incompatible BLEUs."
            self.ctest.extend(other.ctest)
            self.crefs.extend(other.crefs)
            self._score = None ## need to recompute

        return self


Calculates longest common subsequence for a pair of tokenized strings : param string : list of str : tokens from a string split using whitespace : param sub : list of str : shorter string also split using whitespace : returns : length ( list of int ) : length of the longest common subsequence between the two strings

def my_lcs(string, sub):
    """
    Calculates longest common subsequence for a pair of tokenized strings
    :param string : list of str : tokens from a string split using whitespace
    :param sub : list of str : shorter string, also split using whitespace
    :returns: length (list of int): length of the longest common subsequence between the two strings

    Note: my_lcs only gives length of the longest common subsequence, not the actual LCS
    """
    if(len(string)< len(sub)):
        sub, string = string, sub

    lengths = [[0 for i in range(0,len(sub)+1)] for j in range(0,len(string)+1)]

    for j in range(1,len(sub)+1):
        for i in range(1,len(string)+1):
            if(string[i-1] == sub[j-1]):
                lengths[i][j] = lengths[i-1][j-1] + 1
            else:
                lengths[i][j] = max(lengths[i-1][j] , lengths[i][j-1])

    return lengths[len(string)][len(sub)]

def my_lcs ( string , sub ) : if ( len ( string ) < len ( sub ) ) : sub , string = string , sub lengths = [ [ 0 for i in range ( 0 , len ( sub ) + 1 ) ] for j in range ( 0 , len ( string ) + 1 ) ] for j in range ( 1 , len ( sub ) + 1 ) : for i in range ( 1 , len ( string ) + 1 ) : if ( string [ i - 1 ] == sub [ j - 1 ] ) : lengths [ i ] [ j ] = lengths [ i - 1 ] [ j - 1 ] + 1 else : lengths [ i ] [ j ] = max ( lengths [ i - 1 ] [ j ] , lengths [ i ] [ j - 1 ] ) return lengths [ len ( string ) ] [ len ( sub ) ]


Compute ROUGE - L score given one candidate and references for an image : param candidate : str : candidate sentence to be evaluated : param refs : list of str : COCO reference sentences for the particular image to be evaluated : returns score : int ( ROUGE - L score for the candidate evaluated against references )

def calc_score(self, candidate, refs):
        """
        Compute ROUGE-L score given one candidate and references for an image
        :param candidate: str : candidate sentence to be evaluated
        :param refs: list of str : COCO reference sentences for the particular image to be evaluated
        :returns score: int (ROUGE-L score for the candidate evaluated against references)
        """
        assert(len(candidate)==1)
        assert(len(refs)>0)
        prec = []
        rec = []

        # split into tokens
        token_c = candidate[0].split(" ")

        for reference in refs:
            # split into tokens
            token_r = reference.split(" ")
            # compute the longest common subsequence
            lcs = my_lcs(token_r, token_c)
            prec.append(lcs/float(len(token_c)))
            rec.append(lcs/float(len(token_r)))

        prec_max = max(prec)
        rec_max = max(rec)

        if(prec_max!=0 and rec_max !=0):
            score = ((1 + self.beta**2)*prec_max*rec_max)/float(rec_max + self.beta**2*prec_max)
        else:
            score = 0.0
        return score


Computes Rouge - L score given a set of reference and candidate sentences for the dataset Invoked by evaluate_captions . py : param hypo_for_image : dict : candidate / test sentences with image name key and tokenized sentences as values : param ref_for_image : dict : reference MS - COCO sentences with image name key and tokenized sentences as values : returns : average_score : float ( mean ROUGE - L score computed by averaging scores for all the images )

def compute_score(self, gts, res):
        """
        Computes Rouge-L score given a set of reference and candidate sentences for the dataset
        Invoked by evaluate_captions.py
        :param hypo_for_image: dict : candidate / test sentences with "image name" key and "tokenized sentences" as values
        :param ref_for_image: dict : reference MS-COCO sentences with "image name" key and "tokenized sentences" as values
        :returns: average_score: float (mean ROUGE-L score computed by averaging scores for all the images)
        """
        assert(gts.keys() == res.keys())
        imgIds = gts.keys()

        score = []
        for id in imgIds:
            hypo = res[id]
            ref  = gts[id]

            score.append(self.calc_score(hypo, ref))

            # Sanity check.
            assert(type(hypo) is list)
            assert(len(hypo) == 1)
            assert(type(ref) is list)
            assert(len(ref) > 0)

        average_score = np.mean(np.array(score))
        return average_score, np.array(score)

def
compute_score
(
self
,
gts
,
res
)
:
assert
(
gts
.
keys
(
)
==
res
.
keys
(
)
)
imgIds
=
gts
.
keys
(
)
score
=
[
]
for
id
in
imgIds
:
hypo
=
res
[
id
]
ref
=
gts
[
id
]
score
.
append
(
self
.
calc_score
(
hypo
,
ref
)
)
# Sanity check.
assert
(
type
(
hypo
)
is
list
)
assert
(
len
(
hypo
)
==
1
)
assert
(
type
(
ref
)
is
list
)
assert
(
len
(
ref
)
>
0
)
average_score
=
np
.
mean
(
np
.
array
(
score
)
)
return
average_score
,
np
.
array
(
score
)


Constructor of Microsoft COCO helper class for reading and visualizing annotations . : param annotation_file ( str ) : location of annotation file : param image_folder ( str ) : location to the folder that hosts images . : return :

def __init__(self, annotation_file=None):
        """
        Constructor of Microsoft COCO helper class for reading and visualizing annotations.
        :param annotation_file (str): location of annotation file
        :param image_folder (str): location to the folder that hosts images.
        :return:
        """
        # load dataset
        self.dataset = {}
        self.anns = []
        self.imgToAnns = {}
        self.catToImgs = {}
        self.imgs = []
        self.cats = []
        self.image2hash = {}
        if not annotation_file == None:
            print('loading annotations into memory...')
            time_t = datetime.datetime.utcnow()
            dataset = json.load(open(annotation_file, 'r'))

            print( datetime.datetime.utcnow() - time_t)
            self.dataset = dataset
            self.createIndex()

def
__init__
(
self
,
annotation_file
=
)
:
# load dataset
self
.
dataset
=
{
}
self
.
anns
=
[
]
self
.
imgToAnns
=
{
}
self
.
catToImgs
=
{
}
self
.
imgs
=
[
]
self
.
cats
=
[
]
self
.
image2hash
=
{
}
if
not
annotation_file
==
:
print
(
'loading annotations into memory...'
)
time_t
=
datetime
.
datetime
.
utcnow
(
)
dataset
=
json
.
load
(
open
(
annotation_file
,
'r'
)
)
print
(
datetime
.
datetime
.
utcnow
(
)
time_t
)
self
.
dataset
=
dataset
self
.
createIndex
(
)


Print information about the annotation file . : return :

def info(self):
        """
        Print information about the annotation file.
        :return:
        """
        for key, value in self.datset['info'].items():
            print( '%s: %s'%(key, value))

def
info
(
self
)
:
for
key
,
value
in
self
.
datset
[
'info'
]
.
items
(
)
:
print
(
'%s: %s'
%
(
key
,
value
)
)


Get ann ids that satisfy given filter conditions . default skips that filter : param imgIds ( int array ) : get anns for given imgs catIds ( int array ) : get anns for given cats areaRng ( float array ) : get anns for given area range ( e . g . [ 0 inf ] ) iscrowd ( boolean ) : get anns for given crowd label ( False or True ) : return : ids ( int array ) : integer array of ann ids

def getAnnIds(self, imgIds=[], catIds=[], areaRng=[], iscrowd=None):
        """
        Get ann ids that satisfy given filter conditions. default skips that filter
        :param imgIds  (int array)     : get anns for given imgs
               catIds  (int array)     : get anns for given cats
               areaRng (float array)   : get anns for given area range (e.g. [0 inf])
               iscrowd (boolean)       : get anns for given crowd label (False or True)
        :return: ids (int array)       : integer array of ann ids
        """
        imgIds = imgIds if type(imgIds) == list else [imgIds]
        catIds = catIds if type(catIds) == list else [catIds]

        if len(imgIds) == len(catIds) == len(areaRng) == 0:
            anns = self.dataset['annotations']
        else:
            if not len(imgIds) == 0:
                anns = sum([self.imgToAnns[imgId] for imgId in imgIds if imgId in self.imgToAnns],[])
            else:
                anns = self.dataset['annotations']
            anns = anns if len(catIds)  == 0 else [ann for ann in anns if ann['category_id'] in catIds]
            anns = anns if len(areaRng) == 0 else [ann for ann in anns if ann['area'] > areaRng[0] and ann['area'] < areaRng[1]]
        if self.dataset['type'] == 'instances':
            if not iscrowd == None:
                ids = [ann['id'] for ann in anns if ann['iscrowd'] == iscrowd]
            else:
                ids = [ann['id'] for ann in anns]
        else:
            ids = [ann['id'] for ann in anns]
        return ids

def getAnnIds ( self , imgIds = [ ] , catIds = [ ] , areaRng = [ ] , iscrowd = None ) : imgIds = imgIds if type ( imgIds ) == list else [ imgIds ] catIds = catIds if type ( catIds ) == list else [ catIds ] if len ( imgIds ) == len ( catIds ) == len ( areaRng ) == 0 : anns = self . dataset [ 'annotations' ] else : if not len ( imgIds ) == 0 : anns = sum ( [ self . imgToAnns [ imgId ] for imgId in imgIds if imgId in self . imgToAnns ] , [ ] ) else : anns = self . dataset [ 'annotations' ] anns = anns if len ( catIds ) == 0 else [ ann for ann in anns if ann [ 'category_id' ] in catIds ] anns = anns if len ( areaRng ) == 0 else [ ann for ann in anns if ann [ 'area' ] > areaRng [ 0 ] and ann [ 'area' ] < areaRng [ 1 ] ] if self . dataset [ 'type' ] == 'instances' : if not iscrowd == None : ids = [ ann [ 'id' ] for ann in anns if ann [ 'iscrowd' ] == iscrowd ] else : ids = [ ann [ 'id' ] for ann in anns ] else : ids = [ ann [ 'id' ] for ann in anns ] return ids


filtering parameters . default skips that filter . : param catNms ( str array ) : get cats for given cat names : param supNms ( str array ) : get cats for given supercategory names : param catIds ( int array ) : get cats for given cat ids : return : ids ( int array ) : integer array of cat ids

def getCatIds(self, catNms=[], supNms=[], catIds=[]):
        """
        filtering parameters. default skips that filter.
        :param catNms (str array)  : get cats for given cat names
        :param supNms (str array)  : get cats for given supercategory names
        :param catIds (int array)  : get cats for given cat ids
        :return: ids (int array)   : integer array of cat ids
        """
        catNms = catNms if type(catNms) == list else [catNms]
        supNms = supNms if type(supNms) == list else [supNms]
        catIds = catIds if type(catIds) == list else [catIds]

        if len(catNms) == len(supNms) == len(catIds) == 0:
            cats = self.dataset['categories']
        else:
            cats = self.dataset['categories']
            cats = cats if len(catNms) == 0 else [cat for cat in cats if cat['name']          in catNms]
            cats = cats if len(supNms) == 0 else [cat for cat in cats if cat['supercategory'] in supNms]
            cats = cats if len(catIds) == 0 else [cat for cat in cats if cat['id']            in catIds]
        ids = [cat['id'] for cat in cats]
        return ids

def getCatIds ( self , catNms = [ ] , supNms = [ ] , catIds = [ ] ) : catNms = catNms if type ( catNms ) == list else [ catNms ] supNms = supNms if type ( supNms ) == list else [ supNms ] catIds = catIds if type ( catIds ) == list else [ catIds ] if len ( catNms ) == len ( supNms ) == len ( catIds ) == 0 : cats = self . dataset [ 'categories' ] else : cats = self . dataset [ 'categories' ] cats = cats if len ( catNms ) == 0 else [ cat for cat in cats if cat [ 'name' ] in catNms ] cats = cats if len ( supNms ) == 0 else [ cat for cat in cats if cat [ 'supercategory' ] in supNms ] cats = cats if len ( catIds ) == 0 else [ cat for cat in cats if cat [ 'id' ] in catIds ] ids = [ cat [ 'id' ] for cat in cats ] return ids


Get img ids that satisfy given filter conditions . : param imgIds ( int array ) : get imgs for given ids : param catIds ( int array ) : get imgs with all given cats : return : ids ( int array ) : integer array of img ids

def getImgIds(self, imgIds=[], catIds=[]):
        '''
        Get img ids that satisfy given filter conditions.
        :param imgIds (int array) : get imgs for given ids
        :param catIds (int array) : get imgs with all given cats
        :return: ids (int array)  : integer array of img ids
        '''
        imgIds = imgIds if type(imgIds) == list else [imgIds]
        catIds = catIds if type(catIds) == list else [catIds]

        if len(imgIds) == len(catIds) == 0:
            ids = self.imgs.keys()
        else:
            ids = set(imgIds)
            for catId in catIds:
                if len(ids) == 0:
                    ids = set(self.catToImgs[catId])
                else:
                    ids &= set(self.catToImgs[catId])
        return list(ids)

def getImgIds ( self , imgIds = [ ] , catIds = [ ] ) : imgIds = imgIds if type ( imgIds ) == list else [ imgIds ] catIds = catIds if type ( catIds ) == list else [ catIds ] if len ( imgIds ) == len ( catIds ) == 0 : ids = self . imgs . keys ( ) else : ids = set ( imgIds ) for catId in catIds : if len ( ids ) == 0 : ids = set ( self . catToImgs [ catId ] ) else : ids &= set ( self . catToImgs [ catId ] ) return list ( ids )


Load anns with the specified ids . : param ids ( int array ) : integer ids specifying anns : return : anns ( object array ) : loaded ann objects

def loadAnns(self, ids=[]):
        """
        Load anns with the specified ids.
        :param ids (int array)       : integer ids specifying anns
        :return: anns (object array) : loaded ann objects
        """
        if type(ids) == list:
            return [self.anns[id] for id in ids]
        elif type(ids) == int:
            return [self.anns[ids]]

def loadAnns ( self , ids = [ ] ) : if type ( ids ) == list : return [ self . anns [ id ] for id in ids ] elif type ( ids ) == int : return [ self . anns [ ids ] ]


Load cats with the specified ids . : param ids ( int array ) : integer ids specifying cats : return : cats ( object array ) : loaded cat objects

def loadCats(self, ids=[]):
        """
        Load cats with the specified ids.
        :param ids (int array)       : integer ids specifying cats
        :return: cats (object array) : loaded cat objects
        """
        if type(ids) == list:
            return [self.cats[id] for id in ids]
        elif type(ids) == int:
            return [self.cats[ids]]

def loadCats ( self , ids = [ ] ) : if type ( ids ) == list : return [ self . cats [ id ] for id in ids ] elif type ( ids ) == int : return [ self . cats [ ids ] ]


Load anns with the specified ids . : param ids ( int array ) : integer ids specifying img : return : imgs ( object array ) : loaded img objects

def loadImgs(self, ids=[]):
        """
        Load anns with the specified ids.
        :param ids (int array)       : integer ids specifying img
        :return: imgs (object array) : loaded img objects
        """
        if type(ids) == list:
            return [self.imgs[id] for id in ids]
        elif type(ids) == int:
            return [self.imgs[ids]]

def loadImgs ( self , ids = [ ] ) : if type ( ids ) == list : return [ self . imgs [ id ] for id in ids ] elif type ( ids ) == int : return [ self . imgs [ ids ] ]


Display the specified annotations . : param anns ( array of object ) : annotations to display : return : None

def showAnns(self, anns):
        """
        Display the specified annotations.
        :param anns (array of object): annotations to display
        :return: None
        """
        if len(anns) == 0:
            return 0
        if self.dataset['type'] == 'instances':
            ax = plt.gca()
            polygons = []
            color = []
            for ann in anns:
                c = np.random.random((1, 3)).tolist()[0]
                if type(ann['segmentation']) == list:
                    # polygon
                    for seg in ann['segmentation']:
                        poly = np.array(seg).reshape((len(seg)/2, 2))
                        polygons.append(Polygon(poly, True,alpha=0.4))
                        color.append(c)
                else:
                    # mask
                    mask = COCO.decodeMask(ann['segmentation'])
                    img = np.ones( (mask.shape[0], mask.shape[1], 3) )
                    if ann['iscrowd'] == 1:
                        color_mask = np.array([2.0,166.0,101.0])/255
                    if ann['iscrowd'] == 0:
                        color_mask = np.random.random((1, 3)).tolist()[0]
                    for i in range(3):
                        img[:,:,i] = color_mask[i]
                    ax.imshow(np.dstack( (img, mask*0.5) ))
            p = PatchCollection(polygons, facecolors=color, edgecolors=(0,0,0,1), linewidths=3, alpha=0.4)
            ax.add_collection(p)
        if self.dataset['type'] == 'captions':
            for ann in anns:
                print( ann['caption'])

def
showAnns
(
self
,
anns
)
:
if
len
(
anns
)
==
0
:
return
0
if
self
.
dataset
[
'type'
]
==
'instances'
:
ax
=
plt
.
gca
(
)
polygons
=
[
]
color
=
[
]
for
ann
in
anns
:
c
=
np
.
random
.
random
(
(
1
,
3
)
)
.
tolist
(
)
[
0
]
if
type
(
ann
[
'segmentation'
]
)
==
list
:
# polygon
for
seg
in
ann
[
'segmentation'
]
:
poly
=
np
.
array
(
seg
)
.
reshape
(
(
len
(
seg
)
/
2
,
2
)
)
polygons
.
append
(
Polygon
(
poly
,
True
,
alpha
=
0.4
)
)
color
.
append
(
c
)
else
:
# mask
mask
=
COCO
.
decodeMask
(
ann
[
'segmentation'
]
)
img
=
np
.
ones
(
(
mask
.
shape
[
0
]
,
mask
.
shape
[
1
]
,
3
)
)
if
ann
[
'iscrowd'
]
==
1
:
color_mask
=
np
.
array
(
[
2.0
,
166.0
,
101.0
]
)
/
255
if
ann
[
'iscrowd'
]
==
0
:
color_mask
=
np
.
random
.
random
(
(
1
,
3
)
)
.
tolist
(
)
[
0
]
for
i
in
range
(
3
)
:
img
[
:
,
:
,
i
]
=
color_mask
[
i
]
ax
.
imshow
(
np
.
dstack
(
(
img
,
mask
*
0.5
)
)
)
p
=
PatchCollection
(
polygons
,
facecolors
=
color
,
edgecolors
=
(
0
,
0
,
0
,
1
)
,
linewidths
=
3
,
alpha
=
0.4
)
ax
.
add_collection
(
p
)
if
self
.
dataset
[
'type'
]
==
'captions'
:
for
ann
in
anns
:
print
(
ann
[
'caption'
]
)


change by ZhengHe Load result file and return a result api object . : param resFile ( str ) : file name of result file : return : res ( obj ) : result api object

def loadRes(self, resFile):
        """
        change by ZhengHe
        Load result file and return a result api object.
        :param   resFile (str)     : file name of result file
        :return: res (obj)         : result api object
        """
        res = COCO()
        res.dataset['images'] = [img for img in self.dataset['images']]
        res.dataset['info'] = copy.deepcopy(self.dataset['info'])
        res.dataset['type'] = copy.deepcopy(self.dataset['type'])
        res.dataset['licenses'] = copy.deepcopy(self.dataset['licenses'])

        # str to hex int for image_id
        imgdict = {}
        def get_image_dict(img_name):
            # image_hash = int(int(hashlib.sha256(img_name).hexdigest(), 16) % sys.maxint)
            image_hash = self.image2hash[img_name]
            if image_hash in imgdict:
                assert imgdict[image_hash] == img_name, 'hash colision: {0}: {1}'.format(image_hash, img_name)
            else:
                imgdict[image_hash] = img_name
            image_dict = {"id": image_hash,
                          "width": 0,
                          "height": 0,
                          "file_name": img_name,
                          "license": '',
                          "url": img_name,
                          "date_captured": '',
                          }
            return image_hash

        print ('Loading and preparing results...     ')
        time_t = datetime.datetime.utcnow()
        anns    = json.load(open(resFile))

        assert type(anns) == list, 'results in not an array of objects'

        # annsImgIds = [ann['image_id'] for ann in anns]
        # change by ZhengHe
        annsImgIds = []
        for ann in anns:
            assert ann['image_id'] != '','image_id must have a name'
            assert ann['caption'] != '', 'caption must be a string'

            w = jieba.cut(ann['caption'].strip().replace('。',''), cut_all=False)
            p = ' '.join(w)
            ann['caption'] = p
            ann['image_id'] = get_image_dict(ann['image_id'])
            annsImgIds.append((ann['image_id']))

        assert set(annsImgIds) == (set(annsImgIds) & set(self.getImgIds())), \
               'Results do not correspond to current coco set'
        if 'caption' in anns[0]:
            imgIds = set([img['id'] for img in res.dataset['images']]) & set([ann['image_id'] for ann in anns])
            res.dataset['images'] = [img for img in res.dataset['images'] if img['id'] in imgIds]
            for id, ann in enumerate(anns):
                ann['id'] = id
        elif 'bbox' in anns[0] and not anns[0]['bbox'] == []:
            res.dataset['categories'] = copy.deepcopy(self.dataset['categories'])
            for id, ann in enumerate(anns):
                bb = ann['bbox']
                x1, x2, y1, y2 = [bb[0], bb[0]+bb[2], bb[1], bb[1]+bb[3]]
                ann['segmentation'] = [[x1, y1, x1, y2, x2, y2, x2, y1]]
                ann['area'] = bb[2]*bb[3]
                ann['id'] = id
                ann['iscrowd'] = 0
        elif 'segmentation' in anns[0]:
            res.dataset['categories'] = copy.deepcopy(self.dataset['categories'])
            for id, ann in enumerate(anns):
                ann['area']=sum(ann['segmentation']['counts'][2:-1:2])
                ann['bbox'] = []
                ann['id'] = id
                ann['iscrowd'] = 0
        print( 'DONE (t=%0.2fs)'%((datetime.datetime.utcnow() - time_t).total_seconds()))

        res.dataset['annotations'] = anns
        res.createIndex()
        return res


Decode binary mask M encoded via run - length encoding . : param R ( object RLE ) : run - length encoding of binary mask : return : M ( bool 2D array ) : decoded binary mask

def decodeMask(R):
        """
        Decode binary mask M encoded via run-length encoding.
        :param   R (object RLE)    : run-length encoding of binary mask
        :return: M (bool 2D array) : decoded binary mask
        """
        N = len(R['counts'])
        M = np.zeros( (R['size'][0]*R['size'][1], ))
        n = 0
        val = 1
        for pos in range(N):
            val = not val
            for c in range(R['counts'][pos]):
                R['counts'][pos]
                M[n] = val
                n += 1
        return M.reshape((R['size']), order='F')

def decodeMask ( R ) : N = len ( R [ 'counts' ] ) M = np . zeros ( ( R [ 'size' ] [ 0 ] * R [ 'size' ] [ 1 ] , ) ) n = 0 val = 1 for pos in range ( N ) : val = not val for c in range ( R [ 'counts' ] [ pos ] ) : R [ 'counts' ] [ pos ] M [ n ] = val n += 1 return M . reshape ( ( R [ 'size' ] ) , order = 'F' )


Encode binary mask M using run - length encoding . : param M ( bool 2D array ) : binary mask to encode : return : R ( object RLE ) : run - length encoding of binary mask

def encodeMask(M):
        """
        Encode binary mask M using run-length encoding.
        :param   M (bool 2D array)  : binary mask to encode
        :return: R (object RLE)     : run-length encoding of binary mask
        """
        [h, w] = M.shape
        M = M.flatten(order='F')
        N = len(M)
        counts_list = []
        pos = 0
        # counts
        counts_list.append(1)
        diffs = np.logical_xor(M[0:N-1], M[1:N])
        for diff in diffs:
            if diff:
                pos +=1
                counts_list.append(1)
            else:
                counts_list[pos] += 1
        # if array starts from 1. start with 0 counts for 0
        if M[0] == 1:
            counts_list = [0] + counts_list
        return {'size':      [h, w],
               'counts':    counts_list ,
               }


Convert polygon segmentation to binary mask . : param S ( float array ) : polygon segmentation mask : param h ( int ) : target mask height : param w ( int ) : target mask width : return : M ( bool 2D array ) : binary mask

def segToMask( S, h, w ):
         """
         Convert polygon segmentation to binary mask.
         :param   S (float array)   : polygon segmentation mask
         :param   h (int)           : target mask height
         :param   w (int)           : target mask width
         :return: M (bool 2D array) : binary mask
         """
         M = np.zeros((h,w), dtype=np.bool)
         for s in S:
             N = len(s)
             rr, cc = polygon(np.array(s[1:N:2]), np.array(s[0:N:2])) # (y, x)
             M[rr, cc] = 1
         return M

def
segToMask
(
S
,
h
,
w
)
:
M
=
np
.
zeros
(
(
h
,
w
)
,
dtype
=
np
.
bool
)
for
s
in
S
:
N
=
len
(
s
)
rr
,
cc
=
polygon
(
np
.
array
(
s
[
1
:
N
:
2
]
)
,
np
.
array
(
s
[
0
:
N
:
2
]
)
)
# (y, x)
M
[
rr
,
cc
]
=
1
return
M