opencv训练时出现的错误处理

发布时间:2024-07-09 20:29:57 作者:yexindonglai@163.com 阅读(877)

一、使用opencv提供的工具进行训练时的错误处理

1、positives.txt(1) : parse errorDone. Created 0 samples

说明你的 正样本 路径写错了
正确格式:positive_images\1.jpg 1 0 0 20 20(路径+1+0+0+w+h)

2、注意:负样本直接写成路径即可,否则会出现后面错误:

  1. Train dataset for temp stage can not be filled. Branch training terminated.
  2. Cascade classifier can't be trained. Check the used training parameters.

3、运行:opencv_traincascade.exe时,注意添加-numPos 50(不一定为样本数,可能比样本数少,不然会出现以下错误) -numNeg 147(除非为默认样本数)

否则会出现以下错误:

  1. OpenCV Error: Bad argument (Can not get new positive sample.
  2. The most possible reason is insufficient count of samples in given vec-file.) in CvCascadeImageReader::PosReader::get,
  3. file C:\build\master_winpack-build-win64-vc14\opencv\apps\traincascade\imagestorage.cpp, line 158

4、Bad argument (_cascadeDirName or _bgfileName or _vecFileName is NULL) in CvCascadeClassifier::train,

  1. file C:\build\master_winpack-build-win64-vc14\opencv\apps\traincascade\cascadeclassifier.cpp
  2. 输入格式不对:可能少了 -

5、OpenCV Error: Assertion failed (_img.rows * _img.cols == vecSize) in CvCascadeImageReader::PosReader

加上 -w 20 -h 20 就好了(你正样本的宽度和高度)

6、Parameters can not be written, because file xml/params.xml can not be opened

表示无法打开文件,需要手动创建一个文件夹 xml

7、Traincascade Error:Bad argument(Can not get new positive sample.The most possible reason is insufficient count of samples in given vec-file.

numPos 数量设置的太大了, 数量小于正样本数量就行;

8、运行 opencv_createsamples.exe 提示:无法定位程序输入点 _ZNSt18condition_variable10notify_oneEv

这种情况一般是 mingw 环境变量的配置问题导致的;因为我编译opencv的时候使用的 posix 模型的mingw版本,而我环境变量同时配置了 win32 和 posix 模型的mingw,因为win32的环境配置在上面,所以会优先使用win32的,

要解决也很简单,只需要将posix模型的mingw 和 win32 替换个位置,让posix模型的mingw配置在上面就可以解决问题; 或者也可以将win32的配置删掉,也能解决问题

改完后再运行 opencv_createsamples.exe 就没问题了

9、OpenCV Error: Assertion failed (!empty()) in detectMultiScale

OpenCV级联检测器Cascadedetect出现错误,可知是xml路径读取错误,不要直接写入相对路径,要改为xml文件所在的绝对路径即可!

二、使用 opencv 代码进行训练时的错误处理

10、Assertion failed (samples.type() == CV_32F || samples.type() == CV_32S) in setData

调用train()函数训练时提示报错如下

  1. OpenCV: terminate handler is called! The last OpenCV error is:
  2. OpenCV(3.4.16) Error: Assertion failed (samples.type() == CV_32F || samples.type() == CV_32S) in setData, file D:\cpp\opencv3.4.16_vc14\sources\modules\ml\src\data.cpp, line 257

这是因为Mat 格式不对造成的,必须将 mat对象转为 CV_32F 或者 CV_32S 才行, 在训练函数前加上以下代码即可,

  1. //uchar型转换为 CV_32FC1
  2. sampleTmp.convertTo(sampleTmp, CV_32FC1);
  3. labelTmp.convertTo(labelTmp, CV_32FC1);

注意:训练样本数据矩阵(sampleTmp) 和 训练样本的标签矩阵(labelTmp) 都要转为 CV_32FC1,如果 训练样本的标签矩阵(labelTmp)未转换的话,会报以下错误

  1. OpenCV: terminate handler is called! The last OpenCV error is:
  2. OpenCV(3.4.16) Error: Assertion failed (responses.type() == CV_32F || responses.type() == CV_32S) in setData, file D:\cpp\opencv3.4.16_vc14\sources\modules\ml\src\data.cpp, line 290

11、Assertion failed ((layout == ROW_SAMPLE && responses.rows == nsamples) || (layout == COL_SAMPLE && responses.cols == nsamples)) in setData

调用opencv的训练函数train()时报错以下信息

  1. OpenCV: terminate handler is called! The last OpenCV error is:
  2. OpenCV(3.4.16) Error: Assertion failed ((layout == ROW_SAMPLE && responses.rows == nsamples) || (layout == COL_SAMPLE && responses.cols == nsamples)) in setData, file D:\cpp\opencv3.4.16_vc14\sources\modules\ml\src\data.cpp, line 296

这是因为调用train进行训练数据时,训练样本数据矩阵(sampleTmp) 和 训练样本的标签矩阵(labelTmp) 的行数不一致导致的,代码如下

  1. cout << sampleTmp.size<< endl;
  2. cout << labelTmp.size<< endl;
  3. bp->train(sampleTmp, ml::ROW_SAMPLE, labelTmp);
  4. // 以上代码输出结果如下 ,其中第一个数字是行数,第二个数字是列数
  5. sampleTmp 100000 x 20
  6. labelTmp 5000 x 1

根据输出结果可以分析,sampleTmp 行数为 100000 行,而labelTmp 只有5000 行,这2个变量的行数明显不一致,那我们就要将这2个变量的行数转为一致即可;因为之前的图片是20 20的,一共有5000张图,`5000 20 = 100000`,所以,只需要将 sampleTmp 中20 20的图片转为 1(行) 400(列)即可;可以使用 reshape 函数进行修改,将 100000 20 转为 5000 400

  1. //序列化,改变行数,将 100000 * 20 转为 5000 * 400, 序列化后放入特征矩阵
  2. sampleTmp = sampleTmp.reshape(0, 5000);
  3. cout <<"sampleTmp :"<< reshapeMat.size<< endl;
  4. cout <<"labelTmp :"<< labelTmp.size<< endl;
  5. bp->train(sampleTmp, ml::ROW_SAMPLE, labelTmp);

12、output training data should be a floating-point matrix with the number of rows equal to the number of training samples and the number of columns equal to the size of last (output) layer) in prepare_to_train

使用BP神经网络进行训练,代码如下:

  1. const string & numberPng = "图片路径";
  2. Mat & sampleTmp;
  3. Mat & labelTmp;
  4. // 读取图片
  5. Mat img = imread(numberPng);
  6. Mat gray;
  7. // 转为灰度图(黑白图)
  8. cvtColor(img, gray, CV_BGR2GRAY);
  9. int b = 20;
  10. int m = gray.rows / b; //原图为1000*2000
  11. int n = gray.cols / b; //裁剪为5000个20*20的小图块
  12. for (int i = 0; i < n; i++) {
  13. // 按列截取
  14. int offsetCol = i * b; //列上的偏移量
  15. for (int j = 0; j < m; j++) {
  16. int offsetRow = j * b; //行上的偏移量
  17. Mat tmp;
  18. //截取20*20的小块, 放到 tmp中
  19. gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp);
  20. //序列化,改变行数,将20*20的居中转为 1 * 400, 序列化后放入特征矩阵
  21. const Mat &reshapeMat = tmp.reshape(0, 1);
  22. sampleTmp.push_back(reshapeMat);
  23. labelTmp.push_back((double) (j / 5)); //对应的标注, 就是图片中的数字对应的值
  24. }
  25. }
  26. Ptr<ml::ANN_MLP> bp = ml::ANN_MLP::create();
  27. // 以下表示神经网络的层数为3,输入层神经元个数为 samcol个,隐含层为6,输出层为1
  28. Mat layers_size = (Mat_<int>(1, 3) << samcol, 6, 1); // samcol维点,1维输出
  29. // 设置神经网络的层数和神经元数量
  30. bp->setLayerSizes(layers_size);
  31. // ml::ANN_MLP::BACKPROP 是 ANN_MLP 类中的一个常量, 它表示采用反向传播算法(Back-Propagation)来训练前馈神经网络。
  32. // 第一个 0.1 表示学习速率,学习速率通常取值在 0 到 1 之间,较小的值能够确保算法稳定收敛,但收敛速度会较慢。较大的值可以加快收敛,但可能会导致算法发散。
  33. // 第二个 0.1 表示动量系数, 动量系数用于改善标准反向传播算法的收敛特性。动量系数控制了当前梯度与上一次梯度的相对权重,取值范围也在 0 到 1 之间, 适当的动量系数可以加快算法收敛,平滑权重更新,并防止算法陷入局部极小值。
  34. bp->setTrainMethod(ml::ANN_MLP::BACKPROP, 0.1, 0.1);
  35. // 设置激活函数为双曲正切函数
  36. bp->setActivationFunction(ml::ANN_MLP::SIGMOID_SYM);
  37. // 设置训练终止条件为最大迭代次数 1000 次,或误差小于 1e-6,即 0.000001
  38. // TermCriteria::MAX_ITER 表示使用最大迭代次数作为终止条件。
  39. bp->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 1000, /*FLT_EPSILON*/1e-6));
  40. // 使用训练样本 sample 和标签 labelsMat 进行 BP 神经网络的训练
  41. bp->train(sampleTmp, ml::ROW_SAMPLE, labelTmp);

调用bp->train()时整体报错如下:

  1. OpenCV: terminate handler is called! The last OpenCV error is:
  2. OpenCV(3.4.16) Error: Bad argument (output training data should be a floating-point matrix with the number of rows equal to the number of training samples and the number of columns equal to the size of last (output) layer) in prepare_to_train, file D:\cpp\opencv3.4.16_vc14\sources\modules\ml\src\ann_mlp.cpp, line 904

翻译:
prepare_to_train 中的参数错误(输出训练数据应为浮点矩阵,行数等于训练样本数,列数等于最后(输出)层的大小);

意思很明显,输出训练数据应为浮点矩阵,输出训练数据指的就是:训练样本的标签矩阵(labelTmp);

注意上面最后一行代码: labelTmp.push_back((int) j / 5); ,这里使用了int类型,这是不对的,按照opencv的要求,需要改为浮点数才行;所以改动后的代码如下, 确保结果是浮点型就ok!

  1. labelTmp.push_back((double) (j / 5));

13、Wrong input image size. Reason: Training and Test images must be of equal size! Expected an image with 2500 elements, but got 10304

报错全文:

  1. OpenCV: terminate handler is called! The last OpenCV error is:
  2. OpenCV(3.4.16) Error: Bad argument (Wrong input image size. Reason: Training and Test images must be of equal size! Expected an image with 2500 elements, but got 10304.) in predict, file D:\cpp\opencv_contrib-3.4.16\modules\face\src\eigen_faces.cpp, line 121

翻译:
参数错误(输入图像大小错误。原因:训练图像和测试图像必须大小相等!预期图像包含2500个元素,但实际得到10304个元素;

问题很明显,调用 predict 函数进行预测的时候,输入的图片大小和训练时的图片大小不一致,使用 cv::resize()函数改变大小即可;

14、Wrong shapes for given matrices

报错全文:

  1. OpenCV: terminate handler is called! The last OpenCV error is:
  2. OpenCV(3.4.16) Error: Bad argument (Wrong shapes for given matrices. Was size(src) = (1,7500), size(W) = (2500,1).) in subspaceProject, file D:\cpp\opencv3.4.16_vc14\sources\modules\core\src\lda.cpp, line 183

翻译:
给定矩阵的形状错误,识别图片时候,需要将原来的图片转换为灰度图片;读取图片变量的时候,将其转为灰度图即可

  1. # 读取图片变量的同时将图片转为灰度图
  2. Mat mat = imread(childPath,cv::COLOR_BGR2GRAY);
  3. # 将读取出来后再转为灰度图
  4. cv::cvtColor(mat, mat, cv::COLOR_BGR2GRAY);

15、 (_src.type() == CV_8UC1) in equalizeHist

报错全文:

  1. OpenCV: terminate handler is called! The last OpenCV error is:
  2. OpenCV(3.4.16) Error: Assertion failed (_src.type() == CV_8UC1) in 在调用(equalizeHist), file D:\cpp\opencv3.4.16_vc14\sources\modules\imgproc\src\histogram.cpp, line 3439

翻译:
指定是在调用 equalizeHist 函数(直方图均衡化:将灰度图进行均值化,使其更加黑白分明)时,必须使用8位的灰度图,该错误告诉你,你的图像不是 8 位灰度图像,需要使用以下函数进行转换

  1. Mat gray;
  2. cvtColor(resizeMat, gray, COLOR_BGR2GRAY);

16、Invalid number of channels in input image

报错全文:

  1. OpenCV: terminate handler is called! The last OpenCV error is:
  2. OpenCV(3.4.16) Error: Unspecified error (> Invalid number of channels in input image:
  3. > 'VScn::contains(scn)'
  4. > where
  5. > 'scn' is 1
  6. ) in cv::impl::{anonymous}::CvtHelper<VScn, VDcn, VDepth, sizePolicy>::CvtHelper(cv::InputArray, cv::OutputArray, int) [with VScn = cv::impl::{anonymous}::Set<3, 4>; VDcn = cv::impl::{anonymous}::Set<1>; VDepth = cv::impl::{anonymous}::Set<0, 2, 5>; cv::impl::{anonymous}::SizePolicy sizePolicy = (cv::impl::<unnamed>::SizePolicy)2; cv::InputArray = const cv::_InputArray&; cv::OutputArray = const cv::_OutputArray&], file D:\cpp\opencv3.4.16_vc14\sources\modules\imgproc\src\color.simd_helpers.hpp, line 88

翻译:
指的是输入图像中的通道数无效,这个报错通常是将单通道的图形转为单通道,单通道图形指的就是灰度图像,也就是说,当前的图形已经是灰度图了,你又再次将图片转为灰度图,就会报这个错误;解决方案是将带有 cv::COLOR_BGR2GRAY 的代码去掉即可

  1. // 去掉以下代码
  2. cvtColor(roi, roi, cv::COLOR_BGR2GRAY);

关键字OpenCV