2 非极大值抑制(NMS)

非极大值抑制(Non-Maximum Suppression,NMS[1])可以正面地表述为局部最大搜索(Local Maximum Search), 其中局部最大值大于其所有邻居 (不包括其自身)。本质上是搜索局部极大值,抑制非极大值元素。

NMS 在计算机视觉领域有着非常重要的应用,如视频目标跟踪、数据挖掘、3D重建、目标识别以及纹理分析等。[2]

2.1 1D NMS

Straightforward Implementation

NMS 的简单实现由两个嵌套循环组成, 其中外部循环遍历所有像素, 内部循环针对外部循环的所有邻居测试其候选项。一旦邻居强度超过当前候选, 内部循环就会中止。显然, 该算法需要对每个像素做 2n 次比较, 而不需要提前中止。在最坏的情况下, 中止不能降低复杂性。这可以通过将算法应用于强度趋势来看出。由于一侧的像素总是小于候选像素, 因此内部循环会在第 (n + 1) 迭代处中止, 从而使每个像素有 n + 1 次比较。因此, 比较像素的最坏情况数是 O(n)。关于时间复杂度分析的具体内容可查看原论文[1]。下面我以一张图片来说明 NMS:

import numpy as np
from matplotlib import pyplot as plt
np.set_printoptions(2)     # 修改了 NumPy 的打印精度
# 指定默认字体, 为在 Matplotlib 中显示中文,设置特殊字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号 '-' 显示为方块的问题

%matplotlib inline

img_name = '../images/catdog.jpg'
img = plt.imread(img_name)

载入图片之后,我们先讨论 3-Neighborhood。

3-近邻

我们先将原图片拉直为一个向量,下面我们定义 NMS:

I = img.flatten()[:30]
w = len(I)
maximumat = []
i = 1
while i + 1 < w:
    if I[i] > I[i+1] and I[i] >= I[i-1]:  # I[i] 是极大值
        maximumat.append(i)
    else:
        i += 1
        while i + 1 < w and I[i] <= I[i+1]:
            i += 1
        if i + 1 < w:
            maximumat.append(i)
    i += 2

plt.plot(I, 'y--')
plt.scatter(maximumat, I[maximumat])
plt.axis('off')
for _x, _y in enumerate(I):
    plt.text(_x, _y, str(_x))
前 30 个像素点的极大值分布图:图中蓝色圆点表示 3 近邻的极大值点

为了更加形象,下面我们将展示 NMS 处理前后的图像:

I = img.flatten()
w = len(I)
maximumat = []
i = 1
while i + 1 < w:
    if I[i] > I[i+1] and I[i] >= I[i-1]:
        maximumat.append(i)
    else:
        i += 1
        while i + 1 < w and I[i] <= I[i+1]:
            i += 1
        if i + 1 < w:
            maximumat.append(i)
    i += 2
K = img[:].flatten()
K[maximumat] = 0

img1 = K.reshape(img.shape)  # 去除极大值点后组成的图像
img2 = img - img1   # 极大值点组成的图像
plt.figure(figsize=(10, 10))
plt.subplot(131)
plt.imshow(img)
plt.title('原图')
plt.axis('off')
plt.subplot(132)
plt.imshow(img1)
plt.title('去除极大值点图')
plt.axis('off')
plt.subplot(133)
plt.imshow(img2)
plt.title('极大值点图')
plt.axis('off')
plt.show()
NMS 处理前后对比

2.2 动态块算法:(2n+1)-近邻

def nms(y, n):
    '''
    参数
    ===========
    y:: 一维数组
    n:: 近邻数
    
    返回
    ==========
    N-近邻 的 NMS
    '''
    i = 0
    maximumat = []
    w = len(y)
    while 2 * n + i < w:

        if I[i+n] > max(I[i+n+1:i+2*n]) and I[i+n] >= max(I[i:i+n]):
            maximumat.append(i+n)
        else:
            i += 1
            while 2 * n + i < w and I[i+n] < max(I[i+n+1:i+2*n]):
                i += 1
            if 2 * n + i < w:
                maximumat.append(i+n)
        i += n
    return maximumat

为了方便我将可视化的代码放入函数:

def plot(img, img1, img2):
    plt.figure(figsize=(10, 10))
    plt.subplot(131)
    plt.imshow(img)
    plt.title('原图')
    plt.axis('off')
    plt.subplot(132)
    plt.imshow(img1)
    plt.title('去除极大值点图')
    plt.axis('off')
    plt.subplot(133)
    plt.imshow(img2)
    plt.title('极大值点图')
    plt.axis('off')
    plt.show()
import numpy as np
from matplotlib import pyplot as plt
np.set_printoptions(2)     # 修改了 NumPy 的打印精度
# 指定默认字体, 为在 Matplotlib 中显示中文,设置特殊字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号 '-' 显示为方块的问题

%matplotlib inline

img_name = '../images/catdog.jpg'
img = plt.imread(img_name)
I = img.flatten()
n = 3
maximumat = nms(I, n)
K = img[:].flatten()
K[maximumat] = 0

img1 = K.reshape(img.shape)  # 去除极大值点后组成的图像
img2 = img - img1   # 极大值点组成的图像
plot(img, img1, img2)
n=3
I = img.flatten()
n = 100
maximumat = nms(I, n)
K = img[:].flatten()
K[maximumat] = 0

img1 = K.reshape(img.shape)  # 去除极大值点后组成的图像
img2 = img - img1   # 极大值点组成的图像
plot(img, img1, img2)
n=100

  1. Neubeck A, Van Gool L. Efficient Non-Maximum Suppression[C]. international conference on pattern recognition, 2006: 850-855.

  2. 非极大值抑制(Non-Maximum Suppression,NMS),顾名思义就是抑制不是极大值的元素,可以理解为局部最大搜索。这个局部代表的是一个邻域,邻域有两个参数可变,一是邻域的维数,二是邻域的大小。这里不讨论通用的 NMS 算法(参考论文《Efficient Non-Maximum Suppression》 对 1 维和 2 维数据的 NMS 实现),而是用于目标检测中提取分数最高的窗口的。例如在行人检测中,滑动窗口经提取特征,经分类器分类识别后,每个窗口都会得到一个分数。但是滑动窗口会导致很多窗口与其他窗口存在包含或者大部分交叉的情况。这时就需要用到 NMS 来选取那些邻域里分数最高(是行人的概率最大),并且抑制那些分数低的窗口。@http://www.cnblogs.com/makefile/p/nms.html © 康行天下

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容