一:LDA概述。
线性判别分析(LDA)是一种用来实现两个或者多个对象特征分类方法,在数据统计、模式识别、机器学习领域均有应用。LDA跟PCA非常相似、唯一不同的是LDA的结果是将数据投影到不同分类、PCA的结果是将数据投影到最高相似分组,而且过程无一例外的都基于特征值与特性向量实现降维处理。PCA变换基于在原数据与调整之后估算降维的数据之间最小均方错误,PCA趋向提取数据最大相同特征、而忽视数据之间微小不同特征、所以如果在OCR识别上使用PCA的方法就很难分辨Q与O个英文字母、而LDA基于最大类间方差与最小类内方差,其目的是减少分类内部之间差异,扩大不同分类之间差异。所以LDA在一些应用场景中有比PCA更好的表现。
二:LDA原理
LDA有时候又被称为FLDA(Fisher Linear Discriminant Analysis)原因就是Fisher首先提出了这种分析方法。以二分类的二维数据为例解释LDA原理,假设有数二维据集如下:
- 分类 1 有 5个样本数据 c1=[(1,2),(2,3),(3,3),(4,5),(5,5)]
- 分类 2 has 6个样本数据 c2=[(1,0),(2,1),(3,1),(3,2),(5,3),(6,5)]
三:OpenCV中LDA分析代码实现
OpenCV中在实现了LDA分析的类,提供了LDA计算分析获取特征值与特征向量,以及支持投影到子空间实现降维的函数方法,代码演示如下:
代码语言:javascript复制#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = Mat::zeros(500, 500, CV_8UC3);
int height = src.rows;
int width = src.cols;
Mat samples = Mat::zeros(300, 2, CV_64FC1);
Mat labels = Mat::zeros(300, 1, CV_32SC1);
int index = 0;
for (int row = 0; row < 10; row ) {
for (int col = 0; col < 10; col ) {
samples.at<double>(index, 0) = row;
samples.at<double>(index, 1) = col;
labels.at<int>(index, 0) = 0;
index ;
}
}
for (int row = 0; row < 10; row ) {
for (int col = 0; col < 10; col ) {
samples.at<double>(index, 0) = (height - row - 1);
samples.at<double>(index, 1) = col;
labels.at<int>(index, 0) = 1;
index ;
}
}
for (int row = 30; row < 40; row ) {
for (int col = 30; col < 40; col ) {
samples.at<double>(index, 0) = (height - row - 1);
samples.at<double>(index, 1) = width-1-col;
labels.at<int>(index, 0) = 2;
index ;
}
}
printf("index = %dn", index);
LDA lda(2);
lda.compute(samples, labels);
Mat eignenvector = lda.eigenvectors();
Mat eigenvalue = lda.eigenvalues();
printf("eigen values rows : %dn", eigenvalue.rows);
printf("eigen values cols : %dn", eigenvalue.cols);
for (int ec = 0; ec < eigenvalue.cols; ec ) {
printf("lemna %d values : %fn", (ec 1), eigenvalue.at<double>(0, ec));
}
printf("eigen vectorn");
for (int ec = 0; ec < eignenvector.rows; ec ) {
printf("vector %d values : %fn", (ec 1), eignenvector.at<double>(ec, 0));
printf("vector %d values : %fn", (ec 1), eignenvector.at<double>(ec, 1));
}
Mat projected = lda.project(samples);
cout << "rows:" << projected.rows << endl;
cout << "cols:" << projected.cols << endl;
for (int i = 0; i<projected.rows; i )
{
for (int j = 0; j<projected.cols; j )
{
printf("%fn", projected.ptr<double>(i)[j]);
}
}
waitKey(0);
return 0;
}