首页 > 其他分享 >OpenCV自学笔记13. 训练自己的分类器

OpenCV自学笔记13. 训练自己的分类器

时间:2022-12-29 14:06:47浏览次数:59  
标签:文件 13 img 32 样本 分类器 OpenCV 图像


训练自己的分类器

本小节使用的图片为:

OpenCV自学笔记13. 训练自己的分类器_html

最近在项目中遇到了一个问题,需要识别图像中的红色圆形。

Hough变换的效果还可以,但是存在计算量大等问题,因此,还需要一种更为准确的方法,识别图像中的圆形。

在此前提下,我尝试训练​级联分类器​,尽管分类器的效果不甚理想,但是也收获颇丰。现把训练过程记录如下。

——把大象装进冰箱里需要几步?
——三步
——训练自己的分类器也不例外,三步

首先,准备正样本和负样本数据
然后,训练,得到分类器
最后,测试,看看分类器好不好用

详细步骤如下:

Step1. 准备正样本和负样本数据

不像人脸识别那样,有现成的数据集。有时候,针对特定的问题,需要我们自己构建正负样本。

(1). 正样本的构建
大家可以根据自己的问题构建正样本。在这个问题中,我通过录制视频,得到视频中每一帧的图像。对这些图像,利用​​Hough圆形检测​​的方法,分割出圆形区域,将圆形区域作为图像,保存到文件中,最后通过人工的方式删除误检的图形。最后构建了大约800个正样本。

OpenCV自学笔记13. 训练自己的分类器_html_02

注意: 正样本要求所有图片的大小必须统一,OpenCV中推荐的大小是20 * 20(我这里是32 * 32)。对于大小不一致的图像,可以通过

dst = cv2.resize(src, (32, 32), interpolation=cv2.INTER_AREA)

将图像大小缩放至32 * 32。

(2). 负样本的构建

负样本的构建就容易多了。只要图像的尺寸大于等于正样本图像就可以了。你可以用一些阿猫阿狗的图像,也可以用一些大海森林的图像,但是不推荐用这些图像当做负样本。应该根据实际问题,把常见的场景拿来做负样本。

我将视频中的每一帧图像,进行切割,得到负样本。 具体说来,帧图像的大小是480 * 640,按照32 *32的大小,均分成300张小图片。然后通过人工的方式,排除近似于正样本的小图片,剩下的就是负样本图片。对视频中每一帧都进行上述切割,最后得到一组负样本。当然,也可以按照48*64进行切割,只要保证负样本图片的尺寸大于等于正样本就可以。切割的步骤,可以参考​​这篇文章​​。

负样本的数量大约为2100个,网上推荐正样本和负样本的比例大致在1 : 2到1 : 3之间

OpenCV自学笔记13. 训练自己的分类器_html_03

(3). 把正样本和负样本的路径,写到文件里

什么是“把正样本和负样本的路径写到文件里”呢?比如你正样本在C://your/path/1.jpg,就把C://your/path/1.jpg
写到一个文件中,专业名词叫做路径列表,这里可以写绝对路径,也可以写相对路径。

方法有很多,我这里使用几行Python代码,实现了这个功能。当然你也可以用Java写,用C写,甚至自己写一个.bat脚本。

正样本的处理代码如下: 其中 0 0 32 32 表示红色圆形在图像中的范围,也就是正样本图像的大小。

path = 'train_img_set/ball/'
dir = os.listdir(path) # 自动排序
fopen = open('train_img_set/info.txt', 'w')
for d in dir:
string = 'ball/' + d + ' 1 0 0 32 32' +'\n'
fopen.write(string)
fopen.close()

负样本的处理代码如下:

path = 'train_img_set/non-ball/' # 替换为你的路径
dir = os.listdir(path) # dir是目录下的全部文件
fopen = open('train_img_set/bg.txt', 'w') # 替换为你的路径
for d in dir: # d是每一个文件的文件名
string = 'non-ball/' + d + '\n' #拼接字符串并换行
fopen.write(string) # 写入文件中
fopen.close()

正样本如下:

OpenCV自学笔记13. 训练自己的分类器_xml_04

负样本如下:

OpenCV自学笔记13. 训练自己的分类器_html_05

(4). 生成正样本的描述文件

在cmd中 用一行命令搞定:

opencv_createsamples.exe -info info.txt -vec pos.vec -num 697 -w 32 -h 32

命令行参数如下:

-info 正样本说明文件

-vec 输出文件,内含用于训练的正样本。

-num 生成的正样本的数目。

-w 输出样本的宽度(以像素为单位)。

-h 输出样本的高度(以像素为单位)。

注:除了上述参数外,还可以配置其他参数,详细请见
​​​http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html​

在命令行中运行这个命令后,可以得到一个叫 pos.vec 的文件

注意,在运行前,需要用到opencv_createsamples.exe,这个文件可以从网上下载,也可以在OpenCV的安装目录下找到,我的是:D:\Program Files\OpenCV\OpenCV-249\opencv\build\x64\vc10\bin

Step2. 对样本进行训练

准备好样本后,对样本进行训练,使用一行命令:

opencv_haartraining.exe -data xml -vec pos.vec -bg bg.txt -nsplits 1 -npos 150 -nneg 450 -nonsym -w 32 -h 32 -mode all -mem 1280

命令行参数如下:

-data 目录名,用于存放训练好的分类器。

-vec 包含正样本的vec文件名(由 opencv_createsamples 程序生成)。

-bg 背景描述文件,也就是包含负样本文件名的那个描述文件。

-numPos 每级分类器训练时所用的正样本数目。

-numNeg 每级分类器训练时所用的负样本数目,可以大于 -bg 指定的图片数目。

-numStages 训练的分类器的级数。

-w 训练样本的宽(单位为像素)

-h 训练样本的高(单位为像素)

必须跟训练样本创建(使用 opencv_createsamples 程序创建)时的尺寸保持一致。

-mode all指定haar特征的种类,all表示使用垂直以及45度旋转特征

参数的详细说明请见:
​​​http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html​

注意,在运行前,需要用到opencv_haartraining.exe,这个文件的找法与opencv_createsamples.exe类似(见上文)。

训练的过程如下所示:

OpenCV自学笔记13. 训练自己的分类器_xml_06

OpenCV自学笔记13. 训练自己的分类器_xml_07

我在训练的过程中,程序会死掉(无法结束),可能是由于正负样本负样本差距不大所致,还需要继续研究一下。

程序死掉也别急,在xml目录下能看到生成了0、1、2、3几个文件,这些文件是训练时,各层的中间文件。我们可以使用convert_cascade.exe生成最后的xml文件,convert_cascade.exe可以从网上下载。

命令如下:

convert_cascade --size=32x32 C://Users//lijialin//PycharmProjects//Hockey//train_img_set//xml C://Users//lijialin//PycharmProjects//Hockey//train_img_set//xml//haar_adaboost.xml

OpenCV自学笔记13. 训练自己的分类器_xml_08

最后,在xml文件中,能看到一个haar_adaboost.xml文件,这个文件就是我们的通过训练得到分类器。

接下来测试这个分类器的效果。

Step3. 测试

测试程序如下:

cascade = cv2.CascadeClassifier('train_img_set/xml/haar_adaboost.xml')
img = cv2.imread('images/1111.png')
cv2.imshow('img', img)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
circles
= cascade.detectMultiScale(gray, 1.3, 5)
if faces is not None:
# x, y, w, h = circles[0]
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

测试结果如下,首先对一幅简单图片进行测试,可以看出,分类器准确地识别出了图像中的红色圆形:

OpenCV自学笔记13. 训练自己的分类器_xml_09

然后对一幅稍微复杂的图片进行测试,可以看到,分类器仅仅识别出了部分红色圆形,准确率是很低的,大概 4 / 9 = 44.4%:

OpenCV自学笔记13. 训练自己的分类器_OpenCV_10

参考资料:

训练分类器:

​​​http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html​​​

Hough识别圆形

图像切割

Python获取目录下的全部文件名,并写入文件中:

今天就到这里吧~

OpenCV自学笔记13. 训练自己的分类器_xml_11


标签:文件,13,img,32,样本,分类器,OpenCV,图像
From: https://blog.51cto.com/u_15762852/5976764

相关文章

  • [NOIP2013 提高组] 货车运输 题解
    [NOIP2013提高组]货车运输题解本题解介绍一种最大生成树+并查集+启发式合并离线的做法。想法题目要多次求两点之间的最大瓶颈路长度,所以可以先参照最小瓶颈路的通......
  • CF416B 1300
    题意解析f[i][j]代表第i幅画最后一次被j画了所花的时间,受到两个的限制,画当前这个画的前一个画家画完了,当前这个画家画完了前面那张画了,取max。代码#include<bits/std......
  • 【MindStudio训练营第一季】OpenCV插件-案例复现​
    【MindStudio训练营第一季】OpenCV插件-案例复现​案例复现流程​OpenCV插件介绍​本代码仓插件实现了opencv的抠图和缩放功能。抠图:支持根据目标检测的(x,y)坐标和(width,heig......
  • opencv-python学习之旅
    opencv-python操作*注:在此笔记中只记录下各种函数的使用,规则详细讲解见https://opencv.apachecn.org/#/docs/4.0.0/2.1-tutorial_py_image_display创建,读取,显示,保存图......
  • 强大的Ubuntu Touch OTA-13已开始推送
    Canonical的LukaszZemczak今天发布的通知称面向UbuntuPhone和Ubuntu平板设备的UbuntuTouchOTA-13系统更软已经成功通过rc-proposed通道向稳定版用户发送,不过整个更......
  • POI2013
    PriceList可以发现答案只有三种:要么最短路乘\(a\),要么最短路换成\(b\),要么最短偶数路换成\(b\)。这里的最短偶数路还要满足不经过\((x,y),(y,z)\)且\((x,z)\)有边。前......
  • OpenCasCade开发环境搭建 (vs2013+win7 64bit + OpenCasCade 6.8.0)
    我的安装环境:Windows7旗舰版SP1x64;VisualStudio2013;OpenCasCade-6.8.0源码包;OpenCasCade下载和安装​​http://www.opencascade.org/getocc/download/loadocc/​​解......
  • Java千问13:Java循环语句的几个冷门知识点你都知道吗?
    我们在进行Java开发的时候,经常会用到循环结构,但是有几个关于循环的“冷门”知识点,不知道你是不是都已经掌握了呢?我们一起来看看一、大括号可以不写吗?我们都知道,如果每次循......
  • P5137 题解
    前言首先感谢所有帮助我卡常的大佬们。题意求\((\sum_{i=0}^{n}a^ib^{n-i})\modp\)的值(\(n\leq10^{18}\),\(p\)不一定为质数)。分析看到数据范围,首先想到快......
  • CF234C 1300
    题意最后要形成形如前面从1k范围内全为负数,从k+1n范围内全为正数,没有0的存在,那此时最少应该改变几个值。解析ca[i]统计前面到i一共有多少个>=0的,cb[i]代表后面到i一共......