diff --git a/tools/analysis_tools/coco_error_analysis.py b/tools/analysis_tools/coco_error_analysis.py
index fba96cafd2e818afacc43b120793dbb1dd228705..722efe6d31f07ba92ecb14836ccd834d5a318bb0 100644
--- a/tools/analysis_tools/coco_error_analysis.py
+++ b/tools/analysis_tools/coco_error_analysis.py
@@ -12,17 +12,17 @@ from pycocotools.cocoeval import COCOeval
 def makeplot(rs, ps, outDir, class_name, iou_type):
     cs = np.vstack([
         np.ones((2, 3)),
-        np.array([.31, .51, .74]),
-        np.array([.75, .31, .30]),
-        np.array([.36, .90, .38]),
-        np.array([.50, .39, .64]),
-        np.array([1, .6, 0])
+        np.array([0.31, 0.51, 0.74]),
+        np.array([0.75, 0.31, 0.30]),
+        np.array([0.36, 0.90, 0.38]),
+        np.array([0.50, 0.39, 0.64]),
+        np.array([1, 0.6, 0]),
     ])
     areaNames = ['allarea', 'small', 'medium', 'large']
     types = ['C75', 'C50', 'Loc', 'Sim', 'Oth', 'BG', 'FN']
     for i in range(len(areaNames)):
         area_ps = ps[..., i, 0]
-        figure_tile = iou_type + '-' + class_name + '-' + areaNames[i]
+        figure_title = iou_type + '-' + class_name + '-' + areaNames[i]
         aps = [ps_.mean() for ps_ in area_ps]
         ps_curve = [
             ps_.mean(axis=1) if ps_.ndim > 1 else ps_ for ps_ in area_ps
@@ -37,19 +37,145 @@ def makeplot(rs, ps, outDir, class_name, iou_type):
                 ps_curve[k],
                 ps_curve[k + 1],
                 color=cs[k],
-                label=str(f'[{aps[k]:.3f}]' + types[k]))
+                label=str(f'[{aps[k]:.3f}]' + types[k]),
+            )
         plt.xlabel('recall')
         plt.ylabel('precision')
-        plt.xlim(0, 1.)
-        plt.ylim(0, 1.)
-        plt.title(figure_tile)
+        plt.xlim(0, 1.0)
+        plt.ylim(0, 1.0)
+        plt.title(figure_title)
         plt.legend()
         # plt.show()
-        fig.savefig(outDir + f'/{figure_tile}.png')
+        fig.savefig(outDir + f'/{figure_title}.png')
         plt.close(fig)
 
 
-def analyze_individual_category(k, cocoDt, cocoGt, catId, iou_type):
+def autolabel(ax, rects):
+    """Attach a text label above each bar in *rects*, displaying its height."""
+    for rect in rects:
+        height = rect.get_height()
+        if height > 0 and height <= 1:  # for percent values
+            text_label = '{:2.0f}'.format(height * 100)
+        else:
+            text_label = '{:2.0f}'.format(height)
+        ax.annotate(
+            text_label,
+            xy=(rect.get_x() + rect.get_width() / 2, height),
+            xytext=(0, 3),  # 3 points vertical offset
+            textcoords='offset points',
+            ha='center',
+            va='bottom',
+            fontsize='x-small',
+        )
+
+
+def makebarplot(rs, ps, outDir, class_name, iou_type):
+    areaNames = ['allarea', 'small', 'medium', 'large']
+    types = ['C75', 'C50', 'Loc', 'Sim', 'Oth', 'BG', 'FN']
+    fig, ax = plt.subplots()
+    x = np.arange(len(areaNames))  # the areaNames locations
+    width = 0.60  # the width of the bars
+    rects_list = []
+    figure_title = iou_type + '-' + class_name + '-' + 'ap bar plot'
+    for i in range(len(types) - 1):
+        type_ps = ps[i, ..., 0]
+        aps = [ps_.mean() for ps_ in type_ps.T]
+        rects_list.append(
+            ax.bar(
+                x - width / 2 + (i + 1) * width / len(types),
+                aps,
+                width / len(types),
+                label=types[i],
+            ))
+
+    # Add some text for labels, title and custom x-axis tick labels, etc.
+    ax.set_ylabel('Mean Average Precision (mAP)')
+    ax.set_title(figure_title)
+    ax.set_xticks(x)
+    ax.set_xticklabels(areaNames)
+    ax.legend()
+
+    # Add score texts over bars
+    for rects in rects_list:
+        autolabel(ax, rects)
+
+    # Save plot
+    fig.savefig(outDir + f'/{figure_title}.png')
+    plt.close(fig)
+
+
+def get_gt_area_group_numbers(cocoEval):
+    areaRng = cocoEval.params.areaRng
+    areaRngStr = [str(aRng) for aRng in areaRng]
+    areaRngLbl = cocoEval.params.areaRngLbl
+    areaRngStr2areaRngLbl = dict(zip(areaRngStr, areaRngLbl))
+    areaRngLbl2Number = dict.fromkeys(areaRngLbl, 0)
+    for evalImg in cocoEval.evalImgs:
+        if evalImg:
+            for gtIgnore in evalImg['gtIgnore']:
+                if not gtIgnore:
+                    aRngLbl = areaRngStr2areaRngLbl[str(evalImg['aRng'])]
+                    areaRngLbl2Number[aRngLbl] += 1
+    return areaRngLbl2Number
+
+
+def make_gt_area_group_numbers_plot(cocoEval, outDir, verbose=True):
+    areaRngLbl2Number = get_gt_area_group_numbers(cocoEval)
+    areaRngLbl = areaRngLbl2Number.keys()
+    if verbose:
+        print('number of annotations per area group:', areaRngLbl2Number)
+
+    # Init figure
+    fig, ax = plt.subplots()
+    x = np.arange(len(areaRngLbl))  # the areaNames locations
+    width = 0.60  # the width of the bars
+    figure_title = 'number of annotations per area group'
+
+    rects = ax.bar(x, areaRngLbl2Number.values(), width)
+
+    # Add some text for labels, title and custom x-axis tick labels, etc.
+    ax.set_ylabel('Number of annotations')
+    ax.set_title(figure_title)
+    ax.set_xticks(x)
+    ax.set_xticklabels(areaRngLbl)
+
+    # Add score texts over bars
+    autolabel(ax, rects)
+
+    # Save plot
+    fig.tight_layout()
+    fig.savefig(outDir + f'/{figure_title}.png')
+    plt.close(fig)
+
+
+def make_gt_area_histogram_plot(cocoEval, outDir):
+    n_bins = 100
+    areas = [ann['area'] for ann in cocoEval.cocoGt.anns.values()]
+
+    # init figure
+    figure_title = 'gt annotation areas histogram plot'
+    fig, ax = plt.subplots()
+
+    # Set the number of bins
+    ax.hist(np.sqrt(areas), bins=n_bins)
+
+    # Add some text for labels, title and custom x-axis tick labels, etc.
+    ax.set_xlabel('Squareroot Area')
+    ax.set_ylabel('Number of annotations')
+    ax.set_title(figure_title)
+
+    # Save plot
+    fig.tight_layout()
+    fig.savefig(outDir + f'/{figure_title}.png')
+    plt.close(fig)
+
+
+def analyze_individual_category(k,
+                                cocoDt,
+                                cocoGt,
+                                catId,
+                                iou_type,
+                                areas=None):
     nm = cocoGt.loadCats(catId)[0]
     print(f'--------------analyzing {k + 1}-{nm["name"]}---------------')
     ps_ = {}
@@ -67,16 +193,18 @@ def analyze_individual_category(k, cocoDt, cocoGt, catId, iou_type):
     gt = copy.deepcopy(cocoGt)
     child_catIds = gt.getCatIds(supNms=[nm['supercategory']])
     for idx, ann in enumerate(gt.dataset['annotations']):
-        if (ann['category_id'] in child_catIds
-                and ann['category_id'] != catId):
+        if ann['category_id'] in child_catIds and ann['category_id'] != catId:
             gt.dataset['annotations'][idx]['ignore'] = 1
             gt.dataset['annotations'][idx]['iscrowd'] = 1
             gt.dataset['annotations'][idx]['category_id'] = catId
     cocoEval = COCOeval(gt, copy.deepcopy(dt), iou_type)
     cocoEval.params.imgIds = imgIds
     cocoEval.params.maxDets = [100]
-    cocoEval.params.iouThrs = [.1]
+    cocoEval.params.iouThrs = [0.1]
     cocoEval.params.useCats = 1
+    if areas:
+        cocoEval.params.areaRng = [[0**2, areas[2]], [0**2, areas[0]],
+                                   [areas[0], areas[1]], [areas[1], areas[2]]]
     cocoEval.evaluate()
     cocoEval.accumulate()
     ps_supercategory = cocoEval.eval['precision'][0, :, k, :, :]
@@ -91,8 +219,11 @@ def analyze_individual_category(k, cocoDt, cocoGt, catId, iou_type):
     cocoEval = COCOeval(gt, copy.deepcopy(dt), iou_type)
     cocoEval.params.imgIds = imgIds
     cocoEval.params.maxDets = [100]
-    cocoEval.params.iouThrs = [.1]
+    cocoEval.params.iouThrs = [0.1]
     cocoEval.params.useCats = 1
+    if areas:
+        cocoEval.params.areaRng = [[0**2, areas[2]], [0**2, areas[0]],
+                                   [areas[0], areas[1]], [areas[1], areas[2]]]
     cocoEval.evaluate()
     cocoEval.accumulate()
     ps_allcategory = cocoEval.eval['precision'][0, :, k, :, :]
@@ -100,9 +231,17 @@ def analyze_individual_category(k, cocoDt, cocoGt, catId, iou_type):
     return k, ps_
 
 
-def analyze_results(res_file, ann_file, res_types, out_dir):
+def analyze_results(res_file,
+                    ann_file,
+                    res_types,
+                    out_dir,
+                    extraplots=None,
+                    areas=None):
     for res_type in res_types:
         assert res_type in ['bbox', 'segm']
+    if areas:
+        assert len(areas) == 3, '3 integers should be specified as areas, \
+            representing 3 area regions'
 
     directory = os.path.dirname(out_dir + '/')
     if not os.path.exists(directory):
@@ -122,8 +261,12 @@ def analyze_results(res_file, ann_file, res_types, out_dir):
         cocoEval = COCOeval(
             copy.deepcopy(cocoGt), copy.deepcopy(cocoDt), iou_type)
         cocoEval.params.imgIds = imgIds
-        cocoEval.params.iouThrs = [.75, .5, .1]
+        cocoEval.params.iouThrs = [0.75, 0.5, 0.1]
         cocoEval.params.maxDets = [100]
+        if areas:
+            cocoEval.params.areaRng = [[0**2, areas[2]], [0**2, areas[0]],
+                                       [areas[0], areas[1]],
+                                       [areas[1], areas[2]]]
         cocoEval.evaluate()
         cocoEval.accumulate()
         ps = cocoEval.eval['precision']
@@ -131,7 +274,7 @@ def analyze_results(res_file, ann_file, res_types, out_dir):
         catIds = cocoGt.getCatIds()
         recThrs = cocoEval.params.recThrs
         with Pool(processes=48) as pool:
-            args = [(k, cocoDt, cocoGt, catId, iou_type)
+            args = [(k, cocoDt, cocoGt, catId, iou_type, areas)
                     for k, catId in enumerate(catIds)]
             analyze_results = pool.starmap(analyze_individual_category, args)
         for k, catId in enumerate(catIds):
@@ -147,10 +290,18 @@ def analyze_results(res_file, ann_file, res_types, out_dir):
             ps[4, :, k, :, :] = ps_allcategory
             # fill in background and false negative errors and plot
             ps[ps == -1] = 0
-            ps[5, :, k, :, :] = (ps[4, :, k, :, :] > 0)
+            ps[5, :, k, :, :] = ps[4, :, k, :, :] > 0
             ps[6, :, k, :, :] = 1.0
             makeplot(recThrs, ps[:, :, k], res_out_dir, nm['name'], iou_type)
+            if extraplots:
+                makebarplot(recThrs, ps[:, :, k], res_out_dir, nm['name'],
+                            iou_type)
         makeplot(recThrs, ps, res_out_dir, 'allclass', iou_type)
+        if extraplots:
+            makebarplot(recThrs, ps, res_out_dir, 'allclass', iou_type)
+            make_gt_area_group_numbers_plot(
+                cocoEval=cocoEval, outDir=res_out_dir, verbose=True)
+            make_gt_area_histogram_plot(cocoEval=cocoEval, outDir=res_out_dir)
 
 
 def main():
@@ -163,8 +314,24 @@ def main():
         help='annotation file path')
     parser.add_argument(
         '--types', type=str, nargs='+', default=['bbox'], help='result types')
+    parser.add_argument(
+        '--extraplots',
+        action='store_true',
+        help='export extra bar/stat plots')
+    parser.add_argument(
+        '--areas',
+        type=int,
+        nargs='+',
+        default=[1024, 9216, 10000000000],
+        help='area regions')
     args = parser.parse_args()
-    analyze_results(args.result, args.ann, args.types, out_dir=args.out_dir)
+    analyze_results(
+        args.result,
+        args.ann,
+        args.types,
+        out_dir=args.out_dir,
+        extraplots=args.extraplots,
+        areas=args.areas)
 
 
 if __name__ == '__main__':