问题#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)是表示我的数据样本的向量吗?
答案 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列。