OpenCV 例程 300篇247. 特征检测之最大稳定极值区域(MSER)

Posted YouCans

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV 例程 300篇247. 特征检测之最大稳定极值区域(MSER)相关的知识,希望对你有一定的参考价值。

『youcans 的 OpenCV 例程300篇 - 总目录』


【youcans 的 OpenCV 例程 300篇】247. 特征检测之最大稳定极值区域(MSER)


1. 最大稳定极值区域(MSER)

最大稳定极值区域(MSER-Maximally Stable Extremal Regions),是一种检测图像文本区域的算法,基于分水岭的思想对图像进行斑点区域检测。
MSER算法具有仿射不变性,对灰度的变化具有较强的鲁棒性,但检测准确率低于深度学习方法,主要用于自然场景的文本检测的前期阶段。

MSER算法对灰度图像进行阈值处理,阈值从0到255依次递增,类似于分水岭算法中的水平面的上升。最低点首先被淹没,随着水面的上升逐渐淹没整个山谷,直到所有的点全部被淹没。在不同阈值下,如果某些连通区域不变或变化很小,则该区域称为最大稳定极值区域。

Q i Q_i Qi表示阈值为 i 时的某一连通区域,则变化率 q i q_i qi 为:

q i = ∣ Q i + Δ − Q i ∣ ∣ Q i ∣ q_i= \\frac|Q_i+\\Delta - Q_i||Q_i| qi=QiQi+ΔQi

当变化率 q i q_i qi 为局部极小值时,则 Q i Q_i Qi为最大稳定极值区域。


2. OpenCV 的 cv::MSER类

OpenCV中提供了MSER类,MSER类继承了cv::Feature2D类。

在Python语言中,OpenCV提供了MSER类的接口函数cv.MSER.create实例化MSER类,成员函数detectRegions检测并返回找到的所有区域。

函数原型:

cv.MSER.create([, delta, min_area, max_area, max_variation, min_diversity, max_evolution, area_threshold, min_margin=, edge_blur_size]) → retval

cv.MSER_create([, delta, min_area, max_area, max_variation, min_diversity, max_evolution, area_threshold, min_margin=, edge_blur_size]) → retval

mser.detectRegions(image[, ]) → msers, bboxes

参数说明:

● image:输入图像,8位单通道、3通道或4通道图像
● msers:检测到的所有区域的点集,列表格式
● bboxes:检测到的所有区域的边界矩形,列表格式
● delta:灰度值的变化量,变化率公式中的 Δ \\Delta Δ,默认值5
● min_area:区域最小面积阈值,默认值60
● max_area:区域最大面积阈值,默认值14400
● max_variation:最大变化率,默认值0.25

注意问题:

⒈函数cv.MSER.create或cv.MSER_create实例化MSER类,创建一个MSER对象mser。在OpenCV的不同版本中可能只允许其中一种方式。
⒉OpenCV的部分版本中,参数delta、min_area、max_area、max_variation的格式为 _delta、_min_area、_max_area、_max_variation。
⒊成员函数detectRegions检测并返回找到的所有区域,输出参数msers、bboxes都是列表格式,列表长度为N,对应于找到的N个区域。
⒋列表msers的第i个元素msers[i]是形如(k,2)的Numpy数组,表示第i个区域点集,k是第i个区域的像素点数量。msers[i]的每一行msers [i][k,:]表示第i个区域的第k个像素点的坐标[x,y]。
⒌列表bboxes的第i个元素bboxes[i]是形如(4,)的Numpy数组,表示第i个区域的垂直边界矩形。数组元素[x, y, w, h]分别表示左上角顶点坐标 (x,y)、矩形宽度w和高度h。


3. 例程14.29:特征检测之最大稳定极值区域(MSER)

本例程示例MSER检测最大稳定极值区域,并通过NMS删除重复结果。MSER检测到4082个区域,NMS删除重复结果后减少到了149个区域。

# 14.29 特征检测之最大稳定极值区域(MSER)
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

def NonMaxSuppression(boxes, thresh=0.5):
    x1, y1 = boxes[:,0], boxes[:,1]
    x2, y2 = boxes[:,0]+boxes[:,2], boxes[:,1]+boxes[:,3]
    area = boxes[:,2] * boxes[:,3]  # 计算面积
    # 删除重复的矩形框
    pick = []
    idxs = np.argsort(y2)  # 返回的是右下角坐标从小到大的索引值
    while len(idxs) > 0:        
        last = len(idxs) - 1  # 将最右下方的框放入pick 数组
        i = idxs[last]
        pick.append(i)
        # 剩下框中最大的坐标(x1Max,y1Max)和最小的坐标(x2Min,y2Min)
        x1Max = np.maximum(x1[i], x1[idxs[:last]])
        y1Max = np.maximum(y1[i], y1[idxs[:last]])
        x2Min = np.minimum(x2[i], x2[idxs[:last]])
        y2Min = np.minimum(y2[i], y2[idxs[:last]])
        # 重叠面积的占比
        w = np.maximum(0, x2Min-x1Max+1)
        h = np.maximum(0, y2Min-y1Max+1)
        overlap = (w * h) / area[idxs[:last]]
        # 根据重叠占比的阈值删除重复的矩形框
        idxs = np.delete(idxs, np.concatenate(([last], np.where(overlap > thresh)[0])))
    return boxes[pick]  # x, y, w, h

if __name__ == '__main__':
    img = cv.imread("../images/Fig0944a.tif", flags=1)
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    height, width = gray.shape[:2]

    # 创建 MSER 对象,检测 MSER 区域
    # mser = cv.MSER_create(_min_area=500, _max_area=20000)
    mser = cv.MSER.create(_min_area=306, _max_area=20000)  # 实例化 MSER
    regions, boxes = mser.detectRegions(gray)  # 检测并返回找到的 MSER
    lenMSER = len(regions)  # 4082
    print("Number of detected MSER: ", lenMSER)
    # print(regions[0].shape, boxes[0].shape)

    imgMser1 = img.copy()
    imgMser2 = img.copy()
    for i in range(lenMSER):
        # 绘制 MSER 凸壳
        points = regions[i].reshape(-1, 1, 2)  # (k,2) -> (k,1,2)
        hulls = cv.convexHull(points)
        cv.polylines(imgMser1, [hulls], 1, (255,0,0), 2)  # 绘制凸壳 (x,y)
        # 绘制 MSER 矩形框
        x, y, w, h = boxes[i]  # 区域的垂直矩形边界框
        cv.rectangle(imgMser2, (x,y), (x+w,y+h), (0,0,255), 2)

    # 非最大值抑制 (NMS)
    imgMser3 = img.copy()
    nmsBoxes = NonMaxSuppression(boxes, 0.6)
    lenNMS = len(nmsBoxes)  # 149
    print("Number of NMS-MSER: ", lenNMS)
    for i in range(lenNMS):
        # 绘制 NMS-MSER 矩形框
        x, y, w, h = nmsBoxes[i]  # NMS 矩形框
        cv.rectangle(imgMser3, (x,y), (x+w,y+h), (0,255,0), 2)

    plt.figure(figsize=(9, 6))
    plt.subplot(131), plt.title("MSER regions")
    plt.axis('off'), plt.imshow(cv.cvtColor(imgMser1, cv.COLOR_BGR2RGB))
    plt.subplot(132), plt.title("MSER boxes")
    plt.axis('off'), plt.imshow(cv.cvtColor(imgMser2, cv.COLOR_BGR2RGB))
    plt.subplot(133), plt.title("NMS-MSER boxes")
    plt.axis('off'), plt.imshow(cv.cvtColor(imgMser3, cv.COLOR_BGR2RGB))
    plt.tight_layout()
    plt.show()


运行结果:

Number of detected MSER: 4082
Number of NMS-MSER: 149

程序说明
程序运行结果如图17-9所示。
⑴ 子图1绘制MSER算法检测到的最大稳定极值区域,检测结果取决于区域面积的阈值设置。子图2绘制检测到的MSER区域的垂直边界矩形。
⑵ 子图3通过NMS方法删除了检测到的MSER区域中的重复结果。MSER算法检测到4082个区域,NMS去重后减少为 149 个区域。


4. 非极大值抑制 NMS

非极大值抑制(non maximum suppression, nms)是通常用于目标检测算法,作用是去除重复的区域,就是抑制不是极大值的元素,在这里就是去除和想要的框重叠部分过大的框。

NMS的基本思想是将所有框按得分进行排序,然后无条件保留其中得分最高的框,然后遍历其余框找到和当前最高分的框的重叠面积(IOU)大于一定阈值的框,并删除。然后继续这个过程,找另一个得分高的框,再删除和其IOU大于阈值的框,一直循环直到所有的框都被处理。

在目标检测中,常用非极大值抑制算法(NMS)对生成的大量候选框进行后处理,在 faster R-CNN 中,每一个 bbox 都有一个得分,然后使用 NMS 去除冗余的候选框,得到最具代表性的 bbox,以加快目标检测的效率。

NMS的具体实现流程为:

  • 根据候选框的类别分类概率(得分),按最高到最低将BBox排序,例如:A>B>C>D>E>F
  • 先标记最大概率矩形框A是要保留下来的,即A的分数最高,则无条件保留
  • 将B~E分别与A求重叠率IoU(两框的交并比),假设B、D与A的IoU大于设定的阈值,那么B和D可以认为是重复标记被剔除
  • 继续从剩下的矩形框C、E、F中选择概率最大的C,标记为要无条件保留下来的框,然后分别计算C与E、F的重叠度,扔掉重叠度超过设定阈值的矩形框
  • 就这样一直重复下去,直到剩下的矩形框没有了,得到所有要保留下来的矩形框

【本节完】

版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/125724395)
Copyright 2022 youcans, XUPT
Crated:2022-11-28

以上是关于OpenCV 例程 300篇247. 特征检测之最大稳定极值区域(MSER)的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV 例程 300篇246. 特征检测之ORB算法

OpenCV 例程 300篇246. 特征检测之ORB算法

OpenCV 例程 300篇243. 特征检测之 FAST 算法

OpenCV 例程 300篇243. 特征检测之 FAST 算法

OpenCV 例程 300篇243. 特征检测之 FAST 算法

youcans 的 OpenCV 例程 300篇244. 特征检测之 BRIEF 特征描述