[论文解读] 图像分割 & 目标识别 | Selective Search和python实现| <Selective Search for Object Recognition>

前言

此处只是叙述ss(selective search method)主体功能, 并且使用网上的简易实现版本-python代码,方便讲解.
官方MATLAB版本和<Selective search for object recognition> 具体论文可以参见文末论文地址 reference 1

1 图像分割和目标识别过程:

1.1 训练过程

在这里插入图片描述
(1) selective search提取候选框:

step1: SS Method:

先过分割形成不同尺度的初始模块区域(region, 初始化方法即Felzenszwalb方法-具体参见<Efficient Graph-Based Image Segmentation>) ---------> 然后通过颜色(color)、纹理(texture)、大小(size)等相似度判断策略, 对相邻区域(region)进行合并 ---------> 不断迭代直到没有可合并区域.---------> 得到不同目标物体的分割图像, 其所在min bounding box即为候选区域

在这里插入图片描述
tips:
绿色->正样本
蓝色-> 负样本

step2: 区分正负样本:

  • 正样本:
    ground-truth(GT,真实标记区域)作为正样本
  • 负样本:
    计算每个候选区域与GT之间的重合度,如果区域A与GT的重合度在20-50%之间,而且A与其他的任何一个已生成的负样本之间的重合度不大于70%,则A被采纳为负样本,否则丢弃A,继续判别下一个区域

(2) 提取特征层:
第一部分中将正样本区域和负样本区域都提取出来了,现在就需要提取每个区域的特征了.
paper在实现过程中,主要使用bag-of-words的方法用于目标表识别. 相比于之前的实现方法,主要的创新点在: 使用多样的color-SIFT特征以及精细的spatial pyramid divsion方法。

  • 使用单尺度(σ=1.2)特征金字塔。
  • 使用SIFT、2个colour SIFT、 Extended OpponentSIFT、RGB-SIFT特征,在四层金字塔模型 1×1、2×2、3×3、4×4,提取特征,最终可以得到一个维的特征向量.

(3) SVM 分类训练:

  • 上一步中,每个区域的特征提取出来了,真实类别标签也知道,那这就是一个2分类问题;
  • 分类器这里采用了带有Histogram Intersection Kernel的SVM分类器进行分类

(4) 训练反馈:
第三部分将分类器训练好了,训练好了就完了吗? NO! 现在流行一种反馈机制,SVM训练完成了,将得到每个训练图像每个候选区域的软分类结果(每个区域都会得到一个属于正样本的概率),一般如果概率大于0.5将被认为是目标,否则被认为是非目标,如果完全分类正确,所有的正样本的SVM输出概率都大于0.5,所有负样本的SVM输出概率都小于0.5,但是最常见的情况是有一部分的负样本的输入概率也是大于0.5的,我们会错误地将这样样本认为是目标,这些样本就称之为"False Positives".

我们这里就是想把这些"False Positives"收集起来,以刚才训练得到的SVM的权值作为其初始权值,对SVM进行二次训练,经过二次训练的SVM的分类准确度一般会有一定的提升

1.2 测试过程

测试的过程基本和训练过程相同:
首先用SS方法得到测试图像上候选区域
–> 然后提取每个区域的特征向量
–> 送入已训练好的SVM进行软分类
–> 将这些区域按照概率值进行排序
–> 把概率值小于0.5的区域去除
–> 对那些概率值大于0.5的,计算每个区域与比它分数更高的区域之间的重叠程度,如果重叠程度大于30%,则把这个区域也去除了
–> 最后剩下的区域为目标区域.

2 论文最大亮点 - selective search method

2.1 主要思路:

输入一张图片,首先通过图像分割的方法(如大名鼎鼎的felzenszwalb算法, 参见reference 2)获得很多小的区域,然后对这些小的区域不断进行合并(通过相似性公式计算, 相邻区域相似度高的合并),一直到无法合并为止。此时这些原始的小区域和合并得到的区域的就是我们得到的bounding box.
在这里插入图片描述
算法分为如下几个大步:

  1. 生成原始的区域集R(利用felzenszwalb算法)
  2. 计算区域集R里每个相邻区域的相似度S={s1,s2,…}
  3. 找出相似度最高的两个区域,将其合并为新集,添加进R
  4. 从S中移除所有与第3步中有关的子集
  5. 计算新集与所有子集的相似度
  6. 跳至第三步,不断循环,合并,直至S为空(到不能再合并时为止)

整体计算过程 已经在1-(1)-step1中描述, 相关流程伪代码参见如下:
在这里插入图片描述

2.2 核心实现

2.2.1 分析了颜色空间

paper要考虑不同的场景和照明条件。因此,paper在具有一系列不变性的颜色空间中执行分层分组算法。
具体地说,以递增的不变性来描述以下颜色空间:
(1)RGB,
(2)强度(灰度图像)I,
(3)Lab,
(4)归一化RGB中的rg通道 + 强度通道I,表示为rgI,
(5)HSV,
(6)标准化的RGB表示为rgb,
(7)C , 这是一个对比色空间,其中强度通道被划分出去,
(8)来自HSV的色调通道H。

下表中列出了在 光线强度/阴影/光线明亮不同条件下, 具体的不变性特性结果:
在这里插入图片描述注:
“+”:具有不变性
“-”:不具有不变性
“+/-”: 在此空间或者通道具有部分不变性
“1/3”: 1/3 通道可以说的上具有不变性


这一节提供了调参的一些思路,分析了不同颜色空间各通道的特点,这有利于我们在面对自己的实际任务时明白要尝试的方向. 但是paper中算法的实现是使用的是单一颜色空间和通道的(并不是所有颜色空间的组合).

2.2.2 相似性判断标准的多样性

关于两张图片相似度计算:
论文中考虑了四种相似度 – 颜色,纹理,尺寸,以及交叠。其中所有的标准的取值输入范围都是在[0, 1] 之间. 其中颜色和纹理相似度,通过获取两个区域的直方图的交集,来判断相似度。

- 颜色相似度计算公式:

在这里插入图片描述
说明:
step1: 每一个颜色通道通过25个bins(柱状条)计算colour histograms(颜色分布直方图). 如果一个region ri是3通道(例如说RGB)的, 则共有75个bins, 即下面面的Ci中 n = 75.
在这里插入图片描述
Ci表示:region ricolour histogram

step2: 计算相邻region的ri, rj颜色相似度: 就是求和Ci, Cj两个合集中各个bins的最小值的和.

step3: 合并ri, rj之后的新的region rtcolour histogram, 可以通过下式子更新:
在这里插入图片描述
size(ri) 表示ri 的bounding box面积
size(rj) 表示rj 的bounding box面积

- 纹理相似度:

在这里插入图片描述
step1: 选择同一个region ri的单通道图像, 令σ = 1并计算在8个方向的高斯导数, 从而形成texture histogram(纹理分布直方图). 从直方图中每个方向各选择10个bins, 组成集合. 如果, 使用的是3通道的图像, 则共有n = 8x10x3=240 (个bins). 即为:
在这里插入图片描述
step2: 与色彩相似度类似, 计算纹理相似度的公式表示如下:
在这里插入图片描述

step3: 用于更新合并 ri, rj形成新的区域的rt的文理直方图方式, 和颜色相似度类似, 不再赘述.

- 尺寸相似度:

计量标准的作用,就是促使更多的小区域尽快合并(面积越小, 相似度越高; 面积越大或者差别越大, 相似度相对会小)
在这里插入图片描述
size(ri) 表示ri 的bounding box面积
size(rj) 表示rj 的bounding box面积
size(im) 表示的是整幅图像的面积大小.

- 交叠相似度:

在这里插入图片描述
其中
在这里插入图片描述表示ri, rj 交集的bounding box面积

- 最后的相似度计算总公式, 是四种相似度的加和。

在这里插入图片描述
ai 表示各个部分的权重. paper并未使用

2.2.3 初始region选择的多样性

初始化分割区域的方法有多种, paper中说当时最好的还是(paper毕竟还是2011-2012年, Felzenszwalb的实现和提出恐怕要追溯到2004年了 ),
P. F. Felzenszwalb and D. P. Huttenlocher. Efficient GraphBased Image Segmentation. IJCV, 59:167–181, 2004, 即Felzenszwalb method, 源码参见 链接
另外, 其实skimage有对应的具体实现, 即:

from skimage.segmentation import felzenszwalb

python实现版 - 可以参见 链接

3 python源码说明

3.1 相似度的实现
def _sim_colour(r1, r2):
    """
        calculate the sum of histogram intersection of colour
    """
    return sum([min(a, b) for a, b in zip(r1["hist_c"], r2["hist_c"])])
 
 
def _sim_texture(r1, r2):
    """
        calculate the sum of histogram intersection of texture
    """
    return sum([min(a, b) for a, b in zip(r1["hist_t"], r2["hist_t"])])
 
 
def _sim_size(r1, r2, imsize):
    """
        calculate the size similarity over the image
    """
    return 1.0 - (r1["size"] + r2["size"]) / imsize
 
 
def _sim_fill(r1, r2, imsize):
    """
        calculate the fill similarity over the image
    """
    bbsize = (
        (max(r1["max_x"], r2["max_x"]) - min(r1["min_x"], r2["min_x"]))
        * (max(r1["max_y"], r2["max_y"]) - min(r1["min_y"], r2["min_y"]))
    )
    return 1.0 - (bbsize - r1["size"] - r2["size"]) / imsize
3.2 主函数
def selective_search(
        im_orig, scale=1.0, sigma=0.8, min_size=50):
    '''Selective Search
    Parameters
    ----------
        im_orig : ndarray
            Input image
        scale : int
            Free parameter. Higher means larger clusters in felzenszwalb segmentation.
        sigma : float
            Width of Gaussian kernel for felzenszwalb segmentation.
        min_size : int
            Minimum component size for felzenszwalb segmentation.
    Returns
    -------
        img : ndarray
            image with region label
            region label is stored in the 4th value of each pixel [r,g,b,(region)]
        regions : array of dict
            [
                {
                    'rect': (left, top, width, height),
                    'labels': [...],
                    'size': component_size
                },
                ...
            ]
    '''
    assert im_orig.shape[2] == 3, "3ch image is expected"
 
    # load image and get smallest regions
    # region label is stored in the 4th value of each pixel [r,g,b,(region)]
    img = _generate_segments(im_orig, scale, sigma, min_size)
 
    if img is None:
        return None, {}
 
    imsize = img.shape[0] * img.shape[1]
    R = _extract_regions(img)
 
    # extract neighbouring information
    neighbours = _extract_neighbours(R)
 
    # calculate initial similarities
    S = {}
    for (ai, ar), (bi, br) in neighbours:
        S[(ai, bi)] = _calc_sim(ar, br, imsize)
 
    # hierarchal search
    while S != {}:
 
        # get highest similarity
        i, j = sorted(S.items(), key=lambda i: i[1])[-1][0]
 
        # merge corresponding regions
        t = max(R.keys()) + 1.0
        R[t] = _merge_regions(R[i], R[j])
 
        # mark similarities for regions to be removed
        key_to_delete = []
        for k, v in list(S.items()):
            if (i in k) or (j in k):
                key_to_delete.append(k)
 
        # remove old similarities of related regions
        for k in key_to_delete:
            del S[k]
 
        # calculate similarity set with the new region
        for k in [a for a in key_to_delete if a != (i, j)]:
            n = k[1] if k[0] in (i, j) else k[0]
            S[(t, n)] = _calc_sim(R[t], R[n], imsize)
 
    regions = []
    for k, r in list(R.items()):
        regions.append({
            'rect': (
                r['min_x'], r['min_y'],
                r['max_x'] - r['min_x'], r['max_y'] - r['min_y']),
            'size': r['size'],
            'labels': r['labels']
        })
 
    return img, regions

说明:

( 1)作用
通过图像分割的方法,从原始图像中提取小区域。
(2)输入
im_orig
原始图片,数据类型为ndarray。
scale
图像分割的集群程度。
值越大,意味集群程度越高,分割的越少,获得子区域越大,默认为1。
数据类型为int。
sigma
图像分割前,会先对原图像进行高斯滤波去噪,sigma即为高斯核的大小,默认为0.8。
数据类型为float。
min_size
最小的区域像素点个数。当小于此值时,图像分割的计算就停止,默认为20。
数据类型为int。
(3)输出
img
具有区域标签的图片,数据类型为ndarray。
img数组的形状为(im_orig_height, im_orig_width, 4)
其中存储的像素信息为:[r, g, b, (region)],region是指区域标签。
regions
区域列表
regions的结构如下:
[
{‘rect’: (x_l, y_d, width, height), ‘size’: size, ‘labels’: labels_list},

]
变量名注释
‘rect’:
x_l:区域左下角的x值;
y_d:区域左下角的y值;
width:区域的宽;
height:区域的高。
通过这四个值,我们就能够确定区域的大小及位置。
‘size’:区域的尺寸。
‘labels’:区域的标签,是列表。

Reference

  1. [SS-Method]论文/项目 Selective search for object recognition. | [IJCV, 2013] |[pdf] |[matlab code]
  2. Felzenszwalb图像分割
  3. selective search - python源码分析
  4. selective search - python源码实现地址
  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI扩展坞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值