最近邻法做图像分类

思想

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

“最相近”怎么办?

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

那么,这个特征怎么求呢?这个 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. 河南:河南大学

发表评论

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