Python-OpenCV —— 物体识别(TrainCascadeClassification)

在上次教程Python-OpenCV —— Machine Learning讲述了如何建立模型,进行训练,然后利用模型对新获得的照片进行预测并给出预测值,本期教程针对某个特定的物体进行检测,将其标记出来,分为3个步骤,第一:训练特定物体,第二:

训练模型

级联分类器

前几天看到一个笑话,很有意思,说的是

  • 理论就是你什么都知道但是什么都干不了
  • 实践就是你什么都能干但是不知道为什么
  • 我就不一样了,我可以理论与实践相结合——什么都干不了而且不知道为什么

开个玩笑,目前有很大一部分的东西都是人们实践得来的经验,有些东西也许很好用,但未必是好理论,比如现在的深度学习,扯远了,继续今天的话题,到底什么是级联分类器,其实就是把分类器按照一定的顺序联合到一起。一个分类器也许不好用,没关系,我给你多加几个,俗话说得好,三个臭皮匠,顶个诸葛亮呢。

具体来说,OpenCV实现的Cascade(级联)分类器就是基于多个弱分类器对不同的特征进行依次处理(分类)来完成对目标的检测,简单的说有多个弱分类器串起来,然后提取每个平滑窗上的不同特征,把这些特征依次放进不同的弱分类器里判断,如果所有的弱分类器都判断正标签,则表示该该平滑窗内检测到目标。这样做的好处是不但通过多个弱分类器来形成一个强的级联分类器,而且可以减少运算量,比如当一个平滑窗第一个特征没有通过第一个分类器,那么就没有必要继续运算下去,直接拒绝掉当前平滑窗,转而处理下一个平滑窗,事实上作者的目的就是为了快速抛弃没有目标的平滑窗,从而达到快速检测目标。

本次用到了OpenCV的两个程序,分别是opencv_createsamples.exeopencv_traincascade.exe,分别用来创建样本文件和训练级联分类器。

准备训练数据

正样本

正样本就是你要检测的东西,比如说香蕉、车牌、酒瓶、红绿灯等等,你可以找相关的数据集,或者自己手动截图,只取你想要识别的那部分,下面我给了一个小程序用来将你截取的图片都变成统一大小。

#改变图片尺寸为统一大小,在当前目录创建一个名为pos的文件夹
#把需要统一尺寸的正样本放到里面,写上尺寸,运行程序就可以了,一般来说建议长宽在100像素一下,不然训练会很慢
import cv2
import os

w = **
h = **

def getimage(file_dir):   
    images = {}
    for root, dirs, files in os.walk(file_dir):  
        for name in files:
            images[name] = os.path.join(root,name)
    return images

    
if __name__ == '__main__':
    n=-1
    aa = os.getcwd()
    dirpath = os.path.join(aa, 'pos')
    imagedic = getimage(dirpath)

    try :
        for key,value in imagedic.items():
            img = cv2.imread(value)
            img1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)             
            img2 = cv2.resize(img1,(w,h)) 
            cv2.imwrite('pos'+str(n+1).rjust(3,'0')+'.jpg',img2)
            n+=1
    except KeyboardInterrupt:
        print('暂停一下')

修改完图片尺寸之后,需要生成图片的路径,我也写了一个代码,运行后,会在当前目录生成一个如图所示的文件


pos.txt

每一行分别代表文件路径 1代表里面有几个目标,咱们用的截取好的,所以只有一个,然后 0 0 60 120 分别代表着图片的起始像素和终止像素的长宽

#会在当前目录生成一个如图所示的文件,记得修改 w h 为上面修改后的尺寸值
import os

def getimage(file_dir):   
    images = {}
    for root, dirs, files in os.walk(file_dir):  
        for name in files:
            images[name] = os.path.join(root,name)
    return images

    
if __name__ == '__main__':
    n=0
    aa = os.getcwd()
    dirpath = os.path.join(aa, 'pos')
    imagedic = getimage(dirpath)
    #print (imagedic)

    try :
        for key,value in imagedic.items():
            with open ('pos.txt','a') as f:
                f.write('pos/'+str(key).rjust(3,'0')+' 1 0 0 w h''\n')
    except KeyboardInterrupt:
        print('暂停一下')

接下来就要用opencv_createsamples.exe生成正样本文件了,写了一个批处理文件,新建crate_samples.bat,打开编辑

"在此处写上你的opencv_createsamples.exe路径"  -info "pos.txt" -vec pos.vec -num 200 -w 60 -h 120   

一些参数解释:

  • info 输入正样本描述文件

  • img 输入图像文件名,默认NULL

  • bg 负样本描述文件,文件中包含一系列的被随机选作物体背景的图像文件名,默认NULL

  • num 生成正样本的数目,默认1000

  • bgcolor 背景颜色,表示透明颜色,默认0

  • bgthresh 颜色容差,所有处于bgcolor- bgthresh和bgcolor+bgthresh之间的像素被置为透明像素,也就是将白噪声加到前景图像上,默认80

  • inv 前景图像颜色翻转标志,如果指定颜色翻转,默认0(不翻转)

  • randinv 如果指定颜色将随机翻转,默认0

  • maxidev 前景图像中像素的亮度梯度最大值,默认40

  • maxxangle X轴最大旋转角度,以弧度为单位,默认1.1

  • maxyangle Y轴最大旋转角度,以弧度为单位,默认1.1

  • maxzangle Z轴最大旋转角度,以弧度为单位,默认0.5

输入图像沿着三个轴进行旋转,旋转角度由上述3个值限定。

  • show 如果指定,每个样本都将被显示,按下Esc键,程序将继续创建样本而不在显示,默认为0(不显示)

  • scale 显示图像的缩放比例,默认4.0

  • w 输出样本宽度,默认24

  • h 输出样本高度,默认24

  • vec 输出用于训练的.vec文件

负样本

负样本只需要生成路径文件,不需要生成vec文件,具体步骤跟上面类似,要注意的是负样本要尽可能比正样本多,大概十倍的样子吧。

开始训练

新建一个文件夹TrainCascadeClassification,一会训练好的文件就在这里
新建一个train.bat,编辑

"你的opencv_traincascade.exe目录"  -data "你的TrainCascadeClassification目录" -vec pos.vec -bg neg.txt -numPos 160 -numNeg 500 -numStages 15 -precalcValBufSize  3000  -precalcIdxBufSize  3000 -featureType LBP  -w 60 -h 120 
Pause  

一些参数解释

  • data 训练的分类器的存储目录
  • vec 正样本文件,由open_createsamples.exe生成,正样本文件后缀名为.vec
  • bg 负样本说明文件,主要包含负样本文件所在的目录及负样本文件名
  • numPos 每级分类器训练时所用到的正样本数目,应小于vec文件中正样本的数目,具体数目限制条件为:numPos+(numStages- 1)numPos(1- minHitRate)<=vec文件中正样本的数目。根据我的经验,一般为正样本文件的80%
  • numNeg 每级分类器训练时所用到的负样本数目,可以大于- bg指定的图片数目。根据我的经验,一般为numPos的2-3倍
  • numStages 训练分类器的级数,强分类器的个数。根据我的经验,一般为12-20
  • precalcValBufSize 缓存大小,用于存储预先计算的特征值,单位MB,根据自己内存大小分配
  • precalcIdxBufSize 缓存大小,用于存储预先计算的特征索引,单位MB,根据自己内存大小分配
  • featureType 训练使用的特征类型,目前支持的特征有Haar,LBP和HOG
  • w 训练的正样本的宽度
  • h 训练的正样本的高

进阶参数

  • minHitRate 影响每个强分类器阈值,每一级分类器最小命中率,表示每一级强分类器对正样本的的分类准确率
  • maxFalseAlarm 最大虚警率,影响弱分类器的阈值,表示每个弱分类器将负样本误分为正样本的比例,一般默认值为0.5
  • weightTrimRate 0- 1之间的阈值,影响参与训练的样本,样本权重更新排序后(从小到大),从前面累计权重小于(1- weightTrimRate)的样本将不参与下一次训练,一般默认值为0.95
  • maxDepth 每一个弱分类器决策树的深度,默认是1,是二叉树(stumps),只使用一个特征。
  • maxWeakCount 每级强分类器中弱分类器的最大个数,当FA降不到指定的maxFalseAlarm时可以通过指定最大弱分类器个数停止单个强分类器

这个时候先看一下我们的工作目录下都有那些东西,没有的话,记得补全它。


工作目录

然后打开train.bat,等着就可以了,训练结束后,会得到自己的xml文件,就可以调用了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容