opencv训练时出现的错误处理

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

一、使用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));

关键字OpenCV