Java + OpenCV SVM Training Error

2019-07-12 18:46发布

I'm trying to train a set of images to generate a training file and then identify some objects in images, separated set a positive and a negative set it up can train.

The problem occurs when I do the test with a file that was already trained, because it returns an error saying that the size of the input file is different from the size of the training sample. But that does not make sense, because the same image has already been trained.

public class Training{

protected static final String PATH_POSITIVE = "data/positivo/";
protected static final String PATH_NEGATIVE = "data/negativo/";
protected static final String XML = "data/test.xml";
protected static final String FILE_TEST = "data/positivo/1.jpg";

static {
    System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
}

protected static Mat getMat( Mat img ) {
    Mat timg = new Mat();
    Imgproc.cvtColor( img, timg, Imgproc.COLOR_BGR2GRAY );
    timg = timg.reshape( 1, timg.width() * timg.height() );
    timg.convertTo( timg, CvType.CV_32FC1 );
    return timg;
}

public static void main( String[ ] args ) {

    Mat classes = new Mat();
    Mat trainingData = new Mat();

    Mat trainingImages = new Mat();
    Mat trainingLabels = new Mat();

    CvSVM clasificador;

    for ( File file : new File( PATH_POSITIVE ).listFiles() ) {
        Mat img = Highgui.imread( file.getAbsolutePath() );
        trainingImages.push_back( getMat( img ) );
        trainingLabels.push_back( Mat.ones( new Size( 1, img.width() * img.height() ), CvType.CV_32FC1 ) );
    }

    for ( File file : new File( PATH_NEGATIVE ).listFiles() ) {
        Mat img = Highgui.imread( file.getAbsolutePath() );
        trainingImages.push_back( getMat( img ) );
        trainingLabels.push_back( Mat.zeros( new Size( 1, img.width() * img.height() ), CvType.CV_32FC1 ) );
    }

    trainingImages.copyTo( trainingData );
    trainingData.convertTo( trainingData, CvType.CV_32FC1 );
    trainingLabels.copyTo( classes );

    CvSVMParams params = new CvSVMParams();
    params.set_kernel_type( CvSVM.LINEAR );
    params.set_svm_type( CvSVM.C_SVC );
    params.set_gamma( 3 );

    clasificador = new CvSVM( trainingData, classes, new Mat(), new Mat(), params );
    clasificador.train( trainingData, classes );
    clasificador.save( XML );

    //Finished the part of the training will run the test with any file

    clasificador = new CvSVM();
    clasificador.load( new File( XML ).getAbsolutePath() );
    Mat timg = getMat( Highgui.imread( new File( FILE_TEST ).getAbsolutePath() ) );
    timg = timg.reshape( 1, timg.width() * timg.height() );
    timg.convertTo( timg, CvType.CV_32FC1 );

    //Here the error occurs
    //Exception in thread "main" CvException [org.opencv.core.CvException: cv::Exception: ..\..\..\..\opencv\modules\ml\src\inner_functions.cpp:1114: error: (-209) The sample size is different from what has been used for training in function cvPreparePredictData
    System.out.println( clasificador.predict( timg ) );

}

}

I am using Java 8 and OpenCV 2.4.10

标签: java opencv
1条回答
我命由我不由天
2楼-- · 2019-07-12 19:05

Based on the comments given by @berak, I decided to make some changes to my original code. The result is the following code and it is working for me:

public class Training{

protected static final String PATH_POSITIVE = "data/positivo/";
protected static final String PATH_NEGATIVE = "data/negativo/";
protected static final String XML = "data/test.xml";
protected static final String FILE_TEST = "data/negativo/1.jpg";

private static Mat trainingImages;
private static Mat trainingLabels;
private static Mat trainingData;
private static Mat classes;
private static CvSVM clasificador;

static {
    System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
    trainingImages = new Mat();
    trainingLabels = new Mat();
    trainingData = new Mat();
    classes = new Mat();
}

public static void main( String[ ] args ) {
    trainPositive();
    trainNegative();
    train();
    test();
}

protected static void test() {
    Mat in = Highgui.imread( new File( FILE_TEST ).getAbsolutePath(), Highgui.CV_LOAD_IMAGE_GRAYSCALE );
    clasificador.load( new File( XML ).getAbsolutePath() );
    System.out.println( clasificador );
    Mat out = new Mat();
    in.convertTo( out, CvType.CV_32FC1 );
    out = out.reshape( 1, 1 );
    System.out.println( out );
    System.out.println( clasificador.predict( out ) );
}

protected static void train() {
    trainingImages.copyTo( trainingData );
    trainingData.convertTo( trainingData, CvType.CV_32FC1 );
    trainingLabels.copyTo( classes );
    CvSVMParams params = new CvSVMParams();
    params.set_kernel_type( CvSVM.LINEAR );
    clasificador = new CvSVM( trainingData, classes, new Mat(), new Mat(), params );
    clasificador.save( XML );
}

protected static void trainPositive() {
    for ( File file : new File( PATH_POSITIVE ).listFiles() ) {
        Mat img = getMat( file.getAbsolutePath() );
        trainingImages.push_back( img.reshape( 1, 1 ) );
        trainingLabels.push_back( Mat.ones( new Size( 1, 1 ), CvType.CV_32FC1 ) );
    }
}

protected static void trainNegative() {
    for ( File file : new File( PATH_NEGATIVE ).listFiles() ) {
        Mat img = getMat( file.getAbsolutePath() );
        trainingImages.push_back( img.reshape( 1, 1 ) );
        trainingLabels.push_back( Mat.zeros( new Size( 1, 1 ), CvType.CV_32FC1 ) );
    }
}

protected static Mat getMat( String path ) {
    Mat img = new Mat();
    Mat con = Highgui.imread( path, Highgui.CV_LOAD_IMAGE_GRAYSCALE );
    con.convertTo( img, CvType.CV_32FC1, 1.0 / 255.0 );
    return img;
}

}
查看更多
登录 后发表回答