用OpenCV3级联分类器自制自己的分类器详细过程

最近在做一个小项目,要训练自己的分类器,网上找了很多资料,但是没有很详细的,这里我将我做的过程,详细的总结一下,一来给大家总结经验,二来日后好查阅,原理我就不赘述,直接讲一下如何训练

一:图片的处理

做训练的图片要是灰度图,而且要统一大小,所以我就用python做了灰度化和归一化处理,代码如下:

from skimage import io,transform,color
import numpy as np
def convert_gray(f,**args):#图片处理与格式化的函数
      rgb=io.imread(f) #读取图片 
      gray=color.rgb2gray(rgb) #将彩色图片转换为灰度图片
      dst=transform.resize(gray,(40,40)) #调整大小,图像分辨率为40*40   
      return dst
datapath='D:/Face_Program/neg/' #图片所在的路径
str=datapath+'/*.jpg' #识别.jpg的图像
coll = io.ImageCollection(str,load_func=convert_gray)#批处理 
for i in range(len(coll)):

   io.imsave(r'D:/Face_Program/neg1//'+np.str(i)+'.jpg',coll[i]) #保存图片在d:/daate/date/人;

 

处理好图片后,我们就要开始训练了

 

二   生成可描述文件

在opencv的安装目录中的bin文件夹下有两个可执行文件opencv_createsamples.exe和opencv_traincascade.exe。将这两个文件拷贝到训练文件夹下,并将正、负样本的文件夹和描述文件——positive_samples.txt和negative_samples.txt也拷贝到这个文件夹下。同时,新建两个.bat文件——create_positive_samples.bat和traincascade.bat,新建一个文件夹data,data文件夹是用于存放之后训练完的数据。这样,训练目录如下:

用OpenCV3级联分类器自制自己的分类器详细过程_第1张图片

我会把这个opencv文件放在后面,需要的自己下载

 

 

用OpenCV3级联分类器自制自己的分类器详细过程_第2张图片
1。制作正样本,生成可描述文件

  • 打开window下的命令窗口,进入指定正样本数据目录下  输入:dir /b>positive_samples.txt 生成正样本的可描述文件

 

  • 用OpenCV3级联分类器自制自己的分类器详细过程_第3张图片

 

  • 然后使用editplus打开生成的文本文件positive_samples.txt 使用快捷键Ctrl+H打开Replace
             1.在行首填充所需字符

     

这里说明一下,图像处理成多少尺寸,生成描述文件的时候就是多少尺寸,我之间生成的是64*64的,但是训练的时候很慢我就改成40/840的了,正样本要有尺寸信息,负样本不需要。上面步骤是做的笔记现在保存退出,制作正样本

三  制作正样本

然后右键create_positive_samples.bat文件

用OpenCV3级联分类器自制自己的分类器详细过程_第4张图片

其中,-info字段填写正样本描述文件;-vec用于保存制作的正样本;-num制定正样本的数目;-w和-h分别指定正样本的宽和高。

保存,双击这个文件,开始制作正样本:

用OpenCV3级联分类器自制自己的分类器详细过程_第5张图片

 

用OpenCV3级联分类器自制自己的分类器详细过程_第6张图片

最后结果用OpenCV3级联分类器自制自己的分类器详细过程_第7张图片

 

这样,正样本制作完成了

 四  级联分类器训练

 

下面进行级联分类器的训练,在traincascade.bat中输入如下内容

用OpenCV3级联分类器自制自己的分类器详细过程_第8张图片

 

字段说明如下:

 

-data:指定保存训练结果的文件夹;

-vec:指定正样本集;

-bg:指定负样本的描述文件夹;

-numPos:指定每一级参与训练的正样本的数目(要小于正样本总数);

-numNeg:指定每一级参与训练的负样本的数目(可以大于负样本图片的总数);

-numStage:训练的级数;

-w:正样本的宽;

-h:正样本的高;

-minHitRate:每一级需要达到的命中率(一般取值0.95-0.995);

-maxFalseAlarmRate:每一级所允许的最大误检率;

-mode:使用Haar-like特征时使用,可选BASIC、CORE或者ALL;

numPos和numNeg要满足1:2.5-1:3之间,这个我自己也把握不好,只有自己慢慢试了,numStage一般在15-20之间,具体还是得靠自己把握,由于样本数不够或者内存等其他原因,训练层数达不到我们的结果,训练到一半就完成了,此时分类器还是可以用的,只是效果可能不太好,比如我自己最多只训练到第八层

另外,还可指定以下字段:

-featureType:可选HAAR或LBP,默认为HAAR;

其他字段将不再说明。


保存,双击执行,开始漫长的训练过程(训练可中断,中断后再执行,会继续中断前的训练

训练结束后,data文件夹下会生成如下训练结果

用OpenCV3级联分类器自制自己的分类器详细过程_第9张图片

cascade.xml文件即为最终的训练结果,即可拿来进行目标检测,通过上述方法,可以训练自己的分类器哦

 

测试如下,在一段视频中检测目标

 
 
import cv2
import sys
from PIL import Image
 
def CatchUsbVideo(window_name, camera_idx):
    cv2.namedWindow(window_name)
    
    #视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
    cap = cv2.VideoCapture(camera_idx)                
    
    #告诉OpenCV使用人脸识别分类器
    classfier = cv2.CascadeClassifier("D:\\Face_Program\\data4_8\\cascade.xml")
    
    #识别出人脸后要画的边框的颜色,RGB格式
    color = (0, 255, 0)
        
    while cap.isOpened():
        ok, frame = cap.read() #读取一帧数据
        if not ok:            
            break  
 
        #将当前帧转换成灰度图像
        grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)                 
        
        #人脸检测,1.2和3分别为图片缩放比例和需要检测的有效点数
        faceRects = classfier.detectMultiScale(grey, scaleFactor = 1.2, minNeighbors = 3, minSize= (40,40))
        if len(faceRects) > 0:            #大于0则检测到                                   
            for faceRect in faceRects:  #单独框出每一张
                x, y, w, h = faceRect        
                cv2.rectangle(frame, (x - 20, y - 20), (x + w + 10, y + h + 10), color, 2)
                        
        #显示图像
        cv2.imshow(window_name, frame)        
        c = cv2.waitKey(10)
        if c & 0xFF == ord('q'):
            break        

    #释放摄像头并销毁所有窗口
    cap.release()
    cv2.destroyAllWindows() 
    
if __name__ == '__main__':
    if len(sys.argv) != 1:
        print("Usage:%s camera_id\r\n" % (sys.argv[0]))
    else:
        CatchUsbVideo(" recognition region", 0)

希望能对大家有所帮助,有所启发

你可能感兴趣的:(openCV计算机视觉,opencv)