[英]OpenCV Training the SVM with picture examples Error
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 在重塑文件/home/denn/Downloads/opencv-2.4.6.1/modules/core/src/matrix.cpp,第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 抛出'cv :: Exception'what()实例后终止终止调用:/home/denn/Downloads/opencv-2.4.6.1/modules/core/src/matrix.cpp:802:错误:(-13)矩阵是不连续的,因此无法在函数重塑中更改其行数
Aborted (core dumped) 中止(核心已弃用)
I'm working on an Automatic Number Plate Recognition project in C++. 我正在使用C ++进行自动车牌识别项目。 all that is left now is train the my SVM.
现在剩下的就是训练我的SVM。
I resized all my images to a 450 by 450 after researching this but the error persists. 经过研究,我将所有图像的尺寸调整为450 x 450,但错误仍然存在。 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? 我有什么建议吗?
As berak pointed out in the comments above, your cv::Mat
can become discontinuous in the following instances: 正如berak在上述评论中指出的那样,您的
cv::Mat
在以下情况下可能会变得不连续:
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.
如果您使用Mat :: col(),Mat :: diag()等来提取矩阵的一部分,或为外部分配的数据构造矩阵头,则此类矩阵可能不再具有[iscontinuous()]属性。
As they point out in the above reference, create your matrices using Mat::create
and you won't have this issue. 正如他们在上述参考中指出的那样,使用
Mat::create
矩阵,您将不会遇到此问题。
Update: 更新:
So, the function Mat::clone
, as our friend berak pointed out in the comments above, will do the trick for you. 因此,正如我们的朋友berak在上面的注释中指出的那样,
Mat::clone
函数将为您解决问题。 It calls the function Mat::create
. 它调用函数
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:
我在Ubuntu 12.04上将以下内容与OpenCV 2.4.8结合使用:
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>
Also, make sure to compile it with the OpenCV libraries (ie opencv_core and opencv_ml). 另外,请确保使用OpenCV库(即opencv_core和opencv_ml)进行编译。 Hope that helps you in your quest for plate recognition.
希望对您的车牌识别有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.