OpenCV用图片样本训练SVM错误

OpenCV Training the SVM with picture examples Error

本文关键字:SVM 错误 样本 OpenCV      更新时间:2023-10-16

当训练我的分类器时,我得到这个错误:

图像步骤错误(矩阵不是连续的,因此它的行数不能改变)在重塑,文件/home/denn/downloads/opencv-2.4.6.1/modules/core/src/matrix.cpp,行802

在抛出'cv::Exception'实例后调用终止什么():/home/denn/downloads/opencv-2.4.6.1/modules/core/src/matrix.cpp:802:错误:(-13)矩阵不是连续的,因此它的行数不能在函数重塑中改变

Aborted (core dumps)

我在一个自动车牌识别项目在c++中工作。现在剩下的就是训练我的SVM了。

我调整了我所有的图像到450乘450研究后,但错误仍然存在。我研究了一下,但是没有一个方法适合我。

如能给予任何帮助,我将不胜感激。

    // Main entry code OpenCV
  #include <cv.h>
  #include <highgui.h>
  #include <cvaux.h>
  #include <iostream>
  #include <vector>
  using namespace std;
  using namespace cv;
   int main ( int argc, char** argv )
  {
cout << "OpenCV Training SVM Automatic Number Plate Recognitionn";
cout << "n";
char* path_Plates;
char* path_NoPlates;
int numPlates;
int numNoPlates;
int imageWidth=450; //144
int imageHeight=450; //33
//Check if user specify image to process
if(argc >= 5 )
{
    numPlates= atoi(argv[1]);
    numNoPlates= atoi(argv[2]);
    path_Plates= argv[3];
    path_NoPlates= argv[4];
}else{
    cout << "Usage:n" << argv[0] << " <num Plate Files> <num Non Plate Files> <path to plate folder files> <path to non plate files> n";
    return 0;
}        
Mat classes;//(numPlates+numNoPlates, 1, CV_32FC1);
Mat trainingData;//(numPlates+numNoPlates, imageWidth*imageHeight, CV_32FC1 );
Mat trainingImages;
vector<int> trainingLabels;
for(int i=0; i< numPlates; i++)
{
    stringstream ss(stringstream::in | stringstream::out);
    ss << path_Plates << i << ".jpg";
    Mat img=imread(ss.str(), 0);
    img= img.reshape(1, 1);
    trainingImages.push_back(img);
    trainingLabels.push_back(1);
}
for(int i=0; i< numNoPlates; i++)
{
    stringstream ss(stringstream::in | stringstream::out);
    ss << path_NoPlates << i << ".jpg";
    Mat img=imread(ss.str(), 0);
    img= img.reshape(1, 1);
    trainingImages.push_back(img);
    trainingLabels.push_back(0);
}
Mat(trainingImages).copyTo(trainingData);
//trainingData = trainingData.reshape(1,trainingData.rows);
trainingData.convertTo(trainingData, CV_32FC1);
Mat(trainingLabels).copyTo(classes);
FileStorage fs("SVM.xml", FileStorage::WRITE);
fs << "TrainingData" << trainingData;
fs << "classes" << classes;
fs.release();
return 0;
 }

我编辑了代码,使它像这样:

  // Main entry code OpenCV
#include <cv.h>
 #include <highgui.h>
 #include <cvaux.h>
#include <iostream>
#include <vector>
#include <iostream>
 using namespace std;
 using namespace cv;
  int main ( int argc, char** argv )
  {
  cout << "OpenCV Training SVM Automatic Number Plate Recognitionn";
  cout << "n";
char* path_Plates;
char* path_NoPlates;
int numPlates;
int numNoPlates;
int imageWidth=450; //144
int imageHeight=450; //33
//Check if user specify image to process
if(argc >= 5 )
{
    numPlates= atoi(argv[1]);
    numNoPlates= atoi(argv[2]);
    path_Plates= argv[3];
    path_NoPlates= argv[4];
}else{
    cout << "Usage:n" << argv[0] << " <num Plate Files> <num Non Plate Files> <path to plate folder files> <path to non plate files> n";
    return 0;
}        
Mat classes;//(numPlates+numNoPlates, 1, CV_32FC1);
Mat trainingData;//(numPlates+numNoPlates, imageWidth*imageHeight, CV_32FC1 );
Mat trainingImages;
vector<int> trainingLabels;

Mat classes = new Mat();
Mat trainingData = new Mat();
Mat trainingImages = new Mat();
Mat trainingLabels = new Mat();
for(int i=0; i< numPlates; i++)
{
    stringstream ss(stringstream::in | stringstream::out);
    ss << path_Plates << i << ".png";
    Mat img=imread(ss.str(), 0);
    img= img.reshape(1, 1);
    trainingImages.push_back(img);
    trainingLabels.push_back(1);//trainingLabels.push_back(Mat.ones(new Size(1, 1), CvType.CV_32FC1));//trainingLabels.push_back(1);
}
for(int i=0; i< numNoPlates; i++)
{
    stringstream ss(stringstream::in | stringstream::out);
    ss << path_NoPlates << i << ".png";
    Mat img=imread(ss.str(), 0);
    img= img.reshape(1, 1); //img= img.clone().reshape(1, 1);
    trainingImages.push_back(img);
    trainingLabels.push_back(0);//trainingLabels.push_back(Mat.zeros(new Size(1, 1), CvType.CV_32FC1));//trainingLabels.push_back(0);
}
trainingImages.copyTo(trainingData);
//trainingData = trainingData.reshape(1,trainingData.rows);
trainingData.convertTo(trainingData, CV_32FC1);
trainingLabels.copyTo(classes);
FileStorage fs("SVM.xml", FileStorage::WRITE);
fs << "TrainingData" << trainingData;
fs << "classes" << classes;
fs.release();
return 0;
   }

但是我在编译时得到这个错误:

    /home/denn/Desktop/NumberPlateRecognition/trainSVM.cpp:52:27: error: conversion from      ‘cv::Mat*’ to non-scalar type ‘cv::Mat’ requested
  /home/denn/Desktop/NumberPlateRecognition/trainSVM.cpp:52:27: error: conversion from   ‘cv::Mat*’ to non-scalar type ‘cv::Mat’ requested
 /home/denn/Desktop/NumberPlateRecognition/trainSVM.cpp:53:32: error: conversion from ‘cv::Mat*’ to non-scalar type ‘cv::Mat’ requested
  /home/denn/Desktop/NumberPlateRecognition/trainSVM.cpp:55:34: error: conversion from      ‘cv::Mat*’ to non-scalar type ‘cv::Mat’ requested
    /home/denn/Desktop/NumberPlateRecognition/trainSVM.cpp:56:34: error: conversion from        ‘cv::Mat*’ to non-scalar type ‘cv::Mat’ requested
 make[2]: *** [CMakeFiles/trainSVM.dir/trainSVM.cpp.o] Error 1
   make[1]: *** [CMakeFiles/trainSVM.dir/all] Error 2
  make: *** [all] Error 2

我有什么建议吗?

正如berak在上面的评论中指出的那样,在以下情况下,您的cv::Mat可能会变得不连续:

如果您使用Mat::col(), Mat::diag()等提取矩阵的一部分,或者为外部分配的数据构造一个矩阵头,这些矩阵可能不再具有[iscontinuous()]属性。

正如他们在上面的参考中指出的,使用Mat::create创建您的矩阵,您将不会有这个问题。

更新:

因此,函数Mat::clone,正如我们的朋友berak在上面的评论中指出的那样,将为您解决这个问题。它调用函数Mat::create。我刚刚尝试了下面的代码,它的效果非常好。

Mat trainingImages;
vector<int> trainingLabels;
for(int i=0; i< numPlates; i++)
{
  stringstream ss;
  ss << path_Plates << "grumpy" << i << ".jpg";
  std::cout << ss.str() << std::endl;
  Mat img =imread(ss.str(), CV_LOAD_IMAGE_GRAYSCALE);
  if(! img.data )  {
    cout <<  "Could not open or find the image" << std::endl ;
    return -1;
  }
  else {
    img = img.clone().reshape(0,1);
    trainingImages.push_back(img);
    trainingLabels.push_back(i);
  }
}

然而,一些注意事项,看起来您可能没有正确的头文件名。我在Ubuntu 12.04上使用了以下OpenCV 2.4.8:

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>

同时,确保用OpenCV库(即opencv_core和opencv_ml)编译它。