How to reduce the number of boxes/regions created in MSER

1.3k views Asked by At

I have been trying to get less boxes with MSER since I have too many boxes created on the same element repeatedly with very little pixel differences. My code is as below:

 ## Get mser, and set parameters

   _delta = 10 
_min_area = 250 
_max_area = 800
_max_variation = 10.0 
_min_diversity = 30.0
_max_evolution = 10 
_area_threshold = 12.0
_min_margin = 2.9 
_edge_blur_size = 3  

mser = cv2.MSER_create(_delta,_min_area, _max_area, _max_variation,
_min_diversity,_max_evolution, _area_threshold, _min_margin, _edge_blur_size)

and then

 ## Do mser detection, get the coodinates and bboxes on the original  image
      gray = cv2.cvtColor(final, cv2.COLOR_BGR2GRAY)
       coordinates, bboxes = mser.detectRegions(gray)

After this , I see there are 26K boxes created. Which amongst the parameters can be tuned for lesser number of regions(since they are overlapping a lot). Kindly help?

1

There are 1 answers

0
Yonatan Simson On

_delta is the most important parameter for reducing the number of boxes. Try raising it to 25. The higher the _delta the less blobs you will get.

  • _min_area - The smallest blob
  • _max_area - The largest blob
  • _min_diversity - Raise to reduce the number of overlapping blobs
  • _max_variation - Raise to reduce areas with high variance

For more information

After that I would checking the bboxes to filter out over lapping blobs

Code Example

import cv2
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
img = cv.imread('input_img.png')
iou_th = 0.95

mser = cv2.MSER_create(_delta=10, _min_area=1000, _max_area=int(0.1 * np.pi * (img.shape[0] /2)**2), _max_variation=0.1)
regions, bboxes = mser.detectRegions(img)
hulls = [cv2.convexHull(p.reshape(-1, 1, 2)) for p in regions]

# Debug plot
img_ = img.copy()
cv2.polylines(img_, hulls, 1, (255, 0, 0), thickness=1)
fig, ax = plt.subplots(figsize=(10, 6))
ax.imshow(img_)
ax.set_title('MSER with overlapping regions')

size_dict = {k: len(region) for k, region in enumerate(regions)}
# Cull overlapping blobs
graph = nx.Graph()
graph.add_nodes_from(range(len(hulls)))
for i, cnt in enumerate(hulls):
    for j, cnt in enumerate(hulls):
        if i >= j:
            continue
        box_i = bboxes[i]
        box_j = bboxes[j]
        tl_i = box_i[:2]
        tl_j = box_j[:2]

        br_i = tl_i + box_i[2:]
        br_j = tl_j + box_j[2:]

        tl = np.maximum(tl_i, tl_j)
        br = np.minimum(br_i, br_j)
        intersected_rect = br - tl
        intersection = np.prod(intersected_rect) if intersected_rect[0] > 0 and intersected_rect[1] > 0 else 0
        union = np.prod(box_i[2:]) + np.prod(box_j[2:]) - intersection
        iou = intersection / union
        if iou > iou_th:
            graph.add_edge(i, j, iou=iou)

# make list of unique regions - pick the smallest region
trees = list(nx.connected_component_subgraphs(graph))
unique_blobs = []
for tree in trees:
    # Choose the smallest region
    smallest_idx = None
    smallest_blob = np.inf
    for node in tree.nodes():
        if size_dict[node] < smallest_blob:
            smallest_blob = size_dict[node]
            smallest_idx = node

        unique_blobs.append(smallest_idx)
unique_blobs = unique_blobs
hulls = [hulls[k] for k in unique_blobs]
regions = [regions[k] for k in unique_blobs]
bboxes = [bboxes[k] for k in unique_blobs]
size_dict = {k: len(region) for k, region in enumerate(regions)}

# debug plot
img_ = img.copy()
cv2.polylines(img_, hulls, 1, (255, 0, 0), thickness=1)
fig, ax = plt.subplots(figsize=(10, 6))
ax.imshow(img_)
ax.set_title('MSER with unique regions')