最近邻法做图像分类

思想

最近邻法思想其实很简单:给出一大堆已经知道标签的图片。现在新来一张图片,新图片和所有的旧图片做比较,找出和旧图片中“最相似”的一张,输出这一张图片的标签作为预测值。

“最相近”怎么办?

一张图片需要抽取它的特征,只要所有特征都很相近,那么两幅图片就很相似。“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子”。虽然简单粗暴,但是很有效。如何定义相近呢?比如求欧式距离,比如距离的绝对值之类的都可以。

那么,这个特征怎么求呢?这个Toy里面使用灰度共生矩阵来求。求得灰度共生矩阵(因为简单啊),然后求灰度共生矩阵的5个二次统计量(能量,对比度,相关性,均匀度,熵)作为特征。在这里,灰度共生矩阵可以使用四个方向(0°,45°,90°,135°),每个方向都能求出来5个二次统计量,也就是一幅图片可以求得20个特征。作为Toy差不多够用了吧?

下面呢,就是如何定义“鸭子”了。公式如下,应该没有打错把?最起码我是这么理解的公式:

$$
F(X)=arc\min_{k}(\sum(X-X_{i}^{k})^{2})
$$

实现

主程序:参数调整,读入图片,分出训练集和测试集,驱动整个程序的运行。

读入图片

这里给的数据集比较特殊:数据集有jpg和png两种类型的图片,每幅图片都是200*200的纹理。共有8个类别,每个类别有8张图片。比如第3个类别第6张图片,文件名为36.jpg。png是对jpg做过直方图均衡化的结果。这两种图片在这里我混用了,为了让基数更大一点。(这个数据集叫Brodatz

对于每一张图片,转变成特征值

测试的时候发现加上熵之后精度会下降。很奇怪。
熵哪里算错了?

$$
N=\sum_{i}\sum_{j}(i-j)^{2}p(i,j)
$$

另外我对灰度共生矩阵加上了1,防止log(0)得到NaN

下面开始做预测吧!因为这个分类器不像决策树那样需要做训练,所以直接做预测就好了。

做预测的引导程序如下:

对于每一个样本,做预测的程序如下:

其实整个算法核心就四句话:

看出来了吧?

我还用了决策树作对比:

话说Matlab自带的决策树用的是什么算法?Sk-learn带的决策树用的是什么算法?

整体代码风格受到sk-learn的影响比较大。比如说参数传递和参数命名之类的。

下面结果是在某个Brodatz数据集上跑的效果。

结果

运行结果如下

看来还是可以的。但加上熵之后,精度反而会下降:

不知道是哪里有问题。

然后可以调整参数,例如加大训练集合、减少样本数之类、改变灰度共生矩阵量化精度之类的。在这里就不做对比了。反正就是,训练集合越大精度越好、特征数量增加可能导致精度减小。

最后附上一些很神奇的代码段:

主程序
ReadImage
TestOne

十分解气啊!

收工开始复习考试。

参考文档

[1] 杨杰. 数字图像处理及Matlab实现. 北京:电子工业出版社
[2] 宋相法. 数字图像处理课堂PPT. 河南:河南大学

发表评论

电子邮件地址不会被公开。 必填项已用*标注