OpenCV实现KNN算法

时间:2024-12-06 18:04:14

原文 OpenCV实现KNN算法

K Nearest Neighbors

这个算法首先贮藏所有的训练样本,然后通过分析(包括选举,计算加权和等方式)一个新样本周围K个最近邻以给出该样本的相应值。这种方法有时候被称作“基于样本的学习”,即为了预测,我们对于给定的输入搜索最近的已知其相应的特征向量。

class CvKNearest : public CvStatModel //继承自ML库中的统计模型基类
{
public: CvKNearest();//无参构造函数
virtual ~CvKNearest(); //虚函数定义 CvKNearest( const CvMat* _train_data, const CvMat* _responses,
const CvMat* _sample_idx=, bool _is_regression=false, int max_k= );//有参构造函数 virtual bool train( const CvMat* _train_data, const CvMat* _responses,
const CvMat* _sample_idx=, bool is_regression=false,
int _max_k=, bool _update_base=false ); virtual float find_nearest( const CvMat* _samples, int k, CvMat* results,
const float** neighbors=, CvMat* neighbor_responses=, CvMat* dist= ) const; virtual void clear();
int get_max_k() const;
int get_var_count() const;
int get_sample_count() const;
bool is_regression() const; protected:
...
};

CvKNearest::train

训练KNN模型

bool CvKNearest::train( const CvMat* _train_data, const CvMat* _responses,
const CvMat* _sample_idx=, bool is_regression=false,
int _max_k=, bool _update_base=false );

这个类的方法训练K近邻模型。它遵循一个一般训练方法约定的限制:只支持CV_ROW_SAMPLE数据格式,输入向量必须都是有序的,而输出可以 是 无序的(当is_regression=false),可以是有序的(is_regression=true)。并且变量子集和省略度量是不被支持的。

参数_max_k 指定了最大邻居的个数,它将被传给方法find_nearest。 参数 _update_base 指定模型是由原来的数据训练(_update_base=false),还是被新训练数据更新后再训练(_update_base=true)。在后一种情况下_max_k 不能大于原值, 否则它会被忽略.

CvKNearest::find_nearest

寻找输入向量的最近邻

float CvKNearest::find_nearest( const CvMat* _samples, int k, CvMat* results=,
const float** neighbors=, CvMat* neighbor_responses=, CvMat* dist= ) const;

对每个输入向量(表示为matrix_sample的每一行),该方法找到k(k≤get_max_k() )个最近邻。在回归中,预测结果将是指定向量的近邻的响应的均值。在分类中,类别将由投票决定。

对传统分类和回归预测来说,该方法可以有选择的返回近邻向量本身的指针(neighbors, array of k*_samples->rows pointers),它们相对应的输出值(neighbor_responses, a vector of k*_samples->rows elements) ,和输入向量与近邻之间的距离(dist, also a vector of k*_samples->rows elements)。

对每个输入向量来说,近邻将按照它们到该向量的距离排序。

对单个输入向量,所有的输出矩阵是可选的,而且预测值将由该方法返回。

例程:使用kNN进行2维样本集的分类,样本集的分布为混合高斯分布

#include "ml.h"
#include "highgui.h" int main( int argc, char** argv )
{
const int K = ;
int i, j, k, accuracy;
float response;
int train_sample_count = ;
CvRNG rng_state = cvRNG(-);
CvMat* trainData = cvCreateMat( train_sample_count, , CV_32FC1 );
CvMat* trainClasses = cvCreateMat( train_sample_count, , CV_32FC1 );
IplImage* img = cvCreateImage( cvSize( , ), , );
float _sample[];
CvMat sample = cvMat( , , CV_32FC1, _sample );
cvZero( img ); CvMat trainData1, trainData2, trainClasses1, trainClasses2; // form the training samples
cvGetRows( trainData, &trainData1, , train_sample_count/ );
cvRandArr( &rng_state, &trainData1, CV_RAND_NORMAL, cvScalar(,), cvScalar(,) ); cvGetRows( trainData, &trainData2, train_sample_count/, train_sample_count );
cvRandArr( &rng_state, &trainData2, CV_RAND_NORMAL, cvScalar(,), cvScalar(,) ); cvGetRows( trainClasses, &trainClasses1, , train_sample_count/ );
cvSet( &trainClasses1, cvScalar() ); cvGetRows( trainClasses, &trainClasses2, train_sample_count/, train_sample_count );
cvSet( &trainClasses2, cvScalar() ); // learn classifier
CvKNearest knn( trainData, trainClasses, , false, K );
CvMat* nearests = cvCreateMat( , K, CV_32FC1); for( i = ; i < img->height; i++ )
{
for( j = ; j < img->width; j++ )
{
sample.data.fl[] = (float)j;
sample.data.fl[] = (float)i; // estimates the response and get the neighbors' labels
response = knn.find_nearest(&sample,K,,,nearests,); // compute the number of neighbors representing the majority
for( k = , accuracy = ; k < K; k++ )
{
if( nearests->data.fl[k] == response)
accuracy++;
}
// highlight the pixel depending on the accuracy (or confidence)
cvSet2D( img, i, j, response == ?
(accuracy > ? CV_RGB(,,) : CV_RGB(,,)) :
(accuracy > ? CV_RGB(,,) : CV_RGB(,,)) );
}
} // display the original training samples
for( i = ; i < train_sample_count/; i++ )
{
CvPoint pt;
pt.x = cvRound(trainData1.data.fl[i*]);
pt.y = cvRound(trainData1.data.fl[i*+]);
cvCircle( img, pt, , CV_RGB(,,), CV_FILLED );
pt.x = cvRound(trainData2.data.fl[i*]);
pt.y = cvRound(trainData2.data.fl[i*+]);
cvCircle( img, pt, , CV_RGB(,,), CV_FILLED );
} cvNamedWindow( "classifier result", );
cvShowImage( "classifier result", img );
cvWaitKey(); cvReleaseMat( &trainClasses );
cvReleaseMat( &trainData );
return ;
}

结果:

aaarticlea/png;base64,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" alt="" />