OpenCV训练级联分类器检测物体操作流程

OpenCV级联分类器操作流程

级联分类器在Android用的,先上效果图
在这里插入图片描述

第一次学用,参考了各位前辈的博客,十分感谢!
踩了一些坑,最后做出了一些成果,决定分享记录下来。
以下是参考:
https://blog.csdn.net/wuxiaoyao12/article/details/39227189
https://blog.csdn.net/LZY272942518/article/details/76512473
https://msd.misuland.com/pd/3148108429789233942 (解决我踩的第一个坑)

一、准备正负样本

新建用于存放正样本(pos)、负样本(neg)、训练结果(data)的文件夹,并将opencv中自带的创建样本程序 opencv_createsamples.exe 和训练程序opencv_traincascade.exe,放入文件夹,如下图。
(两个程序的路径: opencv\build\x86\vc15\bin\opencv_createsamples.exe,opencv\build\x86\vc15\bin\opencv_traincascade.exe)。

两个.bat文件是之后要用的
作为第一次学的小白,个人理解如下。如有不对之处,欢迎留言指出。指教就是给我帮忙,在下必然虚心接受。
正样本:只包含待检测物体的图像。
负样本:不包含样本的背景图像,需要比正样本分辨率大。
正样本可以通过VS,OpenCV,USB摄像头采集图像。负样本也可以通过网络批量下载图片,通过以下代码实现记录。
(源码参考:https://blog.csdn.net/LZY272942518/article/details/76512473)

// An highlighted block
#include<opencv2\opencv.hpp>
#include<highgui.h>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>
#include <ctype.h>

using namespace cv;
using namespace std;

Mat image;

int main(int argc, const char** argv)
{

	VideoCapture cap;
	cap.open(1);

	if (!cap.isOpened())
	{
		cout << "Could not initialize capturing...\n";
		return -1;
	}

	namedWindow("CamShift Demo", 1);

	Rect selection = Rect(150, 150, 250, 250);
	Mat frame, cp_roi;
	bool paused = false;
	int cnt = 1;
	for (;;)
	{
		cap >> frame;
		frame.copyTo(image);
		Mat roi(frame, selection);

		rectangle(image, Point(selection.x, selection.y), Point(selection.x + selection.width, selection.y + selection.height), Scalar(255, 0, 0), 1, 8);
		char c = (char)waitKey(10);

		//按下数字键0,将蓝框中图像(作为正样本)拷贝到指定文件夹
		if (c == '0')
		{
			roi.copyTo(cp_roi);
			resize(cp_roi, cp_roi, Size(40, 60));
			string filename_pos = "E:/A_YHK/2_mechanical_engineering/AAAAAA/Pickup_Tool/pos/";
			string str_pos = ".bmp";
			char filename1[50];
			filename_pos = filename_pos + to_string(cnt) + str_pos;
			cv::imwrite(filename_pos, cp_roi);
			cout << filename_pos << endl;
			cnt++;
		}

		//按下数字键9,将整改图像(作为负样本)拷贝到指定文件夹
		if (c == '9')
		{
			string filename_neg = "E:/A_YHK/2_mechanical_engineering/AAAAAA/Pickup_Tool/neg/";
			string str_neg = "neg.bmp";
			char filename1[50];
			filename_neg = filename_neg + to_string(cnt) + str_neg;
			cv::imwrite(filename_neg, frame);
			cout << filename_neg << endl;
			cnt++;
		}

		imshow("CamShift Demo", image);

		if (c == 27)
			break;

	}

	return 0;
}

于是文件夹中就有了正负样本的图像了。
注意:正样本图像需归一化为同样的尺寸大小(这里是40X60)。

二、制作训练数据集

在pos文件夹中新建文本文件,输入
dir /b > pos.dat
(不建议直接在网上复制,否则在保存的时候会出现编码问题)

修改后缀为 .bat ,相信大家都知道是为什么,双击执行就好了。
在这里插入图片描述
之后出现 .dat 文件,用记事本打开,删掉非图片的文字行,通过文字替换来描述正样本(描述参数的含义请参考前辈的博客)
在这里插入图片描述
同样的操作,在负样本文件夹 neg 中新建 .bat 文件,输入以下代码之后执行
DIR . /S/ON/B>neg.txt

删掉非图片的文字行,之后不用再替换描述语句了。

这里说明一下我掉进的坑,负样本中因使用绝对路径,所以应该使用以上的命令而不是dir /b > neg.dat
否则在最后训练的时候会出现以下错误:
Train dataset for temp stage can not be filled. Branch training terminated.

回到上一级目录,新建 .bat 文件,输入以下指令以创建正样本数据集(num 表示正样本图片的数量):
opencv_createsamples.exe -info pos\pos.dat -vec pos\pos.vec -num 397 -w 40 -h 60
pause

执行。
pos文件夹中生成 .vec 文件

现在pos文件夹下应该有三个非图片的文件:
在这里插入图片描述

三、训练

新建 .bat 文件,输入
opencv_traincascade.exe -data “E:\A_YHK\2_mechanical_engineering\AAAAAA\Pickup_Tool\data” -vec “E:\A_YHK\2_mechanical_engineering\AAAAAA\Pickup_Tool\pos\pos.vec” -bg “E:\A_YHK\2_mechanical_engineering\AAAAAA\Pickup_Tool\neg\neg.txt” -numPos 350 -numNeg 500 -numStages 14 -mem 2048 -featureType LBP -minHitRate 0.99 -maxFalseAlarmRate 0.5 -mode ALL -w 40 -h 60
pause

为了保险起见,我所有的文件都用的绝对路径。执行即可训练出分类器(各种参数原理,见前辈博客)

这里再一次说明一下我掉进的坑:numPos 参数表示每一个弱分类器所用的图片数量,我当时一共采了397张图片,但是输入397之后发现报错
在这里插入图片描述
于是乎我减少了numPos 的值,就成功了。
受前辈博客的启发,numPos 的值约为 numNeg 值的0.6~0.8倍左右,所以本人采用了0.7倍的值。
在data文件夹中可以看到结果,第一个文件是训练好的分类器。
在这里插入图片描述

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值