#include <opencv2/core.hpp>
#include <opencv2/ml.hpp>
#include <iostream>
#include <vector>
int main()
{
size_t const FeatureSize = 24;
{
auto rtrees = cv::ml::RTrees::create();
rtrees->setMaxDepth(10);
rtrees->setMinSampleCount(2);
rtrees->setRegressionAccuracy(0);
rtrees->setUseSurrogates(false);
rtrees->setMaxCategories(16);
rtrees->setPriors(cv::Mat());
rtrees->setCalculateVarImportance(false);
rtrees->setActiveVarCount(0);
rtrees->setTermCriteria({ cv::TermCriteria::MAX_ITER, 100, 0 });
std::vector<float> labels; //#1
cv::Mat_<float> features;
for(size_t i = 0; i != 500; ++i){
std::vector<float> data;
for(size_t j = 0; j != FeatureSize; ++j){
data.emplace_back(0); //#2
}
labels.emplace_back(i % 2);
features.push_back(cv::Mat(data, true));
}
rtrees->train(features.reshape(1, labels.size()),
cv::ml::ROW_SAMPLE, labels);
rtrees->write(cv::FileStorage("smoke_classifier.xml",
cv::FileStorage::WRITE));
}
{
auto rtrees2 = cv::ml::RTrees::create();
cv::FileStorage read("smoke_classifier.xml",
cv::FileStorage::READ);
rtrees2->read(read.root());
int a = rtrees2->getMinSampleCount();
std::cout<<"a == "<<a<<"\n";
cv::Mat1f feat2(1, FeatureSize, 0.f);
std::cout<<"predict == "<<rtrees2->predict(feat2)<<"\n";
}
}
如果你将#1从float更改为int并读取xml然后调用predict,程序将崩溃,但如果我没有从xml读取信息,那么即使#1类型是函数预测也可以工作INT
但是如果我将标签从int更改为float,当我调用train来训练机器时,rtree会弹出另一条错误消息(虚拟数据&#34; 0&#34;代码片段(#2)不会导致程序崩溃,但真正的数据会)。
另一个问题是,将标签从int更改为float会使其从分类到回归问题,但我真正需要的是分类而不是回归(虽然很容易通过回归来模拟分类,因为只有两个标签)
将标签更改为浮动并呼叫列车以训练机器时的错误消息
&#34; .... \ opencv-3.0.0 \ sources \ modules \ ml \ src \ tree.cpp:1190:错误:(-215)(int)_sleft.size()&lt; n&amp;&amp; (int)_sright.size()&lt; n在函数cv :: ml :: DTreesImpl :: calcDir&#34;
中答案 0 :(得分:1)
相关代码位于 tree.cpp 。
使用int
标签时,此行会导致崩溃:
float DTreesImpl::predictTrees( const Range& range, const Mat& sample, int flags ) const
{
...
if( predictType == PREDICT_MAX_VOTE ) {
...
sum = (flags & RAW_OUTPUT) ? (float)best_idx : classLabels[best_idx]; // Line 1487
...
}
}
因为classLabels
为空(即使它出现在xml文件中)。
使用float
标签时,此行不会被执行,因为predictType
将是PREDICT_SUM
而不是PREDICT_MAX_VOTE
。 (相关代码具有相同的功能)。
原因是文件未正确加载(这可能是错误)。实际上,在阅读文件时有这个检查
void DTreesImpl::readParams( const FileNode& fn )
{
...
int format = 0; // line 1720
fn["format"] >> format;
bool isLegacy = format < 3;
...
if (isLegacy) { ... }
else
{
...
fn["class_labels"] >> classLabels;
}
}
但在编写文件时,字段&#34;格式&#34;不在这里。因此,您实际上是以错误的格式读取文件,因为您输入了isLegacy
部分。
解决方法是将文件另存为:
...
std::vector<int> labels;
...
rtrees->write(cv::FileStorage("smoke_classifier.xml", cv::FileStorage::WRITE));
// Add this
{
cv::FileStorage fs("smoke_classifier.xml", cv::FileStorage::APPEND);
fs << "format" << 3; // So "isLegacy" return false;
}
cv::FileStorage read("smoke_classifier.xml",
cv::FileStorage::READ);
auto rtrees2 = cv::ml::RTrees::create();
rtrees2->read(read.root());
这样做,文件将被正确加载,程序不会崩溃。
由于我无法在calcDir
中重现您的其他问题,请告诉我这是否有效。