【问题标题】:OpenCV Training the SVM with picture examples ErrorOpenCV 用图片示例训练 SVM 错误
【发布时间】:2014-04-23 05:43:53
【问题描述】:

在训练我的分类器时,我收到此错误:

reshape,文件/home/denn/Downloads/opencv-2.4.6.1/modules/core/src/matrix.cpp中的图像步骤错误(矩阵不连续,因此无法更改其行数) ,第 802 行

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

中止(核心转储)

我正在使用 C++ 开发一个自动车牌识别项目。现在剩下的就是训练我的 SVM。

经过研究,我将所有图像的大小调整为 450 x 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 Recognition\n";
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 Recognition\n";
  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

我有什么建议吗?

【问题讨论】:

  • 如果 m.isContinuous() == false - 你不能调用 reshape 。越早解决管道中的问题越好
  • 那在哪里?我没有在任何地方看到它。您能否向我解释一下它的含义以及如何删除它?谢谢贝拉克
  • 问题出在您的数据中,而不是在您的代码中。您是否使用某些程序来预处理/调整图像大小?它可能会填充您的图像,因此宽度是 4 的倍数(这在这里是一件坏事)。
  • 就像下面的 robot_sherrick 提示一样,一旦您从旧数据中创建新的 Mat,您就可以摆脱问题。甚至可能是 img= img.clone().reshape(1, 1); 就可以了

标签: c++ opencv svm


【解决方案1】:

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

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

正如他们在上述参考中指出的那样,使用Mat::create 创建矩阵,您就不会遇到这个问题。

更新:

所以,正如我们的朋友 berak 在上面的 cmets 中指出的那样,函数 Mat::clone 将为您解决问题。它调用函数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)对其进行编译。希望对您寻求车牌识别有所帮助。

【讨论】:

  • 如何使用 Mat::create?有没有你知道的有更多解释和例子可以使用的来源?我自己的搜索被证明是徒劳的
  • 嘿,谢谢!它奏效了!就像你说的那样,就像一个魅力!
猜你喜欢
  • 1970-01-01
  • 2015-05-04
  • 2015-07-25
  • 2016-06-25
  • 2015-04-18
  • 2015-01-22
  • 2015-06-12
  • 2017-08-25
相关资源
最近更新 更多