cv图像之 bag of words搭建笔记

近期尝试使用MATLAB实现对图像的bag of words分类。在此记录一些心得体会,望与小伙伴们交流。


一. filterResponses

    将图片放入不同的filterBank中,输出结果

输入:
     W×H×3的图像
     N个filterBank
输出:
     W×H × N×3 的矩阵

    这一步比较简单,使用convn即可得到

    此外,我是先把每个filter后的结果保存到一个cell里面,最后用vertcat(垂直合并矩阵)把结果变成一个W×H×N×3的矩阵。


二. Dictionary

    这一步是构建字典

    把一堆图片的每个像素通过N个filter后的结果(每个像素的60个outputs作为一个元素),通过Kmeans生成字典。

    因为图片太多,使用rand随机抽取像素点。

    输出的dictionary大小为: K(自行定义的分成多少类)×N×3

btw:这一步耗时比较长,如果电脑有多核,使用parfor快很多!

    我使用了20个filter,分成了K=300类,建立成的字典大小为300×60。(最后我的randam像素点选取了200个,k分成了305类,这个需要在不断测试中获得比较好的数字选取。)


三. Visual Words

    有了dictionary后,下一步是把所有的图片的每个像素变成字典“文字”。

    简单来说就是把每个图片过filter得到的整个filterResponse(每一行代表一个像素的结果,即每一行都有60列,共有W×H行)的每一行跟dictionary比较,该像素跟dictionary最相似的那一行就是那个像素的visual word。用dictionary行数(ID)代替visual Word编码,把每张图片表示成W×H的wordMap矩阵,并且保存成.mat。

    这里使用到了pdist2函数。

    D = pdist2(X,Y,distance)
    矩阵中一行代表一个元素,D(i,j)表示X的i行与Y的j行的距离

    用 imagesc(wordMap) 可以可视化图片的visual Word表示。

    这里一开始比较纠结的是怎么可视化呢?怎样知道每个visual word代表的像素RGB呢?如果你也开始纠结这个问题,说明——恭喜你,你也被我带跑了!其实,并不需要考虑每个visual Word代表的像素RGB,只用把同一个visual Word用一种RGB表示就可以了,所以直接用每个Word的ID代替就OK了,展现出来的是。


四. Image Features

    如何获得每张图片的特征呢?这里可以使用直方图。

    上一步得到的每一个图片的wordMap后,可对每张图片每个单词出现的次数进行统计,统计出来的直方图便是图片的特征。

    直方图十分好计算,输入:W×H的wordMap矩阵,输出:K×1的矩阵。记得要归一化。

    ★然而,对于整张图的直方图计算,没有空间信息。因此使用金字塔空间匹配SPM。简单来说就是把image分割成n×n的cell,再对每个cell计算直方图,再把每个cell的直方图拼接在一起,变成了K([4^(LayerNum)-1]/3)×1的矩阵。

    拼接的时候,level0和level1取1/2^(-L)倍,其余取1/2^(l-L-1)倍。

    这里使用mat2cell可以直接分割wordMap。要注意的是,有时候图片的大小不一定是被2或4整除的,因此可以前面向下取整,最后一块是所有剩下的即可。

    当LayerNum=3,即L=2时,得到的结果大小为6300×1。(最后我用了LayerNum=4)


五. Recognize System

    有的教程在这里先写distance的代码,但是我发现,没有做recognize之前,我实在搞不清楚distance的输入和输出是怎么一回事。因此我先写了recognize system。

    recognize system是要得到一个vision.mat里面包含:

        filterBank
        dictionary
        train_features
        train_labels

    其中filterBank、dictionary、train_labels是从前面得到的数据以及已有的数据可以直接load的,需要做的其实只有train_features。

    train_features是什么呢?它其实是T张用来训练的图片每个通过一系列的计算得到的SPM直方图的集合矩阵,大小为K([4^(LayerNum)-1]/3)×T,每一列代表一张图片。

    看起来很简单的样子,只是从已有的wordMap.mat中导入wordMap的时候要使用wordMap.wordMap。然后每个wordMap用前面的直方图计算函数一计算,全部拼接(horzcat矩阵水平拼接),完成!


六. Distance

    这时候就可以回过头来看distance了。distance是在测试的时候,通过这个函数判断测试的图片跟train_features的每一列的差距。

    使用直方图相交相似即可。也就是sum(min(h,train_features))(当然这只是意会,代码具体不是这样的,我使用了bsxfun运算)。


七. 测试

    选定一些测试图片输入测试,预测的分类与图片标签进行对比。我的精确度大约能做到58%-64%。



    还在摸索如何提升精确度,也希望小伙伴们提提意见。

你可能感兴趣的:(图像处理,机器学习)