采用opencv中的opencv_createsamples和opencv_traincascade训练分类器

    最近有一个项目检测的想法,准备采用opencv的adaboost直接检测,今天从建立样本到训练分类器走了一遍,记录一下过程,当中也遇到费脑的坑。
一、准备样本 
        首先建立正负样本的训练集,最近有看python,以往matlab用的多,今天决定在python下构建样本集合。由于样本数据比较少,只有6、7张含有目标的原始图片,因此决定通过抠图得到目标图像,然后对目标图像进行增广处理,增加样本数量。
        样本抠图:这个程序比较简单,主要是首先遍历样本原图,然后通过一系列的鼠标动作来获取目标区域,最后抠图保存为目标图像。参考了几篇网络文章,该部分程序如下:
 
import sys
import os
import glob as gb
import cv2
import numpy as np

def on_mouse(event, x, y, flags, param):
    global img,point1,point2,cut_img
    img2 = img.copy()
    if event == cv2.EVENT_LBUTTONDOWN: #左键点击
        point1 = (x,y)
        cv2.circle(img2, point1, 5, (0,255,0), 1)
        cv2.imshow('image', img2)
    elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON): #按住左键拖曳
        cv2.rectangle(img2, point1, (x,y), (255,0,0), 1)
        cv2.imshow('image', img2)
    elif event == cv2.EVENT_LBUTTONUP: #左键释放
        point2 = (x,y)
        cv2.rectangle(img2, point1, point2, (0,0,255), 1)
        cv2.imshow('image', img2)
        min_x = min(point1[0],point2[0])
        min_y = min(point1[1],point2[1])
        width = abs(point1[0] - point2[0])
        height = abs(point1[1] -point2[1])
        cut_img = img[min_y:min_y+height, min_x:min_x+width]


def main():
    global img,cut_img
    root_path = "E:/text detection/"
    count = 0
    img_path = gb.glob(root_path+"*.bmp")
    for path in img_path:
        print(path)
        img = cv2.imread(path)
        count = count+1;
        cv2.namedWindow('image')
        cv2.setMouseCallback('image', on_mouse)
        cv2.imshow('image', img)
        cv2.waitKey(0)
        cut_gray = cv2.cvtColor(cut_img,cv2.COLOR_RGBA2GRAY)
        cv2.imwrite(str(count) + '.jpg', cut_gray)
 
if __name__ == '__main__':
    main()

样本多样性拓展:在的到样本图像后,从平移、旋转和增加噪声三个角度出发对增加样本多样性,对于旋转仅考虑了居中旋转,没有考虑放射变换之类复杂的增广手段。具体代码为:
import sys
import os
import glob as gb
import cv2
import numpy as np

# 定义平移translate函数
def translate(image, x, y):
    # 定义平移矩阵
    M = np.float32([[1, 0, x], [0, 1, y]])
    shifted = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
    # 返回转换后的图像
    return shifted
# 定义旋转rotate函数
def rotate(image, angle, center=None, scale=1.0):
    # 获取图像尺寸
    (h, w) = image.shape[:2]
    # 若未指定旋转中心,则将图像中心设为旋转中心
    if center is None:
        center = (w / 2, h / 2)
    # 执行旋转
    M = cv2.getRotationMatrix2D(center, angle, scale)
    rotated = cv2.warpAffine(image, M, (w, h))
    # 返回旋转后的图像
    return rotated

#增加噪声
def addNoise(img):
    noise = np.random.randint(0, 20, img.shape)
    noise = noise.astype(np.uint8)
    img2 = cv2.addWeighted(noise, 1, img, 1, 0)
    return img2

def main():
    global img,cut_img
    root_path = "E:/text detection/pos/"
    count = 0
    img_path = gb.glob(root_path+"*.jpg")
    #图像平移上下左右各5个像素
    for path in img_path:
        img = cv2.imread(path)
        img = cv2.cvtColor(img,cv2.COLOR_RGBA2GRAY)
        for x in range(-5,6):#x方向移动
            for y in range(-5,6):#y方向移动
                im = translate(img,x,y)
                for angle in range(-2,2):#上下转动
                    ima = rotate(im,angle)
                    count = count + 1;
                    imn = cv2.resize(ima,(100,20))
                    cv2.imwrite(root_path+str(count) + '.bmp', imn)
                    for st in range(1,2):
                        count = count + 1;
                        imnoise = addNoise(imn)
                        imn = cv2.resize(imnoise, (100, 20))
                        cv2.imwrite(root_path + str(count) + '.bmp', imn)

if __name__ == '__main__':
    main()
     通过该方法大概获得了6000张左右的正样本,对于负样本则进行了随机截取,主要是截取时尺度随机,但要比正样本大,负样本一共截取了20000左右。
      建立样本后需要对样本处理,两类样本都应该建立一个样本说明文件,而正样本还需要生成opencv需要的vec格式文件。可以采用建立bat批处理文件或者直接调用命令参数行来完成。
        样本说明文件可以采用命令:切换到当前目录  运行命令 dir/b>pos.txt    其中pos.txt为自己建立的样本文件名字,可以任取。此时pos.txt文件中已给出所有正样本图像名字列表,注意把最后一行不属于图像名字的内容删除。  负样本采用相同的方法来得到:dir/b>neg.txt。
   下一步则是采用opencv_createsamples.exe生成正样本vec文件,具体命令为:opencv_createsamples.exe -info pos\pos.txt -vec pos\pos.vec -num 6556 -w 120 -h 20    ,其中-info说明了正样本信息,-vec给出生成的vec文件名字和位置,后面则为样本个数和样本的尺度。
二 训练样本
     此处遇到了最大的坑,一下午的时间浪费在此处。
     训练的时候采用opencv_traincascade.exe 具体命令为:opencv_traincascade.exe -data data -vec pos\pos.vec -bg neg\neg.txt -numPos 5000 -numNeg 11000 -numStages 15 -featureType LBP -w 100 -h 20 -minHitRate 0.999 -maxFalseAlarmRate 0.5,其中data为存放xml分类文件的目录,这里采用了lbp特征,计算速度较快。在训练的时候遇到了奇怪的问题,正样本可以读,因为在vec文件里, 负样本读到10199个时,就崩溃了,没法继续训练。 此时决定采用小样本量来试一下,pos 500,neg 1000,可以训练,但一轮后读负样本时读到几百个又崩溃了。查找了大量的网页,经过多次测试一直不行。此时想可能是opencv的问题,我用的是2413已经编译过的版本,决定下载个opencv3.4试一下,官网编译后的文件下载太慢,因此从github下载源代码自己编译。先用cmake生成vs解决方案,注意要把cuba类的应用去掉,否则太慢。生成dll文件后,加入测试,成功运行。
    因此,使用opencv时,保险起见,最后下载源代码在自己的机器上重新编译。


 
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值