训练时的OpenCV错误ANN_MLP

时间:2016-04-24 12:28:44

标签: c++ opencv

我希望列车神经网络对两种类型的图像进行分类,但是当列车网络出现这种错误时:

OpenCV错误:错误的参数(输出训练数据应该是一个浮点矩阵,行数等于训练样本的数量,列数等于最后(输出)层的大小)在cv中: :ml :: ANN_MLPImpl :: prepare_to_train,文件C:\ buildslave64 \ win64_amdocl \ master_PackSlave-win64-vc14-shared \ opencv \ modules \ ml \ src \ ann_mlp.cpp,第675行

我的代码:

#include "opencv2\core.hpp"
#include "opencv2\imgproc.hpp"
#include "opencv2\imgcodecs.hpp"
#include "opencv2\highgui.hpp"
#include "opencv2\ml.hpp"
#include <string>
#include "lbp.h"
using namespace cv;
using namespace cv::ml;
void LoadTrainingData();

Mat Data;
Mat Lables;
//const int numberOfClass1 = 2384;
//const int numberOfClass2 = 2462;
const int numberOfClass1 = 23;
const int numberOfClass2 = 24;
int Class1 = 1;
int Class2 = -1;
const int imageDimention = 22;

std::string NumberToString(size_t Number)
{
    std::stringstream ss;
    ss << Number;
    return ss.str();
}



void main() {
    LoadTrainingData();
    Ptr<ANN_MLP> annClassifier;
    annClassifier = ANN_MLP::create();
    annClassifier->setActivationFunction(ANN_MLP::ActivationFunctions::SIGMOID_SYM);
    Mat layers(1, 3, CV_32F);
    layers.at<float>(0) = Data.cols;
    layers.at<float>(1) = 100;
    layers.at<float>(2) = 2;
    annClassifier->setLayerSizes(layers);
    annClassifier->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
    annClassifier->setTrainMethod(ANN_MLP::TrainingMethods::BACKPROP);
    bool trained = annClassifier->train(Data,ROW_SAMPLE,Lables);
    if (trained)
        annClassifier->save("Ann_sigmoid_eye");

}
void LoadTrainingData() {

    Data = Mat(numberOfClass1 + numberOfClass2, imageDimention*imageDimention, CV_32FC1);
    Lables = Mat(numberOfClass1 + numberOfClass2,1 , CV_32SC1);
    // load openEye 
    Mat img;
    Mat lbpImg;
    Mat row;
    std::string path;
    for (size_t i = 1; i <= numberOfClass2; i++)
    {
        path = "class1 (" + NumberToString(i) + ").jpg";
        img = imread(path);
        if (img.channels() > 1)
            cvtColor(img, img, CV_BGR2GRAY);
        lbp::ELBP(img,lbpImg, 1, 16);       
        row = lbpImg.reshape(0, 1);
        row.convertTo(row, CV_32FC1);
        Data.push_back(row);
        Lables.push_back(Class1);

    }
    for (size_t i = 1; i <= numberOfClass1; i++)
    {
        path ="class2 (" + NumberToString(i) + ").jpg";
        img = imread(path);
        if (img.channels() > 1)
            cvtColor(img, img, CV_BGR2GRAY);
        lbp::ELBP(img,lbpImg, 1, 16);
        row = lbpImg.reshape(0, 1);
        row.convertTo(row, CV_32FC1);
        Data.push_back(row);
        Lables.push_back(Class2);
    }
}

我不知道为什么会这样!请帮助我,谢谢。

1 个答案:

答案 0 :(得分:0)

火车对安安的反应与通常的opencv ml方法略有不同。

如果你的ann中有2个输出神经元,每个训练特征也需要2个输出神经元,而不是单个&#34;类标签&#34; (例如与SVM一样)。

它应该是这样的:

[train_data]                [train_responses]

lbpfeature1                 -1   1     // class A
lbpfeature2                 -1   1     // class A
lbpfeature3                 1   -1     // class B
lbpfeature4                 1   -1     // class B

所以,响应必须有num_features行X 2 cols。 一种方式(有无穷无尽的......)将是:

// leave Labels empty (btw, your original code seems to leave the 1st element empty)
    // Lables = Mat(numberOfClass1 + numberOfClass2,1 , CV_32SC1);

    // instead of 
    //Lables.push_back(Class1);
    Lables.push_back(1.0f);
    Lables.push_back(-1.0f);

    // and instead of 
    //Lables.push_back(Class2);
    Lables.push_back(-1.0f);
    Lables.push_back(1.0f);

    // then, before training, reshape to N x 2:
    Labels = Labels.reshape(1, Labels.rows / 2);
    Data.convertTo(Data, CV_32FC1);
    Lables.convertTo(Lables, CV_32FC1);