ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OpenCV训练自己的物体检测分类器步骤

2021-10-07 23:03:23  阅读:140  来源: 互联网

标签:exe opencv 步骤 样本 cv2 分类器 OpenCV path os


环境:python3.7  OpenCV3.4.3.18

工具:

opencv_annotation.exe

opencv_createsamples.exe

opencv_traincascade.exe

环境和工具下载安装

OpenCV库在cmd下终端命令
 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-contrib-python==3.4.3.18
包括了OpenCV主要模块以及OpenCV贡献库
工具在GitHub上下载
https://github.com/opencv/opencv/releases?after=3.4.3

安装OpenCV后在以下目录

一、准备阶段

 文件模板

 positive_images放置正样本图片、negative_image放置负样本图片、xml为训练好的分类器文件

样本收集

正样本:我们想要正确分类出的类别所对应的样本,例如,我们要对一张图片进行分类,以确定其是否属于菠萝,那么在训练的时候,菠萝的图片则为正样本。

负样本:不是我们想要的分类对应的样本,就是除了菠萝的图片

样本数据越多检测效果越好,正样本的特征越明显越好,负样本背景越复杂越好。

1、去www.kaggle.com下载想要的数据集或者使用scrapy+selenium批量爬取图片

2、自己拍摄想要检测物体的图片

二、预处理

图像的注水处理:通过自动对图像的旋转、平移、缩放从而增加样本数量

比如:通过旋转

"path是图片路径,执行后,会在同一目录下生成11张依次旋转30度的图片"
def spin(path):   
    retval=cv2.imread(path)
    he,we=retval.shape[:2]
    for x in range(1,12):
        M=cv2.getRotationMatrix2D(center=(we/2,he/2),angle=x*30,scale=1)
        M=cv2.warpAffine(retval,M,(we,he))
        new_path=path[:-3]+'-spin'+str(x)+'.jpg'
        #print(new_path)
        cv2.imwrite(new_path,M)

 调节亮度:

"path是图片路径,执行后会在同一目录下生成五张亮度依次递增的图片"
def light(path):
    retval=cv2.imread(path)
    img_hsv = cv2.cvtColor(retval, cv2.COLOR_BGR2HSV)
    darker_hsv = img_hsv.copy()
    for y in range(1,6):
        darker_hsv[:, :, 2] = darker_hsv2[:, :, 2]+2*y
        darker_img = cv2.cvtColor(darker_hsv, cv2.COLOR_HSV2BGR)
        new_path=path[:-3]+'-light+'+str(x)+'ipg'
        cv2.imwrite(new_path, darker_img)

图像大小统一处理(40*40):

批量重命名文件夹中的图片文件

import os
from PIL import Image


class BatchRename():
    def __init__(self):
        self.path = r'.\positive_images'
 
    def rename(self):
        filelist = os.listdir(self.path)
        total_num = len(filelist)
        i = 0
        for item in filelist:
            if item.endswith('.jpg'):
                src = os.path.join(os.path.abspath(self.path), item)
                print(src)
                dst = os.path.join(os.path.abspath(self.path), str(i) + '.jpg')
                try:
                    os.rename(src, dst)
                    print ('converting %s to %s ...' % (src, dst))
                    i = i + 1
                except :
                    continue
        print ('total %d to rename & converted %d jpgs' % (total_num, i))
 
if __name__ == '__main__':
    demo = BatchRename()
    demo.rename()
    pass

执行后 

批量修改图片尺寸

from PIL import Image
import os.path
import glob

def convertjpg(jpgfile,outdir,width=40,height=40):
    img=Image.open(jpgfile)
    try:
        new_img=img.resize((width,height),Image.BILINEAR)   
        new_img.save(os.path.join(outdir,os.path.basename(jpgfile)))
    except Exception as e:
        print(e)
for jpgfile in glob.glob(r".\positive_images\*.jpg"):
    #像素修改后存入images文件
    convertjpg(jpgfile,r".\positive_images")

三、生成样本描述文件

生成正样本描述文件可以利用标注工具opencv_annotation.exe

opencv_annotation.exe的使用,在当前目录cmd下输入opencv_annotation.exe可以看到是使用说明

 比如:opencv_annotation.exe -a=生成的pos.txt路径 -i=正样本文件夹路径

 

用鼠标左键标记进行矩形框选想要识别的物体 

 英文下,’c'是确认框选,'d'删除所选的框,'n'是下一张,'esc'是停止。

如果图片中只有一个物体,可直接生成描述文件(尽量自己用opencv_annotation标注,效果更好)

file_dir=os.getcwd()
print(file_dir)
file_dir=r'.\positive_images'
L=[]
i=0
with open(r".\pos.txt","w+") as f:
    for root, dirs, files in os.walk(file_dir):
        for file in files:  
            if os.path.splitext(file)[1] == '.jpg':
                L.append(os.path.join(root, file))
                f.write(L[i]+' 1'+' 0'+' 0'+' 40'+' 40'+'\n')
                i+=1

生成pos.txt 

生成负样本描述文件(不用进行标注)

file_dir=r'.\negative_image'
L=[]
i=0
with open(r".\neg.txt","w+") as f:
    for root, dirs, files in os.walk(file_dir):  
        for file in files:  
            if os.path.splitext(file)[1] == '.jpg':  
                L.append(os.path.join(root, file))
                f.write(L[i]+'\n')
                i+=1
print("ok")

生成neg.txt

四、 合成样本vec文件

这里只需要合成正样本vec文件,负样本不需要,这里使用opencv_createsamples.exe

opencv_createsamples.exe的使用,在当前目录cmd下输入opencv_createsamples.exe可以看到是使用说明

 比如opencv_createsamples.exe -vec pos.vec  -info pos.txt -num 50 -w 40 -h 40

-vec  参数代表.vec文件的存储位置;

-info  代表生成的annotation的位置;

-num  生成的正样本的数目

-w 窗口的宽度;-h 窗口的高度;

 结束之后在当前目录下生成pos.vec文件

五、训练模型

训练模型使用opencv_traincascade.exe

opencv_traincascade.exe的使用,在当前目录cmd下输入opencv_traincascade.exe可以看到是使用说明

 比如:opencv_traincascade.exe -data xml -vec pos.vec -bg neg.txt -numPos 10 -numNeg 2000 -numStages 15 -w 40 -h 40 -minHitRate 0.999 -maxFalseAlarmRate 0.5 -mode ALL

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

-vec:指定正样本集;

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

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

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

-numStage:训练的级数;

-w:正样本的宽;-h:正样本的高;(必须与opencv_createsample中使用的-w和-h值一致)

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

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

-mode:使用Haar-like特征时使用,可选BASIC、CORE或者ALL;(ALL使用垂直和45度角旋转特征。)

(这个截图是训练好模型后,再次运行opencv_traincascade.exe的结果)

 训练好分类器的文件在xml文件夹下

六、测试模型

import numpy as np
import cv2

#加载级联器
pineapple_cascade = cv2.CascadeClassifier(r'xml\cascade.xml')

#检测
def detect(image):
    #将图像转变为灰度图像
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    #调用级联器
    pineapples = face_cascade.detectMultiScale(gray,
                                         scaleFactor=1.15,
                                         minNeighbors=5,
                                         minSize=(10, 10))
    print(pineapples)
    print("发现{0}个菠萝!".format(len(pineapples)))
    #绘制出菠萝区域
    for (x, y, w, h) in pineapples:
        cv2.circle(image, (int((x + x + w) / 2), int((y + y + h) / 2)),
                   int(w / 2), (0, 255, 0), 2)
    return image

retval=cv2.imread(r'test.jpg')
image=detect(retval)
cv2.imwrite('detect.jpg',image)

 运行后生成检测后的图片detect.jpg(这里只是个展示,样本少,效果不是很好)

 

 以上只是一个简单的训练步骤展示,供参考学习使用

 

标签:exe,opencv,步骤,样本,cv2,分类器,OpenCV,path,os
来源: https://blog.csdn.net/qq_46292437/article/details/120628859

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有