文档章节

基于SVD实现PCA的图像识别

初雪之音
 初雪之音
发布于 2015/10/04 00:50
字数 1329
阅读 1676
收藏 14

        本文实现基于SVD奇异矩阵分解的PCA主成分分析,使用该算法来完成对人脸图像的识别,主要讲解SVD实现PCA的原理,如何利用SVD实现图像特征的降维,以及SVD在文本聚类方面的使用,例如弱化同义词、多义词的影响,解决传统文本向量空间无法解决的问题。

需求分析

        本次实验需求分析很简单,实现人脸图像识别,简单地模仿谷歌、百度的识图搜索功能。

特征表示

        特征用来区别一个事物属于哪种类别,例如“是否有翅膀”可以拿来区别麻雀和哈士奇。如何判别两幅图是否是同一个人,我们可以选取图像的像素矩阵构成特征向量,例如一副180 * 200的jpg图像,根据其像素矩阵可以构成一个特征向量vector[180 * 200],有了特征向量我们就可以使用欧氏距离、余弦相似度等计算两幅图的相似度,从而得出是否属于同一个人。

特征选取

        直接使用像素矩阵构成特征向量,当图像很大时计算难免耗时Time Limited,我们将像素称为原始特征。如何将原始特征向量降维,同时又保存它的主要特性,我们可以联想到PCA主成分分析。在PCA主成分分析中,有一种奇异矩阵分解SVD算法,原矩阵可以分解为 M = U x S x V',然后选取前 k 个重要的特征组成新的特征向量完成降维。例如上例,k=20时,可以组成新的特征向量vec'[180 * 20 + 200 * 20],计算量大大减少又不影响比较结果。接下来,我们就来看一下SVD是个是么东西。

        SVD入门基础三步曲:

(1)机器学习中的数学(5)-强大的矩阵奇异值分解(SVD)及其应用

(2)【译】从几何角度看SVD

(3)奇异值分解和图像压缩

        看完上面3篇也就大概知道SVD的原理是什么了,矩阵U由左奇异特征向量组成(描述y轴方向的变化趋势),矩阵S代表对于左(右)特征向量的重要性,矩阵V' 由右奇异特征向量组成(描述x轴方向的变化趋势)。

        由SVD原理可知,我们可以选取前r 个左奇异特征向量、前r 个右奇异特征向量,组成一个新的特征向量vec[ m * k + n * k],从而完成降维,减少计算量而又保佑原有人脸图像特性。

模型建立

        模型特征向量选取完成后,我们就可以拿来比较两幅人脸图像的相似性了。在计算图像相似性时,本文采用余弦相似度算法进行比较,算法代码实现如下:

Pca.java

package key;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import Jama.*;

public class Pca {
    public double Cosine(double[] v1, double[] v2) {
        double ans = 0;

        int n = v1.length;
        double a = 0;
        for (int i = 0; i < n; i++) {
            a += v1[i] * v2[i];
        }
        double b = 0;
        for (int i = 0; i < n; i++) {
            b += v1[i] * v1[i];
        }
        b = Math.sqrt(b);
        double c = 0;
        for (int i = 0; i < n; i++) {
            c += v2[i] * v2[i];
        }
        c = Math.sqrt(c);
        ans = a / b / c;

        return ans;
    }

    public double[] PcaVector(double[][] pixels, int k) {
        Matrix ps = Matrix.constructWithCopy(pixels);
        if (ps.getRowDimension() < ps.getColumnDimension()) {
            ps = ps.transpose();
        }

        SingularValueDecomposition svd = ps.svd();
        Matrix u = svd.getU();
        Matrix s = svd.getS();
        Matrix vt = svd.getV().transpose();

        double[] vec = new double[u.getRowDimension() * k
                + vt.getColumnDimension() * k];
        int cur = 0;
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < u.getRowDimension(); j++) {
                vec[cur + i * u.getRowDimension() + j] = u.get(j, i);
            }
        }
        cur += u.getRowDimension() * k;
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < vt.getColumnDimension(); j++) {
                vec[cur + i * vt.getColumnDimension() + j] = vt.get(i, j);
            }
        }

        return vec;
    }

    public double[][] Pixels(File file) throws IOException {
        BufferedImage bi = ImageIO.read(file);

        int h = bi.getHeight();
        int w = bi.getWidth();
        double arr[][] = new double[w][h];

        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                arr[i][j] = bi.getRGB(i, j);
            }
        }

        return arr;
    }
}

Keyven.java

package key;

import java.io.File;
import java.io.IOException;

public class Keyven {
    public static void main(String[] args) throws IOException {
        Pca pk = new Pca();
        int k = 20;

        File key = new File("data/key.jpg");
        double[] vec_key = pk.PcaVector(pk.Pixels(key), k);

        File folder = new File("data/faces");
        if (folder.isDirectory()) {
            for (File f : folder.listFiles()) {
                double[] vec_f = pk.PcaVector(pk.Pixels(f), k);
                System.out.println(f.getName() + ":\t"
                        + pk.Cosine(vec_key, vec_f));
            }
        }
    }
}

实验效果

        原图像集和候选搜索图像如下:

        我们来看一下实验效果:


        对比还是蛮不错的^_^!

测试数据集下载

实验扩展

        上面讲到左奇异特征向量代表y轴的变化趋势,右奇异向量代表x轴的变化趋势,想象用在自然语言处理文本聚类中,有一个文档-词项共现矩阵,使用SVD作主成分分析,有可能使得原共现矩阵里正交的向量变得不正交,从而弱化了同义词、多义词的影响,而不是简简单单地依靠一个词是否在一篇文档中出现过来造特征……

© 著作权归作者所有

共有 人打赏支持
初雪之音
粉丝 44
博文 265
码字总数 148651
作品 0
广州
程序员
矩阵特征值分解与奇异值分解含义解析及应用

特征值与特征向量的几何意义 矩阵的乘法是什么,别只告诉我只是“前一个矩阵的行乘以后一个矩阵的列”,还会一点的可能还会说“前一个矩阵的列数等于后一个矩阵的行数才能相乘”,然而,这里...

日拱一卒
2016/07/01
44
0
深度学习算法:SVD分解算法及其应用

From: http://www.tuicool.com/articles/bEfMZr 矩阵的奇异值分解在矩阵理论的重要性不言而喻,它在最优化问题、特征值问题、最小乘方问题、广义逆矩阵问,统计学,图像压缩等方面都有十分重要...

xuzheng_1982
2017/01/18
0
0
OpenCV学习(37) 人脸识别(2)

在前面一篇教程中,我们学习了OpenCV中基于特征脸的人脸识别的代码实现,我们通过代码 Ptr model = createEigenFaceRecognizer(); 创建了人脸识别模型类,该识别模型类基于特征值人脸。该类有...

迈克老狼1
2013/11/20
0
0
三种方法实现PCA算法(Python)

  主成分分析,即Principal Component Analysis(PCA),是多元统计中的重要内容,也广泛应用于机器学习和其它领域。它的主要作用是对高维数据进行降维。PCA把原先的n个特征用数目更少的k...

但盼风雨来_jc
2017/12/12
0
0
三种方法实现PCA算法(Python)

  主成分分析,即Principal Component Analysis(PCA),是多元统计中的重要内容,也广泛应用于机器学习和其它领域。它的主要作用是对高维数据进行降维。PCA把原先的n个特征用数目更少的k...

jclian91
2017/12/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSX | SafariBookmarksSyncAgent意外退出解决方法

1. 启动系统, 按住⌘-R不松手2. 在实用工具(Utilities)下打开终端,输入csrutil disable, 然后回车; 你就看到提示系统完整性保护(SIP: System Integrity Protection)已禁用3. 输入reboot回车...

云迹
今天
4
0
面向对象类之间的关系

面向对象类之间的关系:is-a、has-a、use-a is-a关系也叫继承或泛化,比如大雁和鸟类之间的关系就是继承。 has-a关系称为关联关系,例如企鹅在气候寒冷的地方生活,“企鹅”和“气候”就是关...

gackey
今天
4
0
读书(附电子书)|小狗钱钱之白色的拉布拉多

关注公众号,在公众号中回复“小狗钱钱”可免费获得电子书。 一、背景 之前写了一篇文章 《小狗钱钱》 理财小白应该读的一本书,那时候我才看那本书,现在看了一大半了,发现这本书确实不错,...

tiankonguse
今天
4
0
Permissions 0777 for ‘***’ are too open

异常显示: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ......

李玉长
今天
5
0
区块链10年了,还未落地,它失败了吗?

导读 几乎每个人,甚至是对通证持怀疑态度的人,都对区块链的技术有积极的看法,因为它有可能改变世界。然而,区块链技术问世已经10年了,我们仍然没有真正的用上区块链技术。 几乎每个人,甚...

问题终结者
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部