使用cv :: ml :: StatModel :: train的Opencv错误以便使用KNN

时间:2018-04-03 09:27:59

标签: c++ opencv computer-vision knn

问题#1:

我正在尝试使用Visual Studio 2017和C ++在opencv 3.4中实现KNN。到目前为止,我已经能够解决我的问题,但昨天我遇到了这个错误:  “非静态成员引用必须与特定对象相关”

int main(int argc, const char *argv[]) {

ReadData("smokeDataBase.yml", 0);//14 smoke
ReadData("forestDataBase.yml" , 1); //14 forest
ReadData("skyDataBase.yml", 2); //12 sky

ReadData("testDataBase.yml", 3);


Mat trainClasses = (Mat_<float>(40, 1) << 1, 1, 1, 1, 1, 1, 1, 1,1,1, 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0); //Couldn't figure out how to do this in some other way


//We prepare the data to use in KNN using self-made function that gets every
//vector in my .yml and appends them together
Mat trainData = prepTrain(forestDataBase, skyDataBase, smokeDataBase);

//学习分类器     int K = 10;     Ptr knn = ml :: KNearest :: create();     ml :: StatModel :: train(trainData,ml :: ROW_SAMPLE,trainClasses); //这一行给出错误

}

由于我无法训练KNN(虽然KNN不是严格意义上的学习方法)但我无法使用KNearest :: findNearest实际从代码中获得我想要的东西。我找不到任何符合我问题的答案,因此我写这篇文章。

我删除了未使用的代码的每个部分,试图让你们更容易帮助我。

问题#2:

当我创建变量TrainData时,我将我在smoke / forest / skyDatabase上的所有数据放在一起。换句话说,我将所有数据附加到一个单独的大量向量中。这是正确的方法吗?我应该分成一个“向量TrainData”变量,其中每个TrainData [i](i从0到TrainData.size)是表示我的数据样本的向量吗?

1 个答案:

答案 0 :(得分:1)

您的第一个问题: 这是official documentation

中描述的功能训练的签名
virtual bool cv::ml::StatModel::train   (   InputArray      samples,
        int     layout,
        InputArray      responses 
    )   

正如您所看到的,该方法是虚拟的,这意味着您可以通过这种方式进行调用!。此函数应由StatModel的子类实现。因此,当您想要使用该方法时,可以从实现此方法的子类调用该方法。 KNearest类实现了它。您的代码应更改为:

Ptr<ml::KNearest> knn = ml::KNearest::create();  
knn->train(trainData, ml::ROW_SAMPLE , trainClasses);

现在提出第二个问题:

您可以将数据准备为ROW_SAMPLE或COL_SAMPLE。 在ROW_SAMPLE中,每个样本都在一行中。因此,如果您的样本由三个浮点数组成,并且您有10个样本,则最终应该得到一个包含10行和3列的Mat对象。 在COL_SAMPLE中,所有内容都被反转。所以最终得到3行10列。