分类 计算机视觉 下的文章

摘要

之前在SIFT算法中,有一个加速操作是使用图像金字塔,即不断对图像进行降采样。按照算法的思想表明:降采样后,标准差为$\sigma$的高斯模糊图像标准差会减半,得到标准差为$1/2\sigma$的高斯模糊图像

这里我不知道该如何证明....网上也没有相关资料,所以暂时采用数值解去验证这个说法。

实验过程

代码贴在最后,主要思路是比较两张图像:一张是先降采样一倍再用$\sigma$高斯模糊的图像;另一张是先使用$2\sigma$进行高斯模糊,再在模糊的图像上进行一倍降采样。

首先可视化这两张图,肉眼查看之间的差距,确实差距还是挺小的。此处$\sigma=30$(忽略窗口的值,那里标错了~)

image-20230709221257222

为了对比,这里把原图分别使用$\sigma$和$2\sigma$进行高斯模糊的结果也可视化了出来。这两张图就明显存在差异,这说明对高斯模糊过的图像降采样,确实会对其$sigma$产生影响

image-20230709221347242

image-20230709221357634

接着最早的两张图做差并画出来,可以看到形成了一个类似边缘检测的图像。这说明“先降采样再$\sigma$高斯模糊”跟“先$2\sigma$高斯模糊再降采样”这两个操作不完全等价。

为什么看上去是边缘检测图像?其实也很好理解,对于不同$\sigma$的高斯模糊图像相减,就是对高斯模糊图像微分,即DOG,DOG和LOG又只差一个常数倍,所以等效边缘检测了~

image-20230709221740842

接下来再探究“先$2\sigma$高斯模糊再降采样”得到的模糊图像的标准差到底是多少。最暴力的方式就是搜索,我们在降采样的图像上使用不同的$\sigma$进行遍历,画出delta的范数变化情况。最后我们发现:最接近的$\sigma_0$就是$\sigma$!

5d45f0cae88e5a5ae970dc07cc4d735

至此,我们知道上述的两个操作并不等价,但是它们足够接近。所以SIFT算法通过这种近似去做图像金字塔,大幅提高运算效率

代码

import cv2

Path = "C:\\Users\\Axuanz\\Desktop\\download.png"

if __name__ == "__main__":
    img = cv2.imread(Path,cv2.IMREAD_GRAYSCALE)

    sigma = 30

    ksize1 = sigma*6+1
    ksize2 = int(sigma/2*6+1)

    blur1 = cv2.GaussianBlur(img,ksize=(ksize1,ksize1),sigmaX=sigma)
    blur1 = cv2.pyrDown(blur1)

    downsample_img = cv2.pyrDown(img)
    blur2 = cv2.GaussianBlur(downsample_img,ksize=(ksize2,ksize2),sigmaX=sigma/2)

    blur3 = cv2.GaussianBlur(img,ksize=(ksize1,ksize1),sigmaX=sigma)
    blur4 = cv2.GaussianBlur(img,ksize=(ksize2,ksize2),sigmaX=sigma/2)

    delta = blur2 - blur1
    print(cv2.norm(delta))

    cv2.imshow("sigma=10",blur1)
    cv2.imshow("sigma=5",blur2)
    cv2.imshow("blur3",blur3)
    cv2.imshow("blur4",blur4)
    cv2.imshow("delta",delta)
    # cv2.waitKey()

###########################################
    sigma2 = 1
    norm_list = []
    while sigma2 <= sigma:
        _ksize = sigma2*6 + 1
        blur = cv2.GaussianBlur(downsample_img,ksize=(_ksize,_ksize),sigmaX = sigma2)
        delta = blur - blur1
        
        norm = cv2.norm(delta)
        print(f"sigma2 = {sigma2},delta norm ={norm}")

        norm_list.append(norm)
        sigma2 += 1
    
    import matplotlib.pyplot as plt
    x = list(range(1,sigma+1))
    print(x)
    print(norm_list)
    plt.plot(x,norm_list)
    plt.show()
###########################################

Program Links : https://github.com/JJJYmmm/Image-Classification-with-SIFT-and-BOW

ReadMe

使用SIFT+BOW+SVM实现的一个图像分类器。SIFT负责提取图片中的尺度不变特征,词袋模型BOW则负责描述一张图片的SIFT特征分布,将结果送入SVM进行学习。项目参考https://github.com/CV-xueba/A01_cvclass_basic_exercise,不过修复了其中的SPM特征提取代码bug,具体修复见Vocabulary.py中的calSPMFeature函数。

项目结构如下:

  • main.py : 程序入口点
  • DataProcess.py : 读取图像,提取图像的SIFT特征
  • ImageInfo.py : 图像相关信息的类,包括类别、大小、SIFT特征的位置和描述符等
  • Vocabulary.py : 词袋模型,将所有SIFT特征进行聚类得到单词,并提取每个图像的SPM特征
  • ClassifierKernel.py : SVM学习BOW特征的实现

结果见项目output.txt

以下是测试集的混淆矩阵

confusion matrix

摘要

本篇主要介绍目标检测的一些基本概念,以及一个人脸检测的实例来加深印象,最后还谈了以下HOG特征的提取。

简单介绍(非常简单)

目标检测就是在负责在一幅图中检测出感兴趣的物体,一般采用滑动窗口来实现。但是实际应用中,检测效果依赖于光照、物体姿态、视角等影响。具体来说,目标检测需要考虑以下几个问题:

  • 如何选择滑动窗口的大小,从而克服检测物体的尺度变化
  • 如何建模图片的特征
  • 如何找到物体对应的特征
  • 如何克服不同摄影角度的问题(最原始的方法是训练多个视角的模型)

image-20230708152459133

人脸检测

本次介绍基于adaboost的人脸检测模型,它广泛用在相机、手机摄影的人脸检测器。

boosting模型

首先介绍boosting模型,它是一种投票式的判别模型,相比于直接训练一个强分类模型,它的思想是训练多个弱分类器,取长补短达到强分类的效果。

训练过程如下,最终目的是训练一个分类器可以分辨红蓝数据点。刚开始所有数据点的权重为1。

image-20230708153956057

接下来训练多个弱分类器,例如线性分类器组。找到一个正确率最高的分类器,将其保留。

这里有个先验假设,我们总能找到一个正确率大于50%的分类器。原因是如果所有分类器的准确率都小于50%,那我们只需要选正确率最低的那个分类器,然后跟他反着预测即可。

image-20230708154132799

我们选出来的分类器性能并不高,他会有一些分类错误的数据点,对于这些数据点,我们扩大它们的权重。(在代码中,我们选择缩小正确预测的数据点的权重,这里方便观察使用另外一种思路)

image-20230708154202268

在新的权重比例下,我们再次训练多个线性分类器,得到一个表现最好的分类器,将其保留。因为我们扩大了第一个分类器分类错误的那些数据点的权重,所以第二个分类器会更加关注这些点的分类。通俗的来说,第二个分类器可以解决第一个分类器没有解决的错误。

image-20230708154527206

同理,我们扩大第二个分类器的分类错误点的权重,并训练第三个分类器。

image-20230708154733591

最后,我们通过多个弱分类器得到一个强分类器。这就是boosting的思想。

image-20230708154822153

当对一个测试图像分类时,使用投票的方式进行预测,如果投票分数大于全局分数的半数,那么就将其分类为真。

image-20230708154849401

人脸检测

回到人脸检测领域,我们选择的弱分类器非常简单,其实就是一个卷积模板。如下图所示,选择一个固定位置的卷积核,卷积核分为白色区域和黑色区域,卷积结果就是白色区域的像素值和与黑色区域的像素值和的差。这个也叫harr-like算子

image-20230708154946084

例如人脸鼻翼区域的卷积核,因为光照的原因,鼻翼下方的像素值普遍比鼻翼位置的像素值低,因此对于人脸来说,整个模板的值往往小于0,这就组成了一个Weak Classifier。

image-20230708155730158

在实际运算中,为了解决运算成本,我们一般使用二维前缀和对图像的区域值计算进行加速

image-20230708155958610

接下来的思路就和boosting一致,我们寻找多个模板构成多个弱分类器。然后参考boosting的训练机制得到一个人脸的强分类器。

image-20230708160114467

image-20230708160119879

image-20230708160126913

不过对于一个准确率达到95%的强分类器,还是需要200个弱分类器参与运算。这效率还是不高,因为实际检测还需要通过滑动窗口确定人脸范围。

image-20230708160214266

因此为了加快速率,采用强分类器的级联结构。具体来说,就是训练多个强分类器(每个强分类器里面都有多个弱分类器)。第一个强分类器的准确率不需要太高,比50%高一点就可以;第二个强分类器则处理第一个强分类器无法解决的错误;第三个分类器则解决第二个分类器无法解决的问题.....(这个思想也很像boosting)。最后通过多个强分类器检测的滑动窗口区域才认为存在人脸,否则直接pass

这里为什么可以加快效率呢,因为强分类器不要求有很高的准确率,他只要保证可以让绝大部分正样本都通过,让部分负样本通过即可。通过多个强分类器的级联可以逐步过滤假阳样本。

假如第一个强分类器的准确率只需要50%,那么它大概只需要两个弱分类器就可以达到目的,这个远远低于95%准确率分类器的200个弱分类器。并且在检测过程中,大部分非人脸都会在这里被拒绝。所以可以提高检测效率

以上级联特点也启示我们,对于越明显的特征检测器(比如刚刚提到的鼻翼位置的harr-like算子),放在越前面,将进一步提高检测效率

说白了,强分类器的级联,其实可以理解成强分类器组的boosting

image-20230708160400464

行人检测

行人检测主要介绍一个HOG特征。行人检测一般就是给定窗口,通过计算窗口中的HOG特征,利用SVM判断窗口中是否包含行人。

image-20230708161410955

HOG的计算过程如下:

  • 首先计算图像的梯度大小和方向图。
  • 将图像分为若干个8x8大小的小单元,对于每个单元,统计其梯度直方图。统计直方图分成9份,即一个小单元对应一个9维向量。
  • 四个小单元为一个block,那么一个block对应一个36维向量。对于每个block中的36维向量进行归一化,这一步可以降低光照等环境影响
  • 滑动窗口大小为一个blcok,步长为一个cell,所以对于一个8x16小单元的图像,最后可以得到$(8-1)*(16-1)=105$个block,那么这张图片的HOG特征长度就为$105*36=3780$。

摘要

图像分类是一个经典的视觉任务。无论是分类、识别、检测等任务,都容易受到视角变化、光照、尺度、变形、遮挡、背景、类内实体等因素的影响,所以寻找合适的图像特征表示是一个比较重要的任务。本篇主要介绍了词袋模型表示。

图像表示

图像表示有很多方法,例如之前提到的SIFT特征、纹理特征、HOG特征,甚至直接对图像分块、随机选择图像块也可以表示图像。

image-20230708144526828

词袋模型

词袋模型也可以用来表示一张图像。词袋模型简单来说就是选取一些图像基元构成字典。对于一张图片,首先对其进行分割,统计这些图像块在字典中的统计直方图,根据统计直方图特征确定图片属于哪种类别。

以下述三幅图为例,训练时,每幅图首先分别选出三张基元(如何选取见下文),因此得到了9个基元的词袋。

image-20230708150042469

对于一张测试图像,同样提取图像块并和字典中的9个基元比较,统计其出现个数,根据统计特征进行分类。

image-20230708150327725

词袋模型其实也广泛用在自然语言处理中,比如可以用它来做主题推断等等。

image-20230708150401912

最后一部分是图像块(基元)的提取,这里有许多方法可以提取。例如对于一张图片,可以使用SIFT提取几个区域,并用SIFT描述符来描述。这样一张图片就表示成多个SIFT描述符形成的文档,而多张图片形成多个文档。

image-20230708150551629

对于所有的SIFT描述符,可以做聚类操作,挑出具有代表性的几个描述符,将其作为词袋模型的单词。(这些单词会分割整个特征空间,对于任意一个SIFT描述符输入,都可以把它归类为某个单词,从而可以统计单词分布)根据这些单词,我们可以知道训练图片的单词分布。当来了一张新的图片,我们同样对其进行SIFT变换,得到文档及其单词分布,通过对比训练库中各类图片的单词分布,可以确定一个最相近的类,完成图像分类的目的。

image-20230708150710946

有时候,对于一整张图片使用词袋模型进行分类会存在问题。例如对于"我爱中国"和"爱我中国"两句话,它们四个字都相同,即单词分布一致,但是却表达了不同的意思。因此对于图像分类来说,我们可以使用空间金字塔表示,例如将图片分块,去比较小块图片的单词分布,从而提高分类的准确率。

image-20230708151436627

生成式模型和判别式模型

以判断一张图片中是否有斑马为例,可以通过贝叶斯公式求得一张照片中有斑马的概率。如下图所示,如果$posterior-ratio$大于1,可以认为这张图含有斑马。$posterior-ratio$通过贝叶斯公式可以表示为极大似然概率比$likelihood-ratio$与先验概率比$prior-ratio$的乘积。

image-20230708144724168

对于判别式模型,它直接建模$posterior-ratio$,也就是求$P(x|y)$。

image-20230708145216547

对于生成式模型,它建模极大似然比,再通过先验概率比得到最终识别结果。关于贝叶斯公式先验公式等内容的理解,可以参考这篇:理解贝叶斯定理(prior/likelihood/posterior/evidence) - 知乎 (zhihu.com)

image-20230708145617910

目标识别

传统目标识别都是采用滑动窗口的搜索方法:不断移动窗口,直到窗口中检测到物体。

image-20230708145914583