[到手飞] 用OpenCV的级联分类器一键训练自己的目标检测数据集

这是一个帮助一键完成OpenCV级联分类器参数配置以及训练的脚本,简化了程序的调用与配置

最近需要编写一个目标检测项目,本来用的是YOLO框架,结果一通大刀阔斧自信满满的”优化”再加上长达3个小时的高强度训练后,十个测试样本能检测到一个都算走运了。迫于无奈与时间紧迫,试了一下OpenCV的级联分类器,没想到效果虽谈不上惊人但还算可用。关键时刻还得靠OpenCV救急。

使用步骤:

1.基础文件准备:

需要创建一个文件夹,并且该文件夹下至少存在如下文件:

[到手飞] 用OpenCV的级联分类器一键训练自己的目标检测数据集

该脚本已开源至 GitHub:

[到手飞] 用OpenCV的级联分类器一键训练自己的目标检测数据集

其中

opencv_traincascade.exe 并不依赖于python所安装的opencv版本(例如这里的训练器版本源自 OpenCV 4.5.2 而我python环境下的OpenCV版本为 3.4.1)

pos 文件夹下存放正样本,neg文件夹下存放负样本。其中正样本长宽比最好一致,因为后面算法会自动下采样至统一尺寸,长宽比保持一直可尽可能保证特征不失真,负样本尺寸无限制。同时正负样本数最好保证在1:3左右。存放样例如下图所示(图片文件名随意):

[到手飞] 用OpenCV的级联分类器一键训练自己的目标检测数据集

xml文件夹存在即可

2.开始训练

训练程序脚本 train.py 部分代码:

import cv2
import os

from options import Parameters

class train_xml:
    def __init__(self, para):
        self.work_path = os.getcwd()
        self.para = para
        # 样本数记录数据
        self.pos_num = 0
        self.neg_num = 0

    def generate_txt(self):
        # 生成正样本txt数据说明以及规范数据格式
        write_str = ''
        for root, dirs, files in os.walk(self.work_path + '\\pos'):  # 工作目录, 子目录, 文件
            for img_name in files:
                img = cv2.imread('pos\\' + img_name)
                h, w = img.shape[:2]
                if w < self.para.aim_w or h < self.para.aim_h:  # 尺寸过小的样本将被舍弃
                    print('log: positive sample discarded')
                else:
                    write_str += f'pos\\{img_name} 1 0 0 {w} {h}\n'
                    self.pos_num += 1
        with open('pos.txt', 'w') as result_file:
            result_file.write(write_str)
        # 生成负样本txt数据说明以及规范数据格式
        write_str = ''
        for root, dirs, files in os.walk(self.work_path + '\\neg'):  # 工作目录, 子目录, 文件
            for img_name in files:
                write_str += f'neg\\{img_name}\n'
                self.neg_num += 1
        with open('neg.txt', 'w') as result_file:
            result_file.write(write_str[:-1])
        # 生成正样本vec数据文件以及打印当前命令
        cmd = f'opencv_createsamples.exe -info {self.work_path}\\pos.txt ' \
              f'-vec pos.vec -num {self.pos_num} -w {self.para.aim_w} -h {self.para.aim_h}'
        print(f'command: {cmd}')
        os.system(cmd)

    def start_train(self, batch_size=48):
        # 这里只是类似于batch size, 即为每一级分类器所用到的正样本数, 设置的数量要小于总体正样本数, 太大会报错
        # 生成批处理bat数据文件
        if worker.pos_num = self.neg_num:
            neg_use = self.neg_num
        else:
            neg_use = 3 * pos_use
        write_str = f'opencv_traincascade -data xml -vec pos.vec -bg {self.work_path}\\neg.txt ' \
                    f'-numStages {self.para.numStages} ' \
                    f'-featureType {self.para.featureType} ' \
                    f'-minHitRate {self.para.minHitRate} ' \
                    f'-maxFalseAlarmRate {self.para.maxFalseAlarmRate} ' \
                    f'-mode {self.para.mode} ' \
                    f'-w {self.para.aim_w} -h {self.para.aim_h} -numPos {pos_use} -numNeg {neg_use}\n\npause'
        with open('start.bat', 'w') as result_file:
            result_file.write(write_str)
        # 输入1开始训练
        continue_switch = int(input('\nFile writing completed. Continue? (0 & 1)\necho: '))
        if continue_switch:
            cmd = 'start.bat'
            print(f'\ncommand: {cmd}')
            os.system(cmd)

if __name__ == '__main__':
    parameters = Parameters()

    worker = train_xml(parameters)
    worker.generate_txt()
    worker.start_train(batch_size=36)

参数配置脚本 options.py 部分代码:

class Parameters:
    def __init__(self):
        # 正样本目标尺度, 也为检测时的尺度
        self.aim_w = 28
        self.aim_h = 28
        # 训练参数
        self.numStages = 20
        self.featureType = 'LBP'
        self.minHitRate = 0.996
        self.maxFalseAlarmRate = 0.12
        self.mode = 'ALL'

路径等参数都已自动获取写入,所有需要调试的参数都在 options.py里,需要注意的参数如下:

正样本目标尺度, 也为检测时的尺度
self.aim_w = '228'
self.aim_h = '228'

这决定了最终训练时的输入图像大小,尽量与训练的正样本保持纵横比一直,需要从两个方面考虑:

一方面是硬件的的RAM限制,这里由于我的笔记本RAM是16G,在大约在230多的像素时内存占用就将近90%,所以这东西真的很吃内存;

二是使用时实际环境的输入图片中目标像素大小的限制,而并非这个训练的正样本尺寸越大越清晰就实际使用效果越好。因为最终检测时大多是将输入图像以不同尺度的下采样,再以当前这个目标尺度作为滑动窗口去目标检测。所以这个目标尺度最好包含在实际待检测图片中的实际物体尺寸除以缩放比例组(例如1.1、1.1^2 …)所组成的尺度组中。可参考下图(图片来源自网络):

[到手飞] 用OpenCV的级联分类器一键训练自己的目标检测数据集

以及一些其他参数的含义如下:

[到手飞] 用OpenCV的级联分类器一键训练自己的目标检测数据集

图片来源于网络

这些训练参数需要视具体场景调整(如偏重纹理特征则使用LBP训练),这里就不再做解释,具体原理参见其他文章:

[到手飞] 用OpenCV的级联分类器一键训练自己的目标检测数据集

[到手飞] 用OpenCV的级联分类器一键训练自己的目标检测数据集

同时貌似该训练器运算是单线程,即在我8核心16线程的CPU下,CPU占用率稳定下来占用率也只达到百分之十几,这可能也正是它最遗憾的缺陷之一。

3.完成测试

测试脚本 test.py 部分代码:

import numpy as np
import cv2

class Static_detection:
    def __init__(self):
        self.classifier = cv2.CascadeClassifier('cascade.xml')
        self.img = None

    def detect(self, img, draw_box=False):
        loc = []
        res = self.classifier.detectMultiScale(img, scaleFactor=1.1, minNeighbors=8, minSize=(28, 28))
        if draw_box:
            for (x, y, w, h) in res:
                cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
                loc.append([x, y, w, h])
            loc = np.array(loc)
            cv2.imshow('detection', img)
            cv2.waitKey(0)
            print('locations are: ', loc)
            return loc
        else:
            for (x, y, w, h) in res:
                loc.append([x, y, w, h])
            loc = np.array(loc)
            return loc

if __name__ == '__main__':
    eagle_eye = Static_detection()
    frame = cv2.imread('test.jpg', 1)
    # frame = cv2.resize(frame, None, fx=1/10, fy=1/10, interpolation=cv2.INTER_AREA)
    eagle_eye.detect(frame, draw_box=True)

将该py文件置于xml文件夹内即可,测试效果:

[到手飞] 用OpenCV的级联分类器一键训练自己的目标检测数据集

这里应项目要求是识别某几个大臭蛾子,样本较多时识别效果还不错。

[到手飞] 用OpenCV的级联分类器一键训练自己的目标检测数据集

训练完成后xml文件夹下会出现如上文件,除了两个标红的文件(其中cascade.xml正是训练结果文件)建议保留外,其他都是临时文件可以删除,这些临时文件只是帮助你在训练中断后恢复训练进度时用的。

训练参数可以很大的影响识别精度,所以需要耐心调教。

You Only need to Click Once

Thanks !

Original: https://blog.csdn.net/m0_57193659/article/details/124450430
Author: Z_MiCTrue
Title: [到手飞] 用OpenCV的级联分类器一键训练自己的目标检测数据集

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/681179/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • python与腾讯语音识别

    语音识别是一项比较复杂的技术,在单机上很难实现高效的识别功能,但借助云平台,就容易多了。 [En] Speech recognition is a relatively compl…

    人工智能 2023年5月27日
    095
  • mongodb/mongoTemplate.upsert批量插入更新数据的实现

    今天来记录一下,项目中使用到的mongoTemplate.upsert,在批量更新数据上的用法。 // mongoTemplate.upsert有三种用法,主要功能是更新数据,如果…

    人工智能 2023年7月29日
    090
  • Kaggle(入门)

    如果你想在 上运行自己的代码,可以按照以下步骤进行操作: 1. 登录 账号并创建一个新的 Notebooks。 2. 在 Notebooks 中选择”+ Add Dat…

    人工智能 2023年7月18日
    041
  • 图像处理——图像增强

    创作背景: 最近在忙着两个YOLOv7项目,通过看大量的论文,发现很多的相关的论文都会在收集图像后进行图像的增强,本文将使用python中的opencv模块实现常见的图像增强方法。…

    人工智能 2023年7月29日
    055
  • 因子分析原理及结果解析

    因子分析原理及结果解析 因子分析的起源: 1904年英国的一个心理学家发现学生的英语、法语和古典语成绩非常有相关性,他认为这三门课程背后有一个共同的因素驱动,最后将这个因素定义为&…

    人工智能 2023年6月19日
    065
  • dataframe常用笔记

    在jupyter notebook里面shift+tab查看函数详情 常用的库/包 import numpy as np import pandas as pd import se…

    人工智能 2023年7月6日
    076
  • 图像基本处理(灰度化)

    项目场景: 今天我们开始最基础的图像处理,将一张图片进行灰度化处理。我们将使用OpenCV来进行图像的处理 基础知识 图片主要包含以下内容:1.像素,也就是我们通常说的RGB模型,…

    人工智能 2023年5月26日
    085
  • 全网最全极限学习机(ELM)及其变种的开源代码分享

    💖作者简介:大家好,我是 车神哥,府学路18号的车神🥇⚡About—> 车神:从 寝室到 实验室最 快3分钟,最 慢3分半(半分钟献给 红 绿 灯)📝个人主页:车手只需要车和…

    人工智能 2023年7月27日
    059
  • 【代码解读】超详细,YOLOV5之build_targets函数解读。

    文章目录 * – + build_targets作用 + 注意 + 可视化结果 + 过程 + 详细代码解读 + * 准备 * 第一遍筛选 * 扩增正样本 + Refer…

    人工智能 2023年7月27日
    0188
  • 【Opencv】—–倾斜图片转正

    今天是我们来玩一个钉子。通过一个钉子来学习一个opencv中的一个函数,这个函数我网上也有搜过,不过遗憾的是,各路好手都是写的是有点不堪入目,现在这个学习氛围是越来越差了,很多人都…

    人工智能 2023年7月18日
    068
  • 数据分析方法(5)之同期群分析

    将同期群分开来看,同期就是相同时间段内,群就是具有某种相似特征或行为的用户即为一个群。 合起来看,同期群就是指相同时间段内具有相似特征或行为的用户。 最常见的按照日期进行分组,对同…

    人工智能 2023年7月8日
    0102
  • 近两年值得阅读的十篇医疗图像分割文献

    一. 题目:CE-Net: Context Encoder Network for 2D Medical Image Segmentation 投稿周期:稿件于 2018 年 12…

    人工智能 2023年7月13日
    0216
  • 【人工智能入门之机器学习决策树的学习(一)】

    ### 回答1: 机器学习_是一门涉及数据处理和模式识别的学科,它通过构建和训练模型来进行预测和分类。而MATLAB作为一种功能强大的计算机编程语言,具备丰富的数据处理和分析工具,…

    人工智能 2023年7月24日
    064
  • 搭建超级实用的免费机器翻译api

    项目场景: 项目中要用到中译英功能,之前项目中实现的是利用百度api服务。但是最近收到短信,百度的免费翻译api缩水严重。每次限制1000字符,一个月最大使用量为5w字符,无法满足…

    人工智能 2023年5月30日
    0131
  • [Python] 实现文本进度条

    目录 简单的开始 单行动态刷新 带刷新的文本进度条 简单的开始 进度条是计算机处理任务或执行软件中常用的增强用户体验的重要手段,它能度条功能。今天我们将利用 Python 字符串处…

    人工智能 2023年7月4日
    0113
  • TensorRT教程17: 使用混合精度–fp32、fp16、int8(重点)

    五种精度类型 kFLOAT kHALF kINT8 kINT32 kTF32 TF32精度 TF32 Tensor Cores 可以使用 FP32 加速网络,通常不会损失准确性。 …

    人工智能 2023年7月9日
    092
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球