精华内容
下载资源
问答
  • 级联分类器训练过程(步骤)

    千次阅读 2018-04-23 17:56:33
    本文借助百度翻译,翻译自:...正文详情如下:介绍使用改进的级联弱分类器包括两个主要阶段:训练阶段和检测阶段。检测阶段使用HAAR或基于LBP的模型,在对象检测教程(object detection tut...

    本文借助百度翻译,翻译自:https://docs.opencv.org/master/dc/d88/tutorial_traincascade.html

    由于本人英语水平有限,翻译有不通顺的地方请参考OpenCV官网,请谅解。正文详情如下:


    介绍

    使用改进的级联弱分类器包括两个主要阶段:训练阶段和检测阶段。检测阶段使用HAAR或基于LBP的模型,在对象检测教程(object detection tutorial,地址:https://docs.opencv.org/master/db/d28/tutorial_cascade_classifier.html)中描述。该文档概述了训练自己的弱分类器级联的功能。本指南将贯穿不同的阶段:收集培训数据,准备培训数据和执行实际模型培训。

    为了支持本教程,将使用几个官方OpenCV应用程序: opencv_createsamplesopencv_annotationopencv_traincascade 和opencv_visualisation.

    重要说明

    • 如果你遇到任何教程提到旧的openocv-haartraining工具(它被弃用并且仍然使用OpenCV1.x接口),那么请忽略该教程,并坚持opencv-tracecascade工具。这个工具是一个新的版本,根据OpenCV 2.x 和3.x的API用C++编写。opencv_traincascade支持Haar样小波特征[191 ]和LBP(局部二进制模式)[108 ]特征。LBP的特征产生整数精度与Haar特征相比,产生了浮点精度,因此LBP的训练和检测比HAAR特征要快几倍。对于LBP和Haar检测质量,主要取决于所使用的训练数据和训练参数的选择。在训练时间的百分比内训练一个基于LBP的分类器可以提供几乎与Haar基分类器相同的质量。
    • 较新的级联分类器检测接口从OpenCV 2.x和OpenCV 3.x(cv::CascadeClassifier)支持与旧的和新的模型格式一起工作。opencv_traincascade甚至可以保存(导出)一个经过训练的级联,如果由于某种原因,你使用旧接口卡住。至少训练模型可以在最稳定的接口中完成。
    • opencv_traincascade应用程序可以使用TBB进行多线程处理。要在多核模式下使用OpenCV,必须建立TBB支持。

    训练数据的准备

    为了训练一个增强的弱分类器级联,我们需要一组正样本(包含要检测的实际对象)和一组负面图像(包含所有你不想检测到的)。负样本的集合必须手动准备,而正样本集是使用opencv_createsamples应用程序创建的。

    负样本

    负样本取自任意图像,不包含要检测的对象。这些负的图像,从其中产生的样本,应该被列在一个特殊的负图像文件中,每行包含一个图像路径(可以是绝对的或相对的)。注意,负样本和样本图像也称为背景样本或背景图像,并且可在本文档中互换使用。

    所描述的图像可以具有不同的尺寸。然而,每个图像应该等于或大于所需的训练窗口大小(对应于模型维度,大多是目标的平均大小),因为这些图像用于将给定的负图像子采样成具有此训练窗口大小的多个图像样本。

    一个负样本文件示例:

    目录结构:

    /img
      img1.jpg
      img2.jpg
    bg.txt

    文件 bg.txt:

    img/img1.jpg
    img/img2.jpg

    当你试图找到你感兴趣的目标时,你的一组负面窗口样本将被用来告诉机器学习步骤,在这种情况下,不必寻找。

    正样本:

    正样本是由opencv_createsamples应用程序创建的。它们被升压(boosting。本人对此翻译持怀疑态度,故将英文贴在此处)过程使用来定义当试图找到感兴趣的目标时,模型应该实际寻找什么。该应用支持生成正样本数据集的两种方式。

    1. 你可以从单个正目标图像中生成一组正样本。
    2. 您可以自己提供所有的正样本图像,使用工具将它们裁剪,调整大小,并把它们放在OpenCV所需的二进制格式中。

    虽然第一种方法对于固定的物体(如不会变化的Logo)的工作很有意义,但是对于刚性较低的物体来说,它很快就会失败。在这种情况下,我们建议使用第二种方法。网上的许多教程甚至陈列了100个真实对象图像,通过使用opencv_createsamples应用程序,可以得到比1000个人工生成的更好的正模型。然而,如果你真的决定采取第一种方法,记住一些事情:

    • 请注意,在将它提交给所提到的应用程序之前,您需要多于一个正样本,因为它只应用透视变换。
    • 如果你想要一个健壮的模型,那么就要检查覆盖在你的对象类中的各种各样的品种。例如,在检测人脸的情况下,你应该考虑不同的种族和年龄组,情感,甚至胡须风格。这也适用于使用第二种方法。

    第一种方法采用单个对象图像,例如公司Logo,并通过随机旋转对象,改变图像强度以及将图像放置在任意背景上,从给定的目标图像创建一组大的正样本。随机性的数量和范围可以由opencv_createsamples应用程序的命令行参数来控制。

    命令行参数:

    • -vec <vec_file_name> : 输出文件的名称,包含用于训练的正样本。
    • -img <image_file_name> : 源对象图像(例如,公司徽标)。
    • -bg <background_file_name> : 背景描述文件;包含作为背景随机扭曲对象的背景的图像列表。
    • -num <number_of_samples> : 产生正样本的数目。
    • -bgcolor <background_color> : 背景颜色(当前假设灰度图像);背景颜色表示透明颜色。由于可能存在压缩伪影,颜色公差的量可以由 -bgthresh指定。bgcolor-bgthresh和bgcolor+bgthresh范围内的所有像素都被解释为透明的。
    • -bgthresh <background_color_threshold>
    • -inv : 如果指定,颜色将被反转。
    • -randinv : 如果指定,颜色将被随机反转。
    • -maxidev <max_intensity_deviation> : 前景样本中像素的最大强度偏差。
    • -maxxangle <max_x_rotation_angle> : X轴的最大旋转角,必须以弧度表示。
    • -maxyangle <max_y_rotation_angle> : 在y轴上的最大旋转角必须以弧度表示。
    • -maxzangle <max_z_rotation_angle> : 对于Z轴的最大旋转角,必须以弧度给出。
    • -show : 有用的调试选项。如果指定,每个样品将被显示。按“Esc”将退出显示图像继续样本生成步骤。
    • -w <sample_width> : 输出样本的宽度(以像素为单位)。
    • -h <sample_height> : 输出样本的高度(以像素为单位)。

    当以这种方式运行opencv_createsamples时,使用以下过程创建示例对象实例:给定源图像在所有三个轴上随机旋转。选择的角度是有限的-maxxangle-maxyangle-maxzangle。然后,从[bg_color-bg_color_threshold; bg_color+bg_color_threshold]范围的强度的像素被解释为透明的。白噪声被添加到前景的强度。如果指定了-inv密钥,则前景像素强度被反转。如果指定了-randinv密钥,则算法随机选择是否应该将反演应用于该样本。最后,将所获得的图像从背景描述文件放置到任意背景,将大小调整为由-w-h指定的所需大小,并存储到由-vec命令行选项指定的vec-文件中。

    正样本也可以从先前标记的图像的集合中获得,这是构建健壮对象模型时的理想方式。该集合由与背景描述文件类似的文本文件来描述。该文件的每一行对应于一个图像。行的第一个元素是文件名,其次是对象注释的数量,接着是描述对象包围矩形(x,y,width,height)的坐标的数字。

    描述文件示例:

    目录结构:

    /img
      img1.jpg
      img2.jpg
    info.dat

    文件 info.dat:

    img/img1.jpg  1  140 100 45 45
    img/img2.jpg  2  100 200 50 50   50 30 25 25

    图像img1.jpg包含单个对象实例,其中包含矩形的以下坐标:(140, 100, 45,45)。图像img2.jpg包含两个对象实例。为了从这些集合中创建正样本,应该指定-info参数,而不是-img

    额外备注:

    • opencv_createsamples实用程序可用于检查存储在任何给定的正样本文件中的样本。为了做到这一点,只需指定-vec-w-h参数。
    • 这里的示例可以参考opencv/data/vec_files/trainingfaces_24-24.vec。它可用于训练具有以下窗口大小的面部检测器:-w 24 -h 24

    使用OpenCV的集成注释工具

    自从OpenCV 3.x以来,社区一直在提供和维护一个开源的注释工具,用于生成-info文件。如果OpenCV应用程序在其中构建,则可以通过命令opencv_annotation来访问该工具。

    使用该工具是相当简单的。该工具接受几个需要的和一些可选参数:

    • --annotations (required) : 注释TXT文件的路径,在其中存储注释,然后将其传递给-info参数[example - /data/annotations.txt]
    • --images (required) : 文件夹中包含对象图像的路径 [example - /data/testimages/]
    • --maxWindowHeight (optional) : 如果输入图像的高度较大,那么这里给定的分辨率,为了便于注释,调整图像的大小,使用--resizeFactor
    • --resizeFactor (optional) : 用于在使用--maxWindowHeight参数时调整输入图像大小的因素

    请注意,可选参数只能一起使用。下面可以看到一个可以使用的命令的例子。

    opencv_annotation --annotations=/path/to/annotations/file.txt --images=/path/to/image/folder/

    这个命令将触发包含第一个图像和鼠标光标的窗口,这将用于注释。一个关于如何使用注释工具的视频可以在 这里 找到。基本上有几个触发动作的击键。鼠标左键用于选择对象的第一个角落,然后继续绘制直到你觉得好了,然后在第二个鼠标左键点击注册时停止。每次选择后,您有以下选择:(本人对下面翻译持怀疑态度,其中的“注释”的英文为“annotation”,可能是指应用程序opencv_annotation

    • 按C:确认注释,把注释变成绿色并确保它已经保存
    • 按D:删除注释集中的最后一条注释(方便移除错误注释)
    • 按N:继续下一个图像
    • 按Esc:这将退出注释软件

    最后,您将得到一个可用的注释文件,该文件可以被传递到opencv_createsamples -info参数。

    梯度训练(Cascade Training)

    下一步是基于预先准备好的正、负数据集,对弱分类器的增强级联进行实际训练。

    按目的分组的opencv_traincascade应用程序的命令行参数:

    常见参数:

    • -data <cascade_dir_name> : 训练过的分类器应该存储在哪里。这个文件夹应该手动创建。
    • -vec <vec_file_name> : 具有正样本的vec-文件(由opencv_createsamples utility创建)。
    • -bg <background_file_name> : 背景描述文件。包含负样品图像的文件。
    • -numPos <number_of_positive_samples> : 每个分类器阶段训练中使用的正样本数。
    • -numNeg <number_of_negative_samples> : 每个分类器阶段训练中使用的负样本数。
    • -numStages <number_of_stages> : 要训练的梯度(cascsde stages)的数目。
    • -precalcValBufSize <precalculated_vals_buffer_size_in_Mb> : 预先计算的特征值的缓冲区大小(单位为MB)。您分配的内存越多,培训过程越快,但是请记住,-precalcValBufSize -precalcIdxBufSize组合不应超过可用的系统内存。
    • -precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb> : 预先计算的特征索引的缓冲区大小(在MB中)。您分配的内存越多,培训过程越快,但是请记住,-precalcValBufSize -precalcIdxBufSize组合不应超过可用的系统内存。
    • -baseFormatSave : 这个参数在Haar-like特征的情况下通用。如果它被指定,梯度将以旧格式保存。这仅适用于向后兼容性的原因,并且允许用户坚持旧的已弃用的接口,至少使用新的接口来训练模型。
    • -numThreads <max_number_of_threads> : 训练期间要使用的最大线程数。请注意,实际使用的线程数可能较低,这取决于您的计算机和编译选项。默认情况下,如果使用TBB支持构建OpenCV,则可以选择最大可用线程,这是优化的必要条件。
    • -acceptanceRatioBreakValue <break_value> : 这个参数被用来确定你的模型应该保持精确的学习和何时停止。一个好的准则是训练不要超过10e^-5,以确保模型不会对你的训练数据造成过度训练。默认情况下,此值设置为-1,以禁用此功能。

    梯度参数:

    • -stageType <BOOST(default)> : 阶段的类型。目前仅支持增强型分类器作为阶段类型。
    • -featureType<{HAAR(default), LBP}> : 特征类型:HAAR - Haar-like features, LBP - local binary patterns
    • -w <sampleWidth> : 训练样本的宽度(以像素为单位)。必须与训练样本创建时使用的值完全相同(opencv_createsamples utility
    • -h <sampleHeight> : 训练样本的高度(以像素为单位)。必须与训练样本创建时使用的值完全相同(opencv_createsamples utility

    增强分类器参数:

    • -bt <{DAB, RAB, LB, GAB(default)}> : 增强分类器类型:DAB - Discrete AdaBoost, RAB - Real AdaBoost, LB - LogitBoost, GAB - Gentle AdaBoost。
    • -minHitRate <min_hit_rate> : 分类器的每个阶段的最小期望命中率。总体命中率可估计为 (min_hit_rate ^ number_of_stages)[192] §4.1
    • -maxFalseAlarmRate <max_false_alarm_rate> : 分类器的每个阶段的最大期望虚警率(false alarm rate)。整体虚警率可估计为(max_false_alarm_rate ^ number_of_stages[192] §4.1
    • -weightTrimRate <weight_trim_rate> : 指定是否应该使用修整和它的重量。一个不错的选择是0.95。
    • -maxDepth <max_depth_of_weak_tree> : 弱树(weak tree)的最大深度。一个不错的选择是1,就是树桩(stumps)的例子。
    • -maxWeakCount <max_weak_tree_count> : 每个梯度的弱树的最大计数。增强分类器(阶段)将有许多弱树(<=maxWeakCount),根据需要实现给定的 -maxFalseAlarmRate

    Haar-like特征参数:

    • -mode <BASIC (default) | CORE | ALL> : 选择在训练中使用的Haar特征集的类型。基本使用只有直立功能,而全部使用全套直立和45度旋转特征集。详情请参阅[ 110 ]

    本地二进制格式(Local Binary Patterns)参数:无。

    opencv_traincascade应用程序完成工作后,将被训练的级联保存在-data文件夹中的cascade.xml文件中。此文件夹中的其他文件是针对中断训练的情况创建的,因此您可以在完成训练后删除它们。

    训练完成,你可以测试你的级联分类器!

    可视化级联分类器

    不时地,可视化的训练级联,看看它所选择的特征和它的阶段是多么复杂是有用的。为此OpenCV提供opencv_visualisation应用程序。此应用程序具有以下命令:

    • --image (required) : 对象模型的参考图像路径。这应该是一个注释,标注为[-w,-h],传递给opencv_createsamplesopencv_traincascade 应用程序。
    • --model (required) : 训练模型的路径,它应该在提供给opencv_traincascade应用程序的-data参数的文件夹中。
    • --data (optional) : 如果必须手动创建的data文件夹被提供,则将存储阶段输出和特征的视频。

    下面可以看到一个示例命令

    opencv_visualisation --image=/data/object.png --model=/data/model.xml --data=/data/result/

    当前可视化工具的一些局限性

    • 只处理级联分类器模型,用 opencv_traincascade工具进行训练,包含树桩(stumps)作为决策树[默认设置]。
    • 所提供的图像需要是具有原始模型维度的样本窗口,传递给 --image参数。

    HAAR/LBP人脸模型的例子在安吉莉娜·朱莉的给定窗口上运行,它具有与级联分类器文件相同的预处理-> 24x24像素图像、灰度转换和直方图均衡:

    为每个阶段制作视频,每个特征可视化:


    每个阶段被存储为图像,用于将来对特征的验证:


    这项工作是由StevenPuttemansOpenCV 3 Blueprints创建的,但Packt 出版社(Packt Publishing)同意将其集成到OpenCV中。

    展开全文
  • adaboost训练 之 强分类器训练原理

    千次阅读 2016-09-30 16:14:49
    最近看opencv中adaboost训练分类器源码,记录下自己对adaboost训练分类器的原理理解。adaboost训练分类器的基本流程: 1、初始化训练样本的类别与权重分布。 2、迭代循环训练分类器。 3、将每次循环训练...

    最近看opencv中adaboost训练强分类器源码,记录下自己对adaboost训练强分类器的原理理解。

    adaboost训练强分类器的基本流程:
    1、初始化训练样本的类别与权重分布。
    2、迭代循环训练弱分类器。
    3、将每次循环训练成的弱分类器与已经存在的弱分类器组成的强分类器。
    4、根据当前强分类器计算正样本置信度,根据传入参数minhitrate来取得强分类器阈值。
    5、用当前强分类器与上步计算得到阈值,分类负样本,如果分类的最大检率小于maxfalsealarm。跳出循环,强分类器训练完成。

    下面结合一般的adaboost的算法原理、opencv源码、记录下我对adaboost的算法流程的详细理解:
    给定一个训练数据集 ,其中属于标记样本是正样本还是负样本的标记集合{-1,+1},一般-1表示负样本,+1表示正样本。在人脸分类器的训练中,是计算出来的正样本人脸图片与负样本非人脸图片的某个haar特征的集合。Adaboost的目的就是从训练数据集T中学习一系列弱分类器(特征表述+特征阈值),然后将这些弱分类器组合成一个强分类器(弱分类器+阈值)来尽可能准确的分类xi以达到能够分类一个新的样本是正样本还是负样本。

    在opencv中函数训练强分类器的函数是:icvCreateCARTStageClassifier。这里要特别说明下,在opencv中为训练强分类器提供了四种方法分别是Discrete AdaBoost(DAB)、Real AdaBoost(RAB)、Logit Boost(LB)和Gentle AdaBoost(GAB)算法。我们通常使用的较多的都是GAB训练算法,也是最简单的,这里是几种训练算法的区别介绍::http://www.cnblogs.com/jcchen1987/p/4581651.html

    这里就DAB算法逻辑做一个介绍::::::::::::::::::

    1、首先,初始化训练数据的权值分布。每一个训练样本最开始时都被赋予相同的权值:1/N。
    这里写图片描述

    opencv源码是在函数cvBooWstStartTraining中对训练的样本数据集进行权重的初始化,以及标识每个样本来初始化数据集

    2、进入循环,进行多轮迭代,把每次迭代记做m

    A、通过函数 cvTrimWeights来剔除小权值的样本:对实际存在的样本按权重的大小排序,找到权重高于总权重的weightfraction倍的样本保留下来,用来训练接下来的弱分类器。

    B、使用前面一步保留下来的权值分布为Dm样本集学习训练,得到一个弱分类器,在函数cvCreateCARTClassifier中实现,记公式如下:

    这里写图片描述

    具体如何训练弱分类,见前面几个博客笔记:cvCreateCARTClassifier

    C、用上步训练出来的弱分类器Gm(x)计算每个样本的分类置信度(具体调用的是函数icvEvalCARTHaarClassifier这里源码中用的是函数指针有点难找到,具体可以看下面我贴出的代码中的注释),将计算出来的每个样本的置信度传入cvBoostNextWeakClassifier函数计算该弱分类器Gm(X)在数据集上的分类误差em,这里四种不同的分类器训练方法有不同的计算方式,其中DAB的计算方法如下,在函数icvBoostNextWeakClassifierDAB中实现:
    这里写图片描述

    D、在上述函数icvBoostNextWeakClassifierDAB中紧接着用公式
    这里写图片描述
    计算了当前弱分类器Gm(X)在当前强分类器中的重要程序,这个公式意味着分类误差率越小的弱分类器在强分类器中的权重越高,作用越大。

    E、在函数icvBoostNextWeakClassifierDAB中接着遍历所有样本,更新训练样本的数据集的权值分布得到Dm+1用于下轮迭代来训练弱分类器,公式如下:
    这里写图片描述
    其中:Zm是一个规一化因子:
    这里写图片描述

    通俗的说就是:遍历每个样本更新其权重Wm+1,i=Wm,i*exp(…) , 同时累加每个样本计算得到的权重Wm+1,i得到Zm,然后规一化下。通过公式可以看出当Gm(xi)分类这个样本正确时,则计算得到的Wm+1,i比Wm,i大,反之,Wm+1,i比Wm,i小,这样就实现了将本次分类正确的样本权值减小,本次分类错误的样本权值增大,这样在下次训练弱分类器里更多的聚焦于本次被分错的样本。

    F、从函数icvBoostNextWeakClassifierDAB返回后,得到了当前弱分类器的权重。将该弱分类器以如下公式的方式加入到当前强分类器中:
    这里写图片描述

    G、紧接着,在函数icvCreateCARTStageClassifier中分开处理正负样本,遍历所有正样本,用当前强分类器中已经训练出来的弱分类器来计算每个正样本的置信度,累加得到置信度累加和,将这些每个样本的置信度累加和排序,根据minhitrate来计算当前强分类器的阈值threshold。

    H、再遍历所有负样本,用当前强分类器中已经训练出来的弱分类器来计算每个负样本的置信度累加和,再用前面计算得到的threshold来判断每个负样本的类别,统计负样本的分类总数,得到负样本的误检率falsealarm,如果误检率小于输入的参数maxfalsealarm,则跳出迭代循环,当前强分类器训练完成!!!!

    下面上源码和注释(结合代码与原理更容易理解)::::

    static
    CvIntHaarClassifier* icvCreateCARTStageClassifier( CvHaarTrainingData* data,   // 全部训练样本
                                                       CvMat* sampleIdx,       // 实际训练样本序列
                                                       CvIntHaarFeatures* haarFeatures,// 全部HAAR特征
                                                       float minhitrate,// 最小正检率(用于确定强分类器阈值)
                                                       float maxfalsealarm,// 最大误检率(用于确定是否收敛)
                                                       int   symmetric,// HAAR是否对称 
                                                       float weightfraction,// 样本剔除比例(用于剔除小权值样本)
                                                       int numsplits,// 每个弱分类器特征个数(一般为1) 
                                                       CvBoostType boosttype,// adaboost类型 
                                                       CvStumpError stumperror,// Discrete AdaBoost中的阈值计算方式
                                                       int maxsplits ) // 弱分类器最大个数  
    {
    
    #ifdef CV_COL_ARRANGEMENT
        int flags = CV_COL_SAMPLE;
    #else
        int flags = CV_ROW_SAMPLE;
    #endif
    
        CvStageHaarClassifier* stage = NULL;// 强分类器
        CvBoostTrainer* trainer;// 临时训练器,用于更新样本权值
        CvCARTClassifier* cart = NULL;// 弱分类器
        CvCARTTrainParams trainParams;// 训练参数 
        CvMTStumpTrainParams stumpTrainParams;// 弱分类器参数
        //CvMat* trainData = NULL;
        //CvMat* sortedIdx = NULL;
        CvMat eval;// 临时矩阵
        int n = 0;// 特征总数
        int m = 0;// 总样本个数 
        int numpos = 0;// 正样本个数
        int numneg = 0; // 负样本个数
        int numfalse = 0; // 误检样本个数
        float sum_stage = 0.0F;// 置信度累积和
        float threshold = 0.0F;// 强分类器阈值
        float falsealarm = 0.0F; // 误检率
    
        //CvMat* sampleIdx = NULL;
        CvMat* trimmedIdx; // 剔除小权值之后的样本序列
        //float* idxdata = NULL;
        //float* tempweights = NULL;
        //int    idxcount = 0;
        CvUserdata userdata;// 训练数据
    
        int i = 0;
        int j = 0;
        int idx;
        int numsamples;// 实际样本个数
        int numtrimmed;// 剔除小权值之后的样本个数
    
        CvCARTHaarClassifier* classifier;
        CvSeq* seq = NULL;
        CvMemStorage* storage = NULL;
        CvMat* weakTrainVals;
        float alpha;
        float sumalpha;
        int num_splits; /* total number of splits in all weak classifiers */
    
    #ifdef CV_VERBOSE
        printf( "+----+----+-+---------+---------+---------+---------+\n" );
        printf( "|  N |%%SMP|F|  ST.THR |    HR   |    FA   | EXP. ERR|\n" );
        printf( "+----+----+-+---------+---------+---------+---------+\n" );
    #endif /* CV_VERBOSE */
    
        n = haarFeatures->count;
        m = data->sum.rows;
        numsamples = (sampleIdx) ? MAX( sampleIdx->rows, sampleIdx->cols ) : m;
    
        //样本与HAAR特征  
        userdata = cvUserdata( data, haarFeatures );
    
        /* 弱分类参数设置 */  
        stumpTrainParams.type = ( boosttype == CV_DABCLASS )
            ? CV_CLASSIFICATION_CLASS : CV_REGRESSION;  // 分类或者回归
        stumpTrainParams.error = ( boosttype == CV_LBCLASS || boosttype == CV_GABCLASS )
            ? CV_SQUARE : stumperror;// 弱分类器阈值计算方式 
        stumpTrainParams.portion = CV_STUMP_TRAIN_PORTION;// 每组特征个数  
        stumpTrainParams.getTrainData = icvGetTrainingDataCallback;// 计算样本的haar值,函数指针
        stumpTrainParams.numcomp = n; // 特征个数
        stumpTrainParams.userdata = &userdata;
        stumpTrainParams.sortedIdx = data->idxcache;// 特征-样本序号矩阵(排序之后)  
    
        // 由于参数众多,所以创建参数结构体 
        trainParams.count = numsplits;// 弱分类器特征树
        trainParams.stumpTrainParams = (CvClassifierTrainParams*) &stumpTrainParams;// 弱分类参数
        trainParams.stumpConstructor = cvCreateMTStumpClassifier;// 筛选最优弱分类器,函数指针
        trainParams.splitIdx = icvSplitIndicesCallback; // CART节点分裂函数
        trainParams.userdata = &userdata;
    
        //临时向量,用于存放样本haar特征值  
        eval = cvMat( 1, m, CV_32FC1, cvAlloc( sizeof( float ) * m ) );
    
        storage = cvCreateMemStorage();
        //最优弱分类器存储序列  
        seq = cvCreateSeq( 0, sizeof( *seq ), sizeof( classifier ), storage );
      
        // 样本类别,只有logitboost才会用到  
        weakTrainVals = cvCreateMat( 1, m, CV_32FC1 );
        // 初始化样本类别与权重,weakTrainVals为{-1, 1},权重都一样,LB的权重初值与其他不一样
        trainer = cvBoostStartTraining( &data->cls, weakTrainVals, &data->weights,
                                        sampleIdx, boosttype );
        num_splits = 0;
        sumalpha = 0.0F;
        do   /*这里每次循环创建一个弱分类器,一个弱分类器可以凶括几个特征,但是一般只有一个特征*/
        {     
    
            #ifdef CV_VERBOSE
            int v_wt = 0;
            int v_flipped = 0;
            #endif /* CV_VERBOSE */
    
            //剔除小权值样本 
            trimmedIdx = cvTrimWeights( &data->weights, sampleIdx, weightfraction );
            numtrimmed = (trimmedIdx) ? MAX( trimmedIdx->rows, trimmedIdx->cols ) : m; // 实际样本总数 
    
            #ifdef CV_VERBOSE
            v_wt = 100 * numtrimmed / numsamples;
            v_flipped = 0;
            #endif /* CV_VERBOSE */
    
            //重要函数,创建CART树的同时,当前最优弱分类器出炉,一般只有根节点~因为一般一个弱分类器只有一个特征由numsplits决定
            cart = (CvCARTClassifier*) cvCreateCARTClassifier( data->valcache,
                                                               flags,
                                                               weakTrainVals, 
                                                               0, 
                                                               0, 
                                                               0, 
                                                               trimmedIdx,
                                                               &(data->weights),
                                                               (CvClassifierTrainParams*) &trainParams );
    
            //创建弱分类器,按分类器的结构体分配一个内存   这个函数指定了eval/save/release三个变量调用的实际函数
            classifier = (CvCARTHaarClassifier*) icvCreateCARTHaarClassifier( numsplits );
            // 将CART树转化为弱分类器  
            icvInitCARTHaarClassifier( classifier, cart, haarFeatures );
    
            num_splits += classifier->count;
    
            /*这里又把释放了*/
            cart->release( (CvClassifier**) &cart );
    
            /*必需要在对称的前提下*/
            if( symmetric && (seq->total % 2) )
            {
                float normfactor = 0.0F;
                CvStumpClassifier* stump;
    
                /* flip haar features */
                for( i = 0; i < classifier->count; i++ )
                {
                    if( classifier->feature[i].desc[0] == 'h' )
                    {
                        for( j = 0; j < CV_HAAR_FEATURE_MAX &&
                                        classifier->feature[i].rect[j].weight != 0.0F; j++ )
                        {
                            classifier->feature[i].rect[j].r.x = data->winsize.width - 
                                classifier->feature[i].rect[j].r.x -
                                classifier->feature[i].rect[j].r.width;                
                        }
                    }
                    else
                    {
                        int tmp = 0;
    
                        /* (x,y) -> (24-x,y) */
                        /* w -> h; h -> w    */
                        for( j = 0; j < CV_HAAR_FEATURE_MAX &&
                                        classifier->feature[i].rect[j].weight != 0.0F; j++ )
                        {
                            classifier->feature[i].rect[j].r.x = data->winsize.width - 
                                classifier->feature[i].rect[j].r.x;
                            CV_SWAP( classifier->feature[i].rect[j].r.width,
                                     classifier->feature[i].rect[j].r.height, tmp );
                        }
                    }
                }
                icvConvertToFastHaarFeature( classifier->feature,
                                             classifier->fastfeature,
                                             classifier->count, data->winsize.width + 1 );
    
                stumpTrainParams.getTrainData = NULL;
                stumpTrainParams.numcomp = 1;
                stumpTrainParams.userdata = NULL;
                stumpTrainParams.sortedIdx = NULL;
    
                for( i = 0; i < classifier->count; i++ )   /*按特征模版循环*/
                {
                    for( j = 0; j < numtrimmed; j++ )  /*计算每个样本在这个特征模版下的具体特征值*/
                    {
                        idx = icvGetIdxAt( trimmedIdx, j );
    
                        eval.data.fl[idx] = cvEvalFastHaarFeature( &classifier->fastfeature[i],
                            (sum_type*) (data->sum.data.ptr + idx * data->sum.step),
                            (sum_type*) (data->tilted.data.ptr + idx * data->tilted.step) );
                        normfactor = data->normfactor.data.fl[idx];  /*缩放因子*/
                        eval.data.fl[idx] = ( normfactor == 0.0F )
                            ? 0.0F : (eval.data.fl[idx] / normfactor);
                    }
                                                             /*cvCreateMTStumpClassifier*/
                    stump = (CvStumpClassifier*) trainParams.stumpConstructor( &eval,
                        CV_COL_SAMPLE,
                        weakTrainVals, 0, 0, 0, trimmedIdx,
                        &(data->weights),
                        trainParams.stumpTrainParams );
    
                    classifier->threshold[i] = stump->threshold;
                    if( classifier->left[i] <= 0 )
                    {
                        classifier->val[-classifier->left[i]] = stump->left;
                    }
                    if( classifier->right[i] <= 0 )
                    {
                        classifier->val[-classifier->right[i]] = stump->right;
                    }
    
                    stump->release( (CvClassifier**) &stump );        
    
                }
    
                stumpTrainParams.getTrainData = icvGetTrainingDataCallback;
                stumpTrainParams.numcomp = n;
                stumpTrainParams.userdata = &userdata;
                stumpTrainParams.sortedIdx = data->idxcache;
    
                #ifdef CV_VERBOSE
                v_flipped = 1;
                #endif /* CV_VERBOSE */
    
            } /* if symmetric */
    
            if( trimmedIdx != sampleIdx )
            {
                cvReleaseMat( &trimmedIdx );
                trimmedIdx = NULL;
            }
    
            //调用icvEvalCARTHaarClassifier函数,计算每个样本的当前最优弱分类器置信度
            for( i = 0; i < numsamples; i++ )
            {
                idx = icvGetIdxAt( sampleIdx, i );
    
                eval.data.fl[idx] = classifier->eval( (CvIntHaarClassifier*) classifier,  /*这是本级强分类器的弱分类器列表,每次新得到一个弱分类器都加进来 */
                    (sum_type*) (data->sum.data.ptr + idx * data->sum.step),
                    (sum_type*) (data->tilted.data.ptr + idx * data->tilted.step),
                    data->normfactor.data.fl[idx] );
            }
    
            //更新样本权重,如果是LogitBoost,也会更新weakTrainVals,函数返回的是弱分类器权重 
            /*这里四种不同的adaboost提升方法*/
            alpha = cvBoostNextWeakClassifier( &eval, &data->cls, weakTrainVals,
                                               &data->weights, trainer );
            //这个变量没什么用 
            sumalpha += alpha;
    
            for( i = 0; i <= classifier->count; i++ )
            {
                if( boosttype == CV_RABCLASS )   /*RAB额外再log一次*/
                {
                    classifier->val[i] = cvLogRatio( classifier->val[i] );
                }
                classifier->val[i] *= alpha;   /*更新分类器权重DAB是依照常见公式,GAB始终是1也就是每个弱分类器的权重相同*/
            }
    
            //添加弱分类器,classifier是弱分类器
            cvSeqPush( seq, (void*) &classifier );
    
            //遍历sampleIdx中所有样本,计算每个样本的弱分类器置信度和  
            numpos = 0;
            for( i = 0; i < numsamples; i++ )
            {
                // 获得样本序号
                idx = icvGetIdxAt( sampleIdx, i );
    
                // 如果样本为正样本
                if( data->cls.data.fl[idx] == 1.0F )
                {
                    //初始化置信度值 
                    eval.data.fl[numpos] = 0.0F;
    
                    // 遍历seq中所有弱分类器
                    for( j = 0; j < seq->total; j++ )
                    {
                        // 获取弱分类器  
                        classifier = *((CvCARTHaarClassifier**) cvGetSeqElem( seq, j ));
    
                        // 累积当前正样本的弱分类器置信度和  
                        //eval == CV_INT_HAAR_CLASSIFIER_FIELDS==icvEvalCARTHaarClassifier
                        eval.data.fl[numpos] += classifier->eval((CvIntHaarClassifier*) classifier,
                                                                 (sum_type*) (data->sum.data.ptr + idx * data->sum.step),
                                                                 (sum_type*) (data->tilted.data.ptr + idx * data->tilted.step),
                                                                 data->normfactor.data.fl[idx] );
                    }
                    /* eval.data.fl[numpos] = 2.0F * eval.data.fl[numpos] - seq->total; */
                    numpos++;
                }
            }
    
            // 对弱分类器输出置信度和进行排序  
            icvSort_32f( eval.data.fl, numpos, 0 );
    
            // 计算阈值,应该是大于threshold则为正类,小于threshold则为负类 
            threshold = eval.data.fl[(int) ((1.0F - minhitrate) * numpos)];
    
            // 遍历所有样本,统计错分负样本个数  
            numneg = 0;
            numfalse = 0;
            for( i = 0; i < numsamples; i++ )
            {
                idx = icvGetIdxAt( sampleIdx, i );
    
                // 如果样本为负样本  
                if( data->cls.data.fl[idx] == 0.0F )
                {
                     // 遍历seq中所有弱分类器
                    numneg++;
                    sum_stage = 0.0F;
                    for( j = 0; j < seq->total; j++ )
                    {
                       classifier = *((CvCARTHaarClassifier**) cvGetSeqElem( seq, j ));
    
                       // 累积当前负样本的分类器输出结果  
                       sum_stage += classifier->eval( (CvIntHaarClassifier*) classifier,
                            (sum_type*) (data->sum.data.ptr + idx * data->sum.step),
                            (sum_type*) (data->tilted.data.ptr + idx * data->tilted.step),
                            data->normfactor.data.fl[idx] );
                    }
    
                    // 因为小于threshold为负类,所以下面是分类错误的情况  
                    /* sum_stage = 2.0F * sum_stage - seq->total; */
                    if( sum_stage >= (threshold - CV_THRESHOLD_EPS) )
                    {
                        numfalse++;
                    }
                }
            }
            // 因为小于threshold为负类,所以下面是分类错误的情况  
            falsealarm = ((float) numfalse) / ((float) numneg);
    
            #ifdef CV_VERBOSE
            {
                // 正样本检出率  
                float v_hitrate    = 0.0F;
                // 负样本误检率
                float v_falsealarm = 0.0F;
    
                /* expected error of stage classifier regardless threshold */
                float v_experr = 0.0F;
    
                // 遍历所有样本  
                for( i = 0; i < numsamples; i++ )
                {
                    idx = icvGetIdxAt( sampleIdx, i );
    
                    sum_stage = 0.0F;
    
                    // 遍历seq中所有弱分类器  
                    for( j = 0; j < seq->total; j++ )
                    {
                        classifier = *((CvCARTHaarClassifier**) cvGetSeqElem( seq, j ));
                        sum_stage += classifier->eval( (CvIntHaarClassifier*) classifier,
                            (sum_type*) (data->sum.data.ptr + idx * data->sum.step),
                            (sum_type*) (data->tilted.data.ptr + idx * data->tilted.step),
                            data->normfactor.data.fl[idx] );
                    }
    
                    /* sum_stage = 2.0F * sum_stage - seq->total; */
                    // 只需要判断单一分支即可 
                    if( sum_stage >= (threshold - CV_THRESHOLD_EPS) )
                    {
                        if( data->cls.data.fl[idx] == 1.0F )
                        {
                            v_hitrate += 1.0F;
                        }
                        else
                        {
                            v_falsealarm += 1.0F;
                        }
                    }
    
                     // 正类样本的sum_stage必须大于0
                    if( ( sum_stage >= 0.0F ) != (data->cls.data.fl[idx] == 1.0F) )
                    {
                        v_experr += 1.0F;
                    }
                }
                v_experr /= numsamples;
                printf( "|%4d|%3d%%|%c|%9f|%9f|%9f|%9f|\n",
                    seq->total, v_wt, ( (v_flipped) ? '+' : '-' ),
                    threshold, v_hitrate / numpos, v_falsealarm / numneg,
                    v_experr );
                printf( "+----+----+-+---------+---------+---------+---------+\n" );
                fflush( stdout );
            }
            #endif /* CV_VERBOSE */
    
        } while( falsealarm > maxfalsealarm && (!maxsplits || (num_splits < maxsplits) ) );
    
        cvBoostEndTraining( &trainer );
    
        if( falsealarm > maxfalsealarm )
        {
            stage = NULL;
        }
        else
        {
            /*这里创建输出的强分类器*/
            stage = (CvStageHaarClassifier*) icvCreateStageHaarClassifier( seq->total, threshold );
    
            cvCvtSeqToArray( seq, (CvArr*) stage->classifier );
        }
    
        /* CLEANUP */
        cvReleaseMemStorage( &storage );
        cvReleaseMat( &weakTrainVals );
        cvFree( &(eval.data.ptr) );
    
        return (CvIntHaarClassifier*) stage;
    }

    感谢:::http://www.cnblogs.com/harvey888/p/5505511.html

    展开全文
  • opencv分类器训练方法

    万次阅读 2018-06-04 16:16:28
    分类器工具集下载人头识别 分类器训练数据集二、文件夹环境下面8个工具在这里(分类器工具集下载)posdata中存放正样本 negdata 存放负样本下载地址:(人头识别 分类器训练数据集)三、开始训练:dos命令下进入 这...

    训练前先扫读一下这篇文章;(级联分类器训练)

    python+opencv实现人头检测

    一、工具,样本数据准备;

    分类器工具集下载

    人头识别 分类器训练数据集

    二、文件夹环境


    下面8个工具在这里(分类器工具集下载

    posdata中存放正样本 negdata 存放负样本下载地址:(人头识别 分类器训练数据集

    三、开始训练:

    dos命令下进入 这个目录;执行dir /b >posdata.dat生成posdata.dat文件

    dos命令下进入 这个目录;执行dir /b >negdata.dat生成negdata.dat文件




    这样正负样本的数据文件都在其各自目录下生成了,接下来进行修改数据文件。打开数据文件的编辑界面,删掉数据文件最后面的posdata.dat,同理删除负样本数据文件里面的negdata.dat。如图: 
    这里写图片描述

    接下里修改数据文件成我这样,posdata.dat: 
    这里写图片描述

    negdata.dat: 
    这里写图片描述

    解释下 1 0 0 20 20这个参数的意思,1代表文件,0 0 20 20,是这个目录下每一张图片的坐标,因为是二维的,而且我正样本所有图片全是20*20像素的,所以就是(0,0)点到(20,20)点,即是读取图片时,从左下角扫描到右上角。 
    注意:在负样本的数据文件里面,要给每一个图片文件加上他的相对地址,因为默认我们训练时,是在negdata的父目录下进行,即是你创建的训练文件夹下进行。

    3.准备工作已经完成,下面开始训练具体操作,首先用opecv_createsamples.exe生成样本描述文件pos.vec。命令如下:

    opencv_createsamples.exe -info posdata\posdata.dat -vec data\pos.vec -num 3900 -w 20 -h 20
    
    • 1
    • 2

    生成了正样本描述文件后,接下来就是用opencv_traincascade.exe进行分类器的生成。命令如下:

    opencv_traincascade.exe -data data1 -vec data\pos.vec -bg negdata -numPos 3900 -numNeg 23000 -minHitRate 0.9999 -maxFalseAlarmRate 0.5 -featureType HAAR -numStages 20 -w 20 -h 20
    
    • 1
    • 2
    • 3

    各个参数的意思我这里就不赘述了,给一篇大牛写的文章,大家自行参考。http://note.sonots.com/SciSoftware/haartraining.html#e134e74e

    接着,等着他训练完成就行。这是个漫长的过程!




    展开全文
  • OpenCV 级联分类器训练——训练步骤详解(一)

    万次阅读 多人点赞 2018-03-09 15:56:21
    一、正样本准备正样本的选取原则正样本的尺寸不是必须一致的,但是要和生成的正样本矢量文件中的宽高有相同的比例(训练过程中,会根据矢量文件中设置的宽高,自动对正样本进行缩放,比如我在用程序标注时,框选目标...

    参考文章:http://blog.csdn.net/xiao_lxl/article/details/44645969
    根据本人实践过程和理解写了下文。

    一、正样本准备

    正样本的选取原则

    1. 正样本的尺寸不是必须一致的,但是要和生成的正样本矢量文件中的宽高有相同的比例(训练过程中,会根据矢量文件中设置的宽高,自动对正样本进行缩放,比如我在用程序标注时,框选目标尺寸为30X30,但生产vec文件时填的尺寸为64X64,训练时会自动将框选图像做等比例缩放);

    2. 正样本图片应该尽可能包含少的干扰背景信息。在训练过程中这些背景信息也会成为正样本的一个局部特征,使得特征值的计算包含干扰信息。

    3. 数据来源尽可能做到多样化,比如样本为车,车的姿态场景应稍丰富些。同一正样本目标的图像太多会使局部特征过于明显,造成这个目标的训练过拟合,影响检测精度,不利于训练器泛化使用。

    1、采集正样本图片

    正样本最后需要大小归一化,采集样本时可直接把它从原图里抠出来以便缩放;但是我是保留了原图,且在一张图上对多个目标做位置标注了,即保存了它的框个数和框位置信息;我在裁剪时将裁剪框做了比例约束,使得裁剪出来的框和最后需要归一化尺寸等比例。比如要归一化成64 X 64,在裁剪样本的时候,我按长宽等比例裁剪(如32X32,48X48);也可以是非1:1的长宽比,具体看你目标对象的尺寸比例而定。

    2、获取正样本路径列表

    在你的图片文件夹里,编写一个.bat文件或者是一个.cmd文件(get route.bat,bat是避免每次都需要去dos框输入),如下所示:
    内容也可更改为: dir pos /b > pos.txt          其中pos是文件夹名字,将pos文件夹中的所有文件名保存到pos.txt文件中;
    这里写图片描述

    运行bat文件,就会生成如下dat文件:

    这里写图片描述

    把这个dat文件中的所有非图片的路径都删掉,比如上图的头两行,由于我不是裁剪的,所以txt中的目标位置我都是通过一个objectMaker小程序生产的框和尺寸坐标位置:

    (pos.txt文件内容中:图像格式后面的数字代表个数(可不只是1),后四个分别对应框的 left top width height,我不是把样本裁剪下来的,那txt中是xxx. jpg 3 1 3 24 24 26 28 25 25 60 80 26 26,xxx. jpg是原图,3为该图上的框数量,后面的数是每个框的信息)

    3、获取正样本矢量集vec文件

    利用opencv里的一个程序叫opencv_createsamples.exe,把它拷贝出来,放在当前目录下。针对它的命令输入也是写成bat文件,因为cascade训练的时候用的是vec。如下:可通过加-show显示某个正样本图像。可以根据自己需求更改num数,-w和-h

    这里写图片描述

    运行bat,就在我们得pos文件夹里生成了如下vec文件:

    这里写图片描述

    就此正样本东西准备结束。

    注意:
    样本矢量库的宽和高设置太大会使样本在训练过程中占用内存较大,可能出现内存分配失败的错误,根据实际情况适当更改。. 

    创建vec命令行参数:

    • -vec 输出文件,内含有用于训练的正样本

    • -img 输入图片文件名

    • -bg 背景描述文件,文件中包含一系列的图像文件名,这些图像将被随机选作物体的背景

    • -num 生成正样本的数目

    • bgcolor 背景颜色(目前为灰度图),背景颜色表示透明颜色。因为图像压缩可造成颜色偏差,颜色的容差可以由 -bgthresh 指定。所有处于 bgcolor-bgthresh 和bgcolor+bgthresh 之间的像素都被设置为透明像素。

    • -bgthresh

    • -inv 如果指定该标志,前景图像的颜色将翻转。

    • -randinv 如果指定该标志,颜色将随机地翻转。

    • -maxidev 前景样本里像素的亮度梯度的最大值。

    • -maxxangle X轴最大旋转角度,必须以弧度为单位。

    • -maxyangle Y轴最大旋转角度,必须以弧度为单位。

    • -maxzangle Z轴最大旋转角度,必须以弧度为单位。

    • -show 很有用的调试选项。如果指定该选项,每个样本都将被显示。如果按下 Esc 键,程序将继续创建样本但不再显示。

    • -w 输出样本的宽度(以像素为单位)。

    • -h 输出样本的高度(以像素为单位)。

    创建样本的流程如下:

    输入图像沿着三个轴随机旋转。
    旋转的角度由 -max?angle 限定。然后像素的亮度值位于 [bg_color-bg_color_threshold;bg_color+bg_color_threshold]范围的像素被设置为透明像素。将白噪声加到前景图像上。
    如果指定了-inv ,那么前景图像的颜色将被翻转。如果指定了-randinv ,程序将随机选择是否将颜色进行翻转。
    任选背景图像,将获得的前景图像放到背景图像上,并将图像调整到-w 和-h 指定的大小。最后将图像存入vec文件,vec文件名由命令行参数-vec 指定。
    正样本也可从一系列事先标记好的图像中创建。标记信息可以存储于一个文本文件,与背景描述文件类似。文件中的每行对应一个图像文件。每行的第一个元素为图像文件名,后面是物体的数目,最后是物体位置和大小的描述 (x, y, width, height)。

    二、关于负样本的准备

    负样本的选取原则:

    1. 在负样本图片中不能包含正样本目标;

    2. 每个负样本之间是各不相同的,即确保负样本的多样性;

    3. 每个负样本的尺寸不是必须相同的,但负样本的尺寸不能小于正样本矢量集图像的宽和高,本文设置的尺寸都大于等于64*64;

    这个特别简单,直接拿原始图,不需要裁剪抠图,也不需要保存框,只要保证比正样本尺寸大就可以了,只要把路径保存下来。同正样本类似,同理也可以是.cmd文件,内容如:dir neg /b > neg.txt     其中neg为负样本所在的图像文件夹名。neg.txt中内容不含框和位置信息。图如下:

    这里写图片描述

    至此有关负样本的也准备完成。

    这里写图片描述

    进行训练的话,创建一个classify20.bat
    我写的.bat内容为:
    @echo off
    opencv_traincascade.exe -data data -vec pos.vec -bg neg\neg.txt -numPos 20000 -numNeg 50000 -numStages 16 -featureType HOG -w 64 -h 64
    pause
    会在data文件夹中生产一个xml文件,即分类器。

    这里写图片描述

    双击运行即可开始训练。

    注意:numPos *2 < numNeg < numPos*4

    需要的文件都在这里列出:

    这里写图片描述
    这里写图片描述

    展开全文
  • Opencv人脸分类器训练以及人脸识别全过程项目,windows+OpenCV(配使用文档),vs2010项目工程。
  • 1.概述在opencv中有两个类型的分类器:opencv_haartraining和opencv_traincascade,后者是2.x版本中基于C++写的新版本的分类器。二者最主要的区别是opencv_traincascade支持Haar和LBP。LBP在训练和检测方面要比Haar...
  • opencv人头分类器训练样本数据集

    热门讨论 2014-12-16 12:04:53
    opencv人头分类器训练样本数据集 正负样本都要,正样本4000+ 负样本25000+ 归一化为20*20
  • Opencv目标检测之级联分类器训练与测试

    万次阅读 多人点赞 2017-01-02 20:32:10
    OpenCV提供了两个程序可以训练自己的级opencv_haartraining 与opencv_traincascade。opencv_traincascade是一个新程序,使用OpenCV 2.x API 以C++ 编写。这二者主要的区别是opencv_traincascade支持 Haar和 LBP...
  • 朴素贝叶斯分类器训练过程分析

    千次阅读 2018-05-25 12:30:51
    转载来源,系列阅读:http://pocore.com/blog/article_495.html原文链接这是一个识别论坛不当言论的案例步骤一:获得这个问题的全部特征(标称型)所谓标称型数据:是可以化成0 1表示的数据用于案例训练的数据如下:...
  • 级联分类器训练及其参数的含义

    千次阅读 2015-10-30 17:51:18
    转载自:级联分类器训练 — OpenCV 2.3.2 documentation http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html 介绍 级联分类器包括两部分:训练和检测。 检测部分在OpenCV...
  • 此文章假定读者已经了解前面5章的内容,包括Haar特征,弱分类器和强分类器结构,以及GAB等内容。 缩进在opencv_traincascade.exe程序中,有如下参数 缩进如上输入的boostParams中的6个参数决用于决定训练过程...
  • [知乎作答]·关于在Keras中多标签分类器训练准确率问题 本文来自知乎问题关于在CNN中文本预测sigmoid分类器训练准确率的问题?中笔者的作答,来作为Keras中多标签分类器的使用解析教程。 一、问题描述 关于在...
  • 关于原理,其他博客有的已经介绍的很详细了,这里主要把我进行训练时的步骤列出来,有的是根据别人的博客参考的,但进行过程中还是会出错,现在把我真正使用的步骤列出来,以供参考一、关于正样本的准备正样本的选取...
  • 上一篇(OpenCV3中的级联分类器目标检测——cv::CascadeClassifier简介)介绍了如何使用级联分类器进行目标检测。这里,我们介绍一下如何训练自己的级联分类器
  • 【opencv】4.使用opencv进行分类器训练

    万次阅读 2017-06-28 13:34:44
    要进行目标跟踪,首先得把目标识别出来,我选用的是基于haar特征的模式识别,要进行模式识别,首先得训练分类器,好在opencv自带了训练分类器的软件,可以在opencv安装目录中找到,如: F:\opencv\build\x86\vc12\...
  • hog+svm行人检测分类器训练

    千次下载 热门讨论 2014-11-24 17:32:52
    行人检测分类器训练训练完可测试效果如何,注意样本的路径问题
  • 紧接上一篇文章 opencv 级联分类器训练步骤和方法 级联分类器训练中命令行和训练过程中参数注释:
  • 基于OpenCV新版本3.1.0详细讲述了HAAR与LBP级联分类器的基本原理与使用技巧,通过视频中人脸实时检测与眼睛跟踪例子...通过OpenCV自带的训练工具实现样本数据训练生成自己的级联分类器文件,使用它实现自定义对象检测。
  • 基于opencv分类器训练完整模式

    热门讨论 2010-04-12 20:59:58
    介绍haar分类器训练模式,包括训练分类器要用的exe文件,以及具体训练步骤,适合初学者,15分钟学会训练。另外含有已训练的分类器样板。
  • 级联分类器训练(OpenCV教程)

    万次阅读 2012-03-28 19:37:05
    级联分类器训练   介绍 使用级联分类器工作包括两个阶段:训练和检测。 检测部分在OpenCVobjdetect 模块的文档中有介绍,在那个文档中给出了一些级联分类器的基本介绍。当前的指南描述了如何训练分类器:准备...
  • adaboost训练 之 弱分类器训练原理

    万次阅读 2016-09-27 15:57:53
    他们称之为"分类和回归树(CART)".OpenCV实现的就是"分类回归树".简单地说,二叉决策树的每个结点表示对对象做判断的一个特征属性,将对象提供的属性值与该结点提供的属性值做对比,例如,判断一辆车是否是小汽车我们...
  • OpenCV+Python训练分类器

    千次阅读 2019-11-24 13:07:49
    @[TOC]opencv训练自己的分类器 opencv训练自己的分类器 总结一下在学习训练自己的分类器所看到的有帮助的资料。 正负样本的处理 正样本:负样本=1:3,正样本尺寸:负样本尺寸=1:6的最终效果比较好,若是场景比较...
  • opencv级联分类器训练

    千次阅读 2013-02-05 17:17:38
    转自:...OpenCV中有两个程序可以训练级联分类器: opencv_haartraining 和 opencv_traincascade。opencv_t
  •   识别可以自己写模板匹配、特征点识别、级联分类器训练识别。   本文章就是讲解级联分类器的训练与识别。 级联分类器相关   OpenCV的级联分类器分有两个,分别为Harr级联分类器和LBP级联分类器。具体级联...
  • 如何用OpenCV训练自己的分类器

    千次阅读 2019-02-20 14:22:18
    如何用OpenCV训练自己的分类器
  • 级联分类器包括两部分:训练和检测。 这个指南是描述如何训练分类器:准备训练数据和运行训练程序。 [官网]:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html 重点注意事项 ...
  • OpenFace人脸分类器训练

    千次阅读 2017-08-10 18:36:04
    本篇文章关于OpenFace人脸分类器训练,默认已经安装好了OpenFace和其他的依赖关系,如何配置可见上一篇文章。 参考文章 如有雷同,绝非巧合 1.准备素材 人脸原图,每个图包含一个人脸,每个人脸n张图(>15)。...
  • 基于darknet框架分类器训练

    万次阅读 2017-07-27 08:57:12
    由于实际的业务数据的要求,需要得到与之匹配的预训练模型,本文将使用YOLO的网络进行预训练,得到适合自己的分类器。这篇文章主要介绍如何利用Darknet框架训练分类器。 安装Darknet 若没有安装Darknet,需首先...
  • 计算机视觉—人脸识别(Hog特征+SVM分类器) 一、SVM支持向量机 1、SVM原理 在机器学习,支持向量机的监督学习模型与相关的学习算法可以分析用于数据分类和回归分析。给定一组训练样例,每个训练样例被标记为属于两...
  • opencv分类器训练步骤总结

    千次阅读 2010-05-02 00:14:00
    自己训练了一个识别五角星的分类器,不过只用了50个正样本,2000个负样本(不含正样本的背景图),所以用起来误判率很高, 把训练步骤弄清楚,只要背景和正样本选取得足够多,足够好,就可以较准确的识别物体. 现在把步骤...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 202,081
精华内容 80,832
关键字:

分类器训练