Pregunta

when training my classifier, i get this error:

Image step is wrong (The matrix is not continuous, thus its number of rows can not be changed) in reshape, file /home/denn/Downloads/opencv-2.4.6.1/modules/core/src/matrix.cpp, line 802

terminate called after throwing an instance of 'cv::Exception' what(): /home/denn/Downloads/opencv-2.4.6.1/modules/core/src/matrix.cpp:802: error: (-13) The matrix is not continuous, thus its number of rows can not be changed in function reshape

Aborted (core dumped)

I'm working on an Automatic Number Plate Recognition project in C++. all that is left now is train the my SVM.

I resized all my images to a 450 by 450 after researching this but the error persists. I have studied and looked around but none of the solutions works for me.

any help accorded will be highly appreciated.

    // 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;
 }

I edited the code and made it like this:

  // 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;
   }

but I get this error on compilation:

    /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

I any advice?

¿Fue útil?

Solución

As berak pointed out in the comments above, your cv::Mat can become discontinuous in the following instances:

if you extract a part of the matrix using Mat::col(), Mat::diag() , and so on, or construct a matrix header for externally allocated data, such matrices may no longer have [the iscontinuous()] property.

As they point out in the above reference, create your matrices using Mat::create and you won't have this issue.

Update:

So, the function Mat::clone, as our friend berak pointed out in the comments above, will do the trick for you. It calls the function Mat::create. I just tried out the following code, and it worked like a charm.

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);
  }
}

However, a few notes, it looks like you might not have the right header file names. I used the following with OpenCV 2.4.8 on Ubuntu 12.04:

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

Also, make sure to compile it with the OpenCV libraries (i.e. opencv_core and opencv_ml). Hope that helps you in your quest for plate recognition.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top