精华内容
下载资源
问答
  • opencv自带的训练器

    千次阅读 2017-03-19 17:00:36
    一、基础知识准备 首先,opencv目前仅支持三种特征的训练检测, HAAR、LBP、...opencv的这个训练算法是基于adaboost而来的,所以需要先对adaboost进行基础知识补充啊,网上一大堆资料,同志们速度去查阅。我的资

    装载:http://blog.csdn.net/wuxiaoyao12/article/details/39227189


    一、基础知识准备

    首先,opencv目前仅支持三种特征的训练检测, HAAR、LBP、HOG,选择哪个特征就去补充哪个吧。opencv的这个训练算法是基于adaboost而来的,所以需要先对adaboost进行基础知识补充啊,网上一大堆资料,同志们速度去查阅。我的资源里也有,大家去下载吧,这些我想都不是大家能直接拿来用的,我下面将直接手把手告诉大家训练怎么操作,以及要注意哪些细节。


    二、关于正样本的准备

    1、采集正样本图片

    因为正样本最后需要大小归一化,所以我在采集样本的时候就直接把它从原图里抠出来了,方便后面缩放嘛,而不是只保存它的框个数和框位置信息(框个数、框位置信息看下一步解释),在裁剪的过程中尽量保持样本的长宽比例一致。比如我最后要归一化成20 X 20,在裁剪样本的时候,我都是20X20或者21X21、22X22等等,最大我也没有超过30X30(不超过跟我的自身用途有关,对于人脸检测这种要保证缩放不变性的样本,肯定就可以超过啦),我资源里也给出可以直接用的裁剪样本程序。

    (这里我说错了,根据createsamples.cpp ,我们不需要提前进行缩放操作,它在第3步变成vec时就包含了缩放工作.如果我们是用objectMaker标记样本,程序同时生成的关于每一幅图的samplesInfo信息,直接给第三步用即可。当然,你提前缩放了也没关系,按照第2步操作即可)

    2、获取正样本路径列表

    在你的图片文件夹里,编写一个bat程序(get route.bat,bat是避免每次都需要去dos框输入,那里又不能复制又不能粘贴!),如下所示:








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


    把这个dat文件中的所有非图片的路径都删掉,比如上图的头两行,再将bmp 替换成 bmp 1 0 0 20 20,如下:


    (1代表个数,后四个分别对应 left top width height,如果我们之前不是把样本裁剪下来的,那么你的这个dat可能就长成这样1. bmp 3 1 3 24 24 26 28 25 25 60 80 26 26,1.bmp是完全的原图啊,你之前的样本就是从这张图上扣下来的)

    3、获取供训练的vec文件

    这里,我们得利用opencv里的一个程序叫opencv_createsamples.exe,可以把它拷贝出来。针对它的命令输入也是写成bat文件啦,因为cascade训练的时候用的是vec。如下:


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

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

    (vec中其实就是保存的每一个sample图,并且已经统一w、h大小了,如果你想看所有的sample,也可以通过调用opencv_createsamples.exe,使用操作,见附)


    三、关于负样本的准备

    这个特别简单,直接拿原始图,不需要裁剪抠图(不裁剪还能保证样本的多样性),也不需要保存框(网上说只要保证比正样本大小大哈,大家就保证吧),只要把路径保存下来。同正样本类似,步骤图如下:



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


    四、开始训练吧

    这里我们用opencv_traincascade.exe(opencv_haartraining.exe的用法跟这个很相似,具体需要输入哪些参数去看opencv的源码吧,网上资料也有很多,主要是opencv_traincascade.exe比opencv_haartraining.exe包含更多的特征,功能齐全些啊),直接上图:


    命令输入也直接用bat文件,请务必保证好大小写一致,不然不予识别参数。小白兔,跑起来~~~


    这是程序识别到的参数,没有错把,如果你哪个字母打错了,你就会发现这些参数会跟你预设的不一样啊,所以大家一定要看清楚了~~~~

    跑啊跑啊跑啊跑,如下:


    这一级的强训练器达到你预设的比例以后就跑去训练下一级了,同志们那个HR比例不要设置太高,不然会需要好多样本,然后stagenum不要设置太小啊,不然到时候拿去检测速度会很慢。

    等这个bat跑结束,我的xml文件也生成了。如下:


    其实这个训练可以中途停止的,因为下次开启时它会读取这些xml文件,接着进行上次未完成的训练。哈哈~~~~好人性化啊!

    训练结束,我要到了我的cascade.xml文件,现在我要拿它去做检测了啊!呼呼~~~~


    五、开始检测吧

    opencv有个opencv_performance.exe程序用于检测,但是它只能用在用opencv_haartraining.exe来用的,所以我这里是针对一些列图片进行检测的,检测代码如下:

    #include <windows.h>
    #include <mmsystem.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "wininet.h"
    #include <direct.h>
    #include <string.h>
    #include <list>
    #pragma comment(lib,"Wininet.lib")
    
    
    #include "opencv2/objdetect/objdetect.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/ml/ml.hpp"
    
    #include <iostream>
    #include <stdio.h>
    
    using namespace std;
    using namespace cv;
    
    String cascadeName = "./cascade.xml";//训练数据
    
    struct PathElem{
    	TCHAR   SrcImgPath[MAX_PATH*2];
    	TCHAR   RstImgPath[MAX_PATH*2];
    };
    int FindImgs(char * pSrcImgPath, char * pRstImgPath, std::list<PathElem> &ImgList);
    
    int main( )
    {
    	CascadeClassifier cascade;//创建级联分类器对象
    	std::list<PathElem> ImgList; 
    	std::list<PathElem>::iterator pImgListTemp; 
    	vector<Rect> rects;
    	vector<Rect>::const_iterator pRect;
    
    	double scale = 1.;
    	Mat image;
    	double t;
    	if( !cascade.load( cascadeName ) )//从指定的文件目录中加载级联分类器
    	{
    		cerr << "ERROR: Could not load classifier cascade" << endl;
    		return 0;
    	}
    
    	
    	int nFlag = FindImgs("H:/SrcPic/","H:/RstPic/", ImgList);		
    	if(nFlag != 0)   
    	{
    		cout<<"Read Image  error !  Input 0 to exit \n";
    		exit(0);
    	}
    
    	pImgListTemp = ImgList.begin();
    	for(int iik = 1; iik <= ImgList.size(); iik++,pImgListTemp++)
    	{
    		image = imread(pImgListTemp->SrcImgPath);	
    		if( !image.empty() )//读取图片数据不能为空
    		{
    			Mat gray, smallImg( cvRound (image.rows/scale), cvRound(image.cols/scale), CV_8UC1 );//将图片缩小,加快检测速度
    			cvtColor( image, gray, CV_BGR2GRAY );//因为用的是类haar特征,所以都是基于灰度图像的,这里要转换成灰度图像
    			resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );//将尺寸缩小到1/scale,用线性插值
    			equalizeHist( smallImg, smallImg );//直方图均衡
    
    			//detectMultiScale函数中smallImg表示的是要检测的输入图像为smallImg,rects表示检测到的目标序列,1.1表示
    			//每次图像尺寸减小的比例为1.1,2表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大
    			//小都可以检测到目标),CV_HAAR_SCALE_IMAGE表示不是缩放分类器来检测,而是缩放图像,Size(30, 30)为目标的
    			//最小最大尺寸
    			rects.clear();
    			printf( "begin...\n");
    			t = (double)cvGetTickCount();//用来计算算法执行时间
    			cascade.detectMultiScale(smallImg,rects,1.1,2,0,Size(20,20),Size(30,30));
    			//|CV_HAAR_FIND_BIGGEST_OBJECT//|CV_HAAR_DO_ROUGH_SEARCH|CV_HAAR_SCALE_IMAGE,
    
    			t = (double)cvGetTickCount() - t;
    			printf( "detection time = %g ms\n\n", t/((double)cvGetTickFrequency()*1000.) );
    			for(pRect = rects.begin(); pRect != rects.end(); pRect++)
    			{
    				rectangle(image,cvPoint(pRect->x,pRect->y),cvPoint(pRect->x+pRect->width,pRect->y+pRect->height),cvScalar(0,255,0));
    			}
    			imwrite(pImgListTemp->RstImgPath,image);
    		}
    	}
    	
    	return 0;
    }
    
    int FindImgs(char * pSrcImgPath, char * pRstImgPath, std::list<PathElem> &ImgList)
    {
    	//源图片存在的目录
    	TCHAR   szFileT1[MAX_PATH*2];
    	lstrcpy(szFileT1,TEXT(pSrcImgPath));   
    	lstrcat(szFileT1, TEXT("*.*"));
    
    	//结果图片存放的目录
    	TCHAR   RstAddr[MAX_PATH*2]; 
    	lstrcpy(RstAddr,TEXT(pRstImgPath));
    	_mkdir(RstAddr);   //创建文件夹
    
    	WIN32_FIND_DATA   wfd; 	
    	HANDLE   hFind   =   FindFirstFile(szFileT1, &wfd); 
    
    
    	PathElem stPathElemTemp;
    	if(hFind != INVALID_HANDLE_VALUE)   
    	{
    		do 
    		{ 
    			if(wfd.cFileName[0] == TEXT('.')) 
    				continue;
    			if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY || strcmp("Thumbs.db", TEXT(wfd.cFileName)) == 0) 
    			{ 
    				;
    			}  
    			else 
    			{ 
    
    				TCHAR   SrcImgPath[MAX_PATH*2];
    				lstrcpy(SrcImgPath, pSrcImgPath); 
    				lstrcat(SrcImgPath, TEXT(wfd.cFileName));
    
    				lstrcpy(stPathElemTemp.SrcImgPath, SrcImgPath); 
    
    				TCHAR   AdressTemp[MAX_PATH*2];
    				lstrcpy(AdressTemp,pRstImgPath); 
    
    				//lstrcat(AdressTemp, TEXT("/"));  
    				lstrcat(AdressTemp, TEXT(wfd.cFileName));  
    				lstrcpy(stPathElemTemp.RstImgPath, AdressTemp); 
    
    				ImgList.push_back(stPathElemTemp);
    
    			}
    		}while(FindNextFile(hFind, &wfd));
    	}
    	else
    	{
    		return -1;
    	}
    	return 0;
    }

    自己看看自己的检测结果咯。效果不好的改进样本,调整训练参数吧~~~嘎嘎


    我觉得我写的够白痴,很方便大家直接拿来用。其中一些细节,大家自己琢磨吧~88



    附:

    1、opencv_createsamples.exe的参数

    (createsamples.cpp)

    	"  [-info <collection_file_name>]\n"
    	"  [-img <image_file_name>]\n"
    	"  [-vec <vec_file_name>]\n"
    	"  [-bg <background_file_name>]\n  [-num <number_of_samples = %d>]\n"
    	"  [-bgcolor <background_color = %d>]\n"
    	"  [-inv] [-randinv] [-bgthresh <background_color_threshold = %d>]\n"
    	"  [-maxidev <max_intensity_deviation = %d>]\n"
    	"  [-maxxangle <max_x_rotation_angle = %f>]\n"
    	"  [-maxyangle <max_y_rotation_angle = %f>]\n"
    	"  [-maxzangle <max_z_rotation_angle = %f>]\n"
    	"  [-show [<scale = %f>]]\n"
    	"  [-w <sample_width = %d>]\n  [-h <sample_height = %d>]\n"//默认24*24

    以下1)~4)是按顺序判断,且有且仅有一个

    1)提供imagename 和vecname时,调用以下操作
    /*
     * cvCreateTrainingSamples
     *
     * Create training samples applying random distortions to sample image and
     * store them in .vec file
     *
     * filename        - .vec file name
     * imgfilename     - sample image file name
     * bgcolor         - background color for sample image
     * bgthreshold     - background color threshold. Pixels those colors are in range
     *   [bgcolor-bgthreshold, bgcolor+bgthreshold] are considered as transparent
     * bgfilename      - background description file name. If not NULL samples
     *   will be put on arbitrary background
     * count           - desired number of samples
     * invert          - if not 0 sample foreground pixels will be inverted
     *   if invert == CV_RANDOM_INVERT then samples will be inverted randomly
     * maxintensitydev - desired max intensity deviation of foreground samples pixels
     * maxxangle       - max rotation angles
     * maxyangle
     * maxzangle
     * showsamples     - if not 0 samples will be shown
     * winwidth        - desired samples width
     * winheight       - desired samples height
     */
    2)提供imagename、bgfilename和infoname时
    与1)类似
    3)提供 infoname和 vecname时,调用以下操作(这里是我们训练需要的)
    /*
     * cvCreateTrainingSamplesFromInfo
     *
     * Create training samples from a set of marked up images and store them into .vec file
     * infoname    - file in which marked up image descriptions are stored
     * num         - desired number of samples
     * showsamples - if not 0 samples will be shown
     * winwidth    - sample width
     * winheight   - sample height
     * 
     * Return number of successfully created samples
     */
    int cvCreateTrainingSamplesFromInfo( const char* infoname, const char* vecfilename,
                                         int num,
                                         int showsamples,
                                         int winwidth, int winheight )

    函数内容:读取当前图中所有标记的sample(x,y,w,h),并将其缩放到winwidth、winheight大小,故在这之前的人为缩放操作不需要

    (可以看到,仅需要num、w、h参数)
    4)仅vecname时,可以将vec里面的所有缩放后的samples都显示出来
    /*
     * cvShowVecSamples
     *
     * Shows samples stored in .vec file
     *
     * filename
     *   .vec file name
     * winwidth
     *   sample width
     * winheight
     *   sample height
     * scale
     *   the scale each sample is adjusted to(这个scale与3中的缩放不是一回事,这里仅为了显示而再次缩放)
     */
    void cvShowVecSamples( const char* filename, int winwidth, int winheight, double scale );

    2、opencv_haartraining.exe的参数

    (haartraining.cpp )

    "  -data <dir_name>\n"
    "  -vec <vec_file_name>\n"
    "  -bg <background_file_name>\n"
    "  [-bg-vecfile]\n"
    "  [-npos <number_of_positive_samples = %d>]\n"
    "  [-nneg <number_of_negative_samples = %d>]\n"
    "  [-nstages <number_of_stages = %d>]\n"
    "  [-nsplits <number_of_splits = %d>]\n"
    "  [-mem <memory_in_MB = %d>]\n"
    "  [-sym (default)] [-nonsym]\n"
    "  [-minhitrate <min_hit_rate = %f>]\n"
    "  [-maxfalsealarm <max_false_alarm_rate = %f>]\n"
    "  [-weighttrimming <weight_trimming = %f>]\n"
    "  [-eqw]\n"
    "  [-mode <BASIC (default) | CORE | ALL>]\n"
    "  [-w <sample_width = %d>]\n"
    "  [-h <sample_height = %d>]\n"
    "  [-bt <DAB | RAB | LB | GAB (default)>]\n"
    "  [-err <misclass (default) | gini | entropy>]\n"
    "  [-maxtreesplits <max_number_of_splits_in_tree_cascade = %d>]\n"
    "  [-minpos <min_number_of_positive_samples_per_cluster = %d>]\n"

    3、opencv_performance.exe参数

    (performance.cpp )

    "  -data <classifier_directory_name>\n"
    "  -info <collection_file_name>\n"
    "  [-maxSizeDiff <max_size_difference = %f>]\n"
    "  [-maxPosDiff <max_position_difference = %f>]\n"
    "  [-sf <scale_factor = %f>]\n"
    "  [-ni <saveDetected = 0>]\n"
    "  [-nos <number_of_stages = %d>]\n"
    "  [-rs <roc_size = %d>]\n"
    "  [-w <sample_width = %d>]\n"
    "  [-h <sample_height = %d>]\n"


    4、opencv_traincascade.exe参数说明

    ——traincascade.cpp 

            cout << "Usage: " << argv[0] << endl;
            cout << "  -data <cascade_dir_name>" << endl;
            cout << "  -vec <vec_file_name>" << endl;
            cout << "  -bg <background_file_name>" << endl;
            cout << "  [-numPos <number_of_positive_samples = " << numPos << ">]" << endl;	//默认2000
            cout << "  [-numNeg <number_of_negative_samples = " << numNeg << ">]" << endl;	//默认1000
            cout << "  [-numStages <number_of_stages = " << numStages << ">]" << endl;	//默认20
            cout << "  [-precalcValBufSize <precalculated_vals_buffer_size_in_Mb = " << precalcValBufSize << ">]" << endl;//默认256
            cout << "  [-precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb = " << precalcIdxBufSize << ">]" << endl;//默认256
            cout << "  [-baseFormatSave]" << endl;						//是否按照旧版存xml文件默认false
           // cout << "  [-numThreads <max_number_of_threads = " << numThreads << ">]" << endl;//这个参数在3.0版本中才出现,默认numThreads = getNumThreads();
           // cout << "  [-acceptanceRatioBreakValue <value> = " << acceptanceRatioBreakValue << ">]" << endl;//这个参数在3.0版本中才出现,默认-1.0
            cascadeParams.printDefaults();
            stageParams.printDefaults();
            for( int fi = 0; fi < fc; fi++ )
                featureParams[fi]->printDefaults();

    其中cascadeParams.printDefaults();——cascadeclassifier.cpp 如下

        cout << "  [-stageType <";                                                 //默认BOOST
        for( int i = 0; i < (int)(sizeof(stageTypes)/sizeof(stageTypes[0])); i++ )
        {
            cout << (i ? " | " : "") << stageTypes[i];
            if ( i == defaultStageType )
                cout << "(default)";
        }
        cout << ">]" << endl;
    
        cout << "  [-featureType <{";                                              //默认HAAR
        for( int i = 0; i < (int)(sizeof(featureTypes)/sizeof(featureTypes[0])); i++ )
        {
            cout << (i ? ", " : "") << featureTypes[i];
            if ( i == defaultStageType )
                cout << "(default)";
        }
        cout << "}>]" << endl;
        cout << "  [-w <sampleWidth = " << winSize.width << ">]" << endl;        //默认24*24
        cout << "  [-h <sampleHeight = " << winSize.height << ">]" << endl;
    stageParams.printDefaults();——boost.cpp如下

        cout << "--boostParams--" << endl;
        cout << "  [-bt <{" << CC_DISCRETE_BOOST << ", "
                            << CC_REAL_BOOST << ", "
                            << CC_LOGIT_BOOST ", "
                            << CC_GENTLE_BOOST << "(default)}>]" << endl;                         //默认CC_GENTLE_BOOST 
        cout << "  [-minHitRate <min_hit_rate> = " << minHitRate << ">]" << endl;                 //默认0.995
        cout << "  [-maxFalseAlarmRate <max_false_alarm_rate = " << maxFalseAlarm << ">]" << endl;//默认0.5
        cout << "  [-weightTrimRate <weight_trim_rate = " << weight_trim_rate << ">]" << endl;    //默认0.95
        cout << "  [-maxDepth <max_depth_of_weak_tree = " << max_depth << ">]" << endl;           //默认1
        cout << "  [-maxWeakCount <max_weak_tree_count = " << weak_count << ">]" << endl;         //默认100
    featureParams[fi]->printDefaults();——haarfeatures.cpp 如下

     cout << "  [-mode <" CC_MODE_BASIC << "(default)| "  //默认CC_MODE_BASIC
                << CC_MODE_CORE <<" | " << CC_MODE_ALL << endl;

    通用参数:

    -data<cascade_dir_name>

    目录名,如不存在训练程序会创建它,用于存放训练好的分类器


    -vec<vec_file_name>

    包含正样本的vec文件名(由 opencv_createsamples 程序生成)


    -bg<background_file_name>

    背景描述文件,也就是包含负样本文件名的那个描述文件


    -numPos<number_of_positive_samples>

    每级分类器训练时所用的正样本数目


    -numNeg<number_of_negative_samples>

    每级分类器训练时所用的负样本数目,可以大于 -bg 指定的图片数目


    -numStages<number_of_stages>

    训练的分类器的级数。


    -precalcValBufSize<precalculated_vals_buffer_size_in_Mb>

    缓存大小,用于存储预先计算的特征值(feature values),单位为MB


    -precalcIdxBufSize<precalculated_idxs_buffer_size_in_Mb>

    缓存大小,用于存储预先计算的特征索引(feature indices),单位为MB。内存越大,训练时间越短


    -baseFormatSave

    这个参数仅在使用Haar特征时有效。如果指定这个参数,那么级联分类器将以老的格式存储


    级联参数:

    -stageType<BOOST(default)>

    级别(stage)参数。目前只支持将BOOST分类器作为级别的类型


    -featureType<{HAAR(default),LBP}>

    特征的类型: HAAR - Haar特征;LBP - 局部纹理模式特征


    -w<sampleWidth>

    -h<sampleHeight>

    训练样本的尺寸(单位为像素)。必须跟训练样本创建(使用 opencv_createsamples 程序创建)时的尺寸保持一致


    Boosted分类器参数:

    -bt<{DAB,RAB,LB,GAB(default)}>

    Boosted分类器的类型: DAB - Discrete AdaBoost,RAB - Real AdaBoost,LB - LogitBoost, GAB - Gentle AdaBoost


    -minHitRate<min_hit_rate>

    分类器的每一级希望得到的最小检测率(正样本被判成正样本的比例)。总的检测率大约为 min_hit_rate^number_of_stages。可以设很高,如0.999


    -maxFalseAlarmRate<max_false_alarm_rate>

    分类器的每一级希望得到的最大误检率(负样本被判成正样本的比例)。总的误检率大约为 max_false_alarm_rate^number_of_stages。可以设较低,如0.5


    -weightTrimRate<weight_trim_rate>

    Specifies whether trimming should be used and its weight. 一个还不错的数值是0.95


    -maxDepth<max_depth_of_weak_tree>

    弱分类器树最大的深度。一个还不错的数值是1,是二叉树(stumps


    -maxWeakCount<max_weak_tree_count>

    每一级中的弱分类器的最大数目。The boosted classifier (stage) will have so many weak trees (<=maxWeakCount), as needed to achieve the given-maxFalseAlarmRate


    Haar特征参数:

    -mode<BASIC(default)| CORE|ALL>

    选择训练过程中使用的Haar特征的类型。 BASIC 只使用右上特征, ALL 使用所有右上特征和45度旋转特征


    5、detectMultiScale函数参数说明

    该函数会在输入图像的不同尺度中检测目标:

    image  -输入的灰度图像,

    objects  -被检测到的目标矩形框向量组,

    scaleFactor  -为每一个图像尺度中的尺度参数,默认值为1.1

    minNeighbors  -为每一个级联矩形应该保留的邻近个数,默认为3,表示至少有3次检测到目标,才认为是目标

    flags -CV_HAAR_DO_CANNY_PRUNING,利用Canny边缘检测器来排除一些边缘很少或者很多的图像区域;

               CV_HAAR_SCALE_IMAGE,按比例正常检测;

               CV_HAAR_FIND_BIGGEST_OBJECT,只检测最大的物体;

               CV_HAAR_DO_ROUGH_SEARCH,只做粗略检测。默认值是0

    minSize和maxSize -用来限制得到的目标区域的范围(先找maxsize,再用1.1参数缩小,直到小于minSize终止检测)

    展开全文
  • 关键字:训练器,contrib,Trainer 问题描述:在使用Trainer函数创建训练器的时候,出现错误,错误提示NameError: name ‘Trainer’ is not defined。 报错信息: &lt;ipython-input-7-4908863d4852&...
    • 关键字:训练器contribTrainer

    • 问题描述:在使用Trainer函数创建训练器的时候,出现错误,错误提示NameError: name ‘Trainer’ is not defined。

    • 报错信息:

    <ipython-input-7-4908863d4852> in main()
          9     place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
         10 
    ---> 11     trainer = Trainer(
         12         train_func=train_program, place=place, optimizer_func=optimizer_program)
         13 
    
    NameError: name 'Trainer' is not defined
    
    • 问题复现:安装PaddlePaddle 1.0以上的版本,然后通过from paddle.fluid.trainer import *导入PaddlePaddle的高级API,之后使用Trainer创建一个训练器,就会报错。错误代码如下:
    from paddle.fluid.trainer import *
    from paddle.fluid.inferencer import *
    ······
    trainer = Trainer(
        train_func=train_program, place=place, optimizer_func=optimizer_program)
    
    • 问题解决:在PaddlePaddle 1.0以上的版本,高级API已经迁移到paddle.fluid.contrib目录下,所以在导包的是应该要使用from paddle.fluid.contrib.trainer import *的导包方式。正确代码如下:
    from paddle.fluid.contrib.trainer import *
    from paddle.fluid.contrib.inferencer import *
    ······
    trainer = Trainer(
        train_func=train_program, place=place, optimizer_func=optimizer_program)
    
    • 问题分析:在对于高层API,PaddlePaddle在版本1.0之后做了很大的改动,比如就修改了高层API所在的位置。同时也完善了高层API的很多功能。高层API虽然没有底层API灵活,但高层API使用更简单,非常适合初学者使用。
    展开全文
  • 手把手教你训练分类

    千次阅读 2014-07-28 14:44:21
    手把手教你训练分类 转载自: 训练过程就是上面的三步 关于正负样本的一些理解:  正样本即包括目标的图片,一般较小(教程里提到的一般是24*24 20*20 18*18单位是像素> 但是在实际做的...

    转载自:http://zhan.renren.com/xjtuopencv?gid=3602888498033866847


    训练过程就是上面的三步

    关于正负样本的一些理解:

           正样本即包括目标的图片,一般较小(教程里提到的一般是24*24 20*20 18*18<单位是像素但是在实际做的时候总有种太模糊,什么都看不清的感觉,我觉得应该可以适当的加大图像,提供更多细节试试,虽然这必然会导致更多的运算时间,而且在进行处理之前,应将所有正样本进行标准化处理<统一大小,转化为灰度图>

            负样本,与正样本相反很容易理解,即任何不包含检测目标的图像,对负样本的标准化处理并不严格,仅有:灰度图 <可能也能使用彩图,在选项里又看到bgcolor这个选项,对图像的大小的限制是大于正样本尺寸(必须满足,是由于训练器的算法决定),同时负样本的数量一般远多于正样本的数量(2-3倍或以上的样子)

             关于合适的样本数量,教程还有opencv中推荐的都是正样本1000+,负样本3000+,这意味着训练时间会很长(目测一晚上+),当然如果你只是来试试看训练方法怎么样,那么可是使用少量样本比如100+的正样本。

            下面进入正题:

    首先我们要获得一个正样本的描述文件

    用于描述正样本文件名(包括绝对路径或相对路径),

    正样本数目以及各正样本在图片中的位置和大小。典型的正样本描述文件如下:

    face_100/face00001.bmp 1 0 0 20 20

    face_100/face00002.bmp 1 0 0 20 20

    face_100/face00003.bmp 1 0 0 20 20

    其中face_100/是相对路径,face00001.bmp是图片名称,1 0 0 20 20 分别表示 1张图片,本样本左下角坐标(不一定是左下,但是肯定是距离原点最近的点)是0 0,右上角的坐标(同样的道理不一定是右上角)是20 20

     

    具体方法是在Dos 下的恰当目录敲入dir/b > samples.dat,则会生成一个samples.dat,里面包含所有正样本文件名列表,但没有相对路径名和正样本位置信息。在samples.dat 文件各行行首增加“face _100/”的方法是使用文本编辑器替换功能,先选中所有行,然后按Tab 键为每行增加一个制表位,然后将制表位全部替换为“face _100/”即可。通过将“bmp”替换为“bmp 1 0 0 20 20”即可在每行添加“1 0 0 20 20”。

    注释:图片文件的格式不局限与bmp jpg png都行,其他格式的没试过,估计opencv支持的都可以

    运行 CreateSamples.exe 程序。下面是一个运行参数示例:

    -info F:\FaceDetect\samples.dat -vec F:\FaceDetect\samples.vec -num 200 -w 20 -h 20

    表示有200 个样本,样本宽20,高20,正样本描述文件为samples.dat,结果输出到samples.vec。

    运行完了会生成一个*.vec 的文件。

     

             对于负样本的描述文件其处理方法与正样本基本相同,但是一个负样本的描述文件应该是做到这样的程度:

    face_100/face00001.bmp

    face_100/face00002.bmp

    face_100/face00003.bmp

    即只有图片的路径,名称,而没有图片数量大小的描述,而且其也不是vec文件,而是dir /b>时所指定的文件

     

    非常重要的一点,所有的样本描述的条目中,路径和文件名内部不允许出现空格,原因自己想

     

    样本创建之后,接下来要训练分类器,这个过程是由haartraining 程序来实现的。该程序源

    码由OpenCV 自带,且可执行程序在OpenCV 安装目录的bin 目录下。

    Haartraining 的命令行参数如下:

    -data<dir_name>

    存放训练好的分类器的路径名。

    -vec<vec_file_name>

    正样本文件名(由trainingssamples 程序或者由其他的方法创建的)

    -bg<background_file_name>

    背景描述文件。

    -npos<number_of_positive_samples>,

    -nneg<number_of_negative_samples>

    用来训练每一个分类器阶段的正/负样本。合理的值是:nPos = 7000;nNeg = 3000

    -nstages<number_of_stages>

    训练的阶段数。

    -nsplits<number_of_splits>

    决定用于阶段分类器的弱分类器。如果1,则一个简单的stump classifier 被使用。如果是2

    或者更多,则带有number_of_splits 个内部节点的CART 分类器被使用。

    -mem<memory_in_MB>

    预先计算的以MB 为单位的可用内存。内存越大则训练的速度越快。

    -sym(default)

    -nonsym

    指定训练的目标对象是否垂直对称。垂直对称提高目标的训练速度。例如,正面部是垂直对

    称的。

    -minhitrate《min_hit_rate》

    每个阶段分类器需要的最小的命中率。总的命中率为min_hit_rate 的number_of_stages 次

    方。

    -maxfalsealarm<max_false_alarm_rate>

    没有阶段分类器的最大错误报警率。总的错误警告率为max_false_alarm_rate 的

    number_of_stages 次方。

    -weighttrimming<weight_trimming>

    指定是否使用权修正和使用多大的权修正。一个基本的选择是0.9

    -eqw

    -mode<basic(default)|core|all>

    选择用来训练的haar 特征集的种类。basic 仅仅使用垂直特征。all 使用垂直和45 度角旋转

    特征。

    -w《sample_width》

    -h《sample_height》

    训练样本的尺寸,(以像素为单位)。必须和训练样本创建的尺寸相同。

    一个训练分类器的例子:

    "D:\Program Files\OpenCV\bin\haartraining.exe" -data data\cascade -vec data\pos.vec

    -bg negdata\negdata.dat -npos 49 -nneg 49 -mem 200 -mode ALL -w 20 -h 20

    训练结束后,会在目录data 下生成一些子目录,即为训练好的分类器。

    值得提醒的是xml文件在于data目录同级的目录下<如果训练成功的话>

    我在试着训练时使用的参数

    注意 -nsplits 这个选项应该尽量设置成2(到底有没有更高的值,我也不知道,应该有吧),这样会获得起码比较细致的训练过程,如果选的话,我不知道你们会怎么样,反正我是只得到了一个6k大小的xml文件,几乎不能用

    展开全文
  • pytorchgpu训练,单机多卡,机多卡

    千次阅读 热门讨论 2019-10-09 09:42:03
    pytorchgpu并行训练 暂时只是使用了单机多卡的GPU进行测试, 并没有使用机多卡, 这里只简述了如何使用DistributedDataParallel代替DataParallel torch.nn.DataParallel   我一般在使用GPU的时候, 会喜欢使用...

    目录

    pytorch多gpu并行训练

    注: 以下都在Ubuntu上面进行的调试, 使用的Ubuntu版本包括14, 18LST

    参考文档:

    data_parallel_tutorial

    distributeddataparallel

    environment-variable-initialization

    PYTORCH 1.0 DISTRIBUTED TRAINER WITH AMAZON AWS

    pytorch/examples/imagenet/main.py

    Distributed-VGG-F

    Getting Started with Distributed Data Parallel

    1.单机多卡并行训练

    1.1.torch.nn.DataParallel

      我一般在使用多GPU的时候, 会喜欢使用os.environ['CUDA_VISIBLE_DEVICES']来限制使用的GPU个数, 例如我要使用第0和第3编号的GPU, 那么只需要在程序中设置:

    os.environ['CUDA_VISIBLE_DEVICES'] = '0,3'
    

      但是要注意的是, 这个参数的设定要保证在模型加载到gpu上之前, 我一般都是在程序开始的时候就设定好这个参数, 之后如何将模型加载到多GPU上面呢?

      如果是模型, 那么需要执行下面的这几句代码:

    model = nn.DataParallel(model)
    model = model.cuda()
    

      如果是数据, 那么直接执行下面这几句代码就可以了:

    inputs = inputs.cuda()
    labels = labels.cuda()
    

      其实如果看pytorch官网给的示例代码,我们可以看到下面这样的代码

    model = Model(input_size, output_size)
    if torch.cuda.device_count() > 1:
        print("Let's use", torch.cuda.device_count(), "GPUs!")
        # dim = 0 [30, xxx] -> [10, ...], [10, ...], [10, ...] on 3 GPUs
        model = nn.DataParallel(model)
    
    model.to(device)
    

      这个和我上面写的好像有点不太一样, 但是如果看一下DataParallel的内部代码, 我们就可以发现, 其实是一样的:

    class DataParallel(Module):
        def __init__(self, module, device_ids=None, output_device=None, dim=0):
            super(DataParallel, self).__init__()
    
            if not torch.cuda.is_available():
                self.module = module
                self.device_ids = []
                return
    
            if device_ids is None:
                device_ids = list(range(torch.cuda.device_count()))
            if output_device is None:
                output_device = device_ids[0]
    

      我截取了其中一部分代码, 我们可以看到如果我们不设定好要使用的device_ids的话, 程序会自动找到这个机器上面可以用的所有的显卡, 然后用于训练. 但是因为我们前面使用os.environ['CUDA_VISIBLE_DEVICES']限定了这个程序可以使用的显卡, 所以这个地方程序如果自己获取的话, 获取到的其实就是我们上面设定的那几个显卡.

      我没有进行深入得到考究, 但是我感觉使用os.environ['CUDA_VISIBLE_DEVICES']对可以使用的显卡进行限定之后, 显卡的实际编号和程序看到的编号应该是不一样的, 例如上面我们设定的是os.environ['CUDA_VISIBLE_DEVICES']="0,2", 但是程序看到的显卡编号应该被改成了'0,1', 也就是说程序所使用的显卡编号实际上是经过了一次映射之后才会映射到真正的显卡编号上面的, 例如这里的程序看到的1对应实际的2

    1.2.torch.nn.parallel.DistributedDataParallel

      pytorch的官网建议使用DistributedDataParallel来代替DataParallel, 据说是因为DistributedDataParallelDataParallel运行的更快, 然后显存分屏的更加均衡. 而且DistributedDataParallel功能更加强悍, 例如分布式的模型(一个模型太大, 以至于无法放到一个GPU上运行, 需要分开到多个GPU上面执行). 只有DistributedDataParallel支持分布式的模型像单机模型那样可以进行多机多卡的运算.当然具体的怎么个情况, 建议看官方文档.

      依旧是先设定好os.environ['CUDA_VISIBLE_DEVICES'], 然后再进行下面的步骤.

      因为DistributedDataParallel是支持多机多卡的, 所以这个需要先初始化一下, 如下面的代码:

    torch.distributed.init_process_group(backend='nccl', init_method='tcp://localhost:23456', rank=0, world_size=1)
    

      第一个参数是pytorch支持的通讯后端, 后面会继续介绍, 但是这里单机多卡, 这个就是走走过场. 第二个参数是各个机器之间通讯的方式, 后面会介绍, 这里是单机多卡, 设置成localhost就行了, 后面的端口自己找一个空着没用的就行了. rank是标识主机和从机的, 这里就一个主机, 设置成0就行了. world_size是标识使用几个主机, 这里就一个主机, 设置成1就行了, 设置多了代码不允许.

      其实如果是使用单机多卡的情况下, 根据pytorch的官方代码distributeddataparallel, 是直接可以使用下面的代码的:

    torch.distributed.init_process_group(backend="nccl")
    model = DistributedDataParallel(model) # device_ids will include all GPU devices by default
    

      但是这里需要注意的是, 如果使用这句代码, 直接在pycharm或者别的编辑器中,是没法正常运行的, 因为这个需要在shell的命令行中运行, 如果想要正确执行这段代码, 假设这段代码的名字是main.py, 可以使用如下的方法进行(参考1 参考2):

    python -m torch.distributed.launch main.py 
    

    注: 这里如果使用了argparse, 一定要在参数里面加上--local_rank, 否则运行还是会出错的

      之后就和使用DataParallel很类似了.

    model = model.cuda()
    model = nn.parallel.DistributedDataParallel(model)
    

      但是注意这里要先将model加载到GPU, 然后才能使用DistributedDataParallel进行分发, 之后的使用和DataParallel就基本一样了

    2.多机多gpu训练

    在单机多gpu可以满足的情况下, 绝对不建议使用多机多gpu进行训练, 我经过测试, 发现多台机器之间传输数据的时间非常慢, 主要是因为我测试的机器可能只是千兆网卡, 再加上别的一些损耗, 网络的传输速度跟不上, 导致训练速度实际很慢. 我看一个github上面的人说在单机8显卡可以满足的情况下, 最好不要进行多机多卡训练

    建议看这两份代码, 实际运行一下, 才会真的理解怎么使用

    pytorch/examples/imagenet/main.py

    Distributed-VGG-F

    2.1.初始化

    初始化操作一般在程序刚开始的时候进行

      在进行多机多gpu进行训练的时候, 需要先使用torch.distributed.init_process_group()进行初始化. torch.distributed.init_process_group()包含四个常用的参数

    backend: 后端, 实际上是多个机器之间交换数据的协议
    init_method: 机器之间交换数据, 需要指定一个主节点, 而这个参数就是指定主节点的
    world_size: 介绍都是说是进程, 实际就是机器的个数, 例如两台机器一起训练的话, world_size就设置为2
    rank: 区分主节点和从节点的, 主节点为0, 剩余的为了1-(N-1), N为要使用的机器的数量, 也就是world_size
    

    2.1.1.初始化backend

      首先要初始化的是backend, 也就是俗称的后端, 在pytorch的官方教程中提供了以下这些后端

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LhZ2L1aY-1571025664154)(img/2019-10-9-pytorch多gpu并行训练/pytorch后端.png)]

      根据官网的介绍, 如果是使用cpu的分布式计算, 建议使用gloo, 因为表中可以看到
    gloo对cpu的支持是最好的, 然后如果使用gpu进行分布式计算, 建议使用nccl, 实际测试中我也感觉到, 当使用gpu的时候, nccl的效率是高于gloo的. 根据博客和官网的态度, 好像都不怎么推荐在多gpu的时候使用mpi

      对于后端选择好了之后, 我们需要设置一下网络接口, 因为多个主机之间肯定是使用网络进行交换, 那肯定就涉及到ip之类的, 对于ncclgloo一般会自己寻找网络接口, 但是某些时候, 比如我测试用的服务器, 不知道是系统有点古老, 还是网卡比较多, 需要自己手动设置. 设置的方法也比较简单, 在Python的代码中, 使用下面的代码进行设置就行:

    import os
    # 以下二选一, 第一个是使用gloo后端需要设置的, 第二个是使用nccl需要设置的
    os.environ['GLOO_SOCKET_IFNAME'] = 'eth0'
    os.environ['NCCL_SOCKET_IFNAME'] = 'eth0'
    

      我们怎么知道自己的网络接口呢, 打开命令行, 然后输入ifconfig, 然后找到那个带自己ip地址的就是了, 我见过的一般就是em0, eth0, esp2s0之类的, 当然具体的根据你自己的填写. 如果没装ifconfig, 输入命令会报错, 但是根据报错提示安装一个就行了.

    2.1.2.初始化init_method

      初始化init_method的方法有两种, 一种是使用TCP进行初始化, 另外一种是使用共享文件系统进行初始化

    2.1.2.1.使用TCP初始化

      看代码:

    import torch.distributed as dist
    
    dist.init_process_group(backend, init_method='tcp://10.1.1.20:23456',
                            rank=rank, world_size=world_size)
    

      注意这里使用格式为tcp://ip:端口号, 首先ip地址是你的主节点的ip地址, 也就是rank参数为0的那个主机的ip地址, 然后再选择一个空闲的端口号, 这样就可以初始化init_method了.

    2.1.2.2.使用共享文件系统初始化

      好像看到有些人并不推荐这种方法, 因为这个方法好像比TCP初始化要没法, 搞不好和你硬盘的格式还有关系, 特别是window的硬盘格式和Ubuntu的还不一样, 我没有测试这个方法, 看代码:

    import torch.distributed as dist
    
    dist.init_process_group(backend, init_method='file:///mnt/nfs/sharedfile',
                            rank=rank, world_size=world_size)
    

      根据官网介绍, 要注意提供的共享文件一开始应该是不存在的, 但是这个方法又不会在自己执行结束删除文件, 所以下次再进行初始化的时候, 需要手动删除上次的文件, 所以比较麻烦, 而且官网给了一堆警告, 再次说明了这个方法不如TCP初始化的简单.

    2.1.3.初始化rankworld_size

      这里其实没有多难, 你需要确保, 不同机器的rank值不同, 但是主机的rank必须为0, 而且使用init_method的ip一定是rank为0的主机, 其次world_size是你的主机数量, 你不能随便设置这个数值, 你的参与训练的主机数量达不到world_size的设置值时, 代码是不会执行的.

    2.1.4.初始化中一些需要注意的地方

      首先是代码的统一性, 所有的节点上面的代码, 建议完全一样, 不然有可能会出现一些问题, 其次, 这些初始化的参数强烈建议通过argparse模块(命令行参数的形式)输入, 不建议写死在代码中, 也不建议使用pycharm之类的IDE进行代码的运行, 强烈建议使用命令行直接运行.

      其次是运行代码的命令方面的问题, 例如使用下面的命令运行代码distributed.py:

    python distributed.py -bk nccl -im tcp://10.10.10.1:12345 -rn 0 -ws 2 
    

      上面的代码是在主节点上运行, 所以设置rank为0, 同时设置了使用两个主机, 在从节点运行的时候, 输入的代码是下面这样:

    python distributed.py -bk nccl -im tcp://10.10.10.1:12345 -rn 1 -ws 2 
    

      一定要注意的是, 只能修改rank的值, 其他的值一律不得修改, 否则程序就卡死了初始化到这里也就结束了.

    2.2.数据的处理-DataLoader

      其实数据的处理和正常的代码的数据处理非常类似, 但是因为多机多卡涉及到了效率问题, 所以这里才会使用torch.utils.data.distributed.DistributedSampler来规避数据传输的问题. 首先看下面的代码:

    print("Initialize Dataloaders...")
    # Define the transform for the data. Notice, we must resize to 224x224 with this dataset and model.
    transform = transforms.Compose(
        [transforms.Resize(224),
         transforms.ToTensor(),
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
    
    # Initialize Datasets. STL10 will automatically download if not present
    trainset = datasets.STL10(root='./data', split='train', download=True, transform=transform)
    valset = datasets.STL10(root='./data', split='test', download=True, transform=transform)
    
    # Create DistributedSampler to handle distributing the dataset across nodes when training
    # This can only be called after torch.distributed.init_process_group is called
    # 这一句就是和平时使用有点不一样的地方
    train_sampler = torch.utils.data.distributed.DistributedSampler(trainset)
    
    # Create the Dataloaders to feed data to the training and validation steps
    train_loader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=(train_sampler is None), num_workers=workers, pin_memory=False, sampler=train_sampler)
    val_loader = torch.utils.data.DataLoader(valset, batch_size=batch_size, shuffle=False, num_workers=workers, pin_memory=False)
    

      其实单独看这段代码, 和平时写的很类似, 唯一不一样的其实就是这里先将trainset送到了DistributedSampler中创造了一个train_sampler, 然后在构造train_loader的时候, 参数中传入了一个sampler=train_sampler. 使用这些的意图是, 让不同节点的机器加载自己本地的数据进行训练, 也就是说进行多机多卡训练的时候, 不再是从主节点分发数据到各个从节点, 而是各个从节点自己从自己的硬盘上读取数据.

      当然了, 如果直接让各个节点自己读取自己的数据, 特别是在训练的时候经常是要打乱数据集进行训练的, 这样就会导致不同的节点加载的数据混乱, 所以这个时候使用DistributedSampler来创造一个sampler提供给DataLoader, sampler的作用自定义一个数据的编号, 然后让DataLoader按照这个编号来提取数据放入到模型中训练, 其中sampler参数和shuffle参数不能同时指定, 如果这个时候还想要可以随机的输入数据, 我们可以在DistributedSampler中指定shuffle参数, 具体的可以参考官网的api, 拉到最后就是DistributedSampler

    2.3.模型的处理

      模型的处理其实和上面的单机多卡没有多大区别, 还是下面的代码, 但是注意要提前想把模型加载到gpu, 然后才可以加载到DistributedDataParallel

    model = model.cuda()
    model = nn.parallel.DistributedDataParallel(model)
    

    2.4.模型的保存与加载

      这里引用pytorch官方教程的一段代码:

    def demo_checkpoint(rank, world_size):
        setup(rank, world_size)
    
        # setup devices for this process, rank 1 uses GPUs [0, 1, 2, 3] and
        # rank 2 uses GPUs [4, 5, 6, 7].
        n = torch.cuda.device_count() // world_size
        device_ids = list(range(rank * n, (rank + 1) * n))
    
        model = ToyModel().to(device_ids[0])
        # output_device defaults to device_ids[0]
        ddp_model = DDP(model, device_ids=device_ids)
    
        loss_fn = nn.MSELoss()
        optimizer = optim.SGD(ddp_model.parameters(), lr=0.001)
    
        CHECKPOINT_PATH = tempfile.gettempdir() + "/model.checkpoint"
        if rank == 0:
            # All processes should see same parameters as they all start from same
            # random parameters and gradients are synchronized in backward passes.
            # Therefore, saving it in one process is sufficient.
            torch.save(ddp_model.state_dict(), CHECKPOINT_PATH)
    
        # Use a barrier() to make sure that process 1 loads the model after process
        # 0 saves it.
        dist.barrier()
        # configure map_location properly
        rank0_devices = [x - rank * len(device_ids) for x in device_ids]
        device_pairs = zip(rank0_devices, device_ids)
        map_location = {'cuda:%d' % x: 'cuda:%d' % y for x, y in device_pairs}
        ddp_model.load_state_dict(
            torch.load(CHECKPOINT_PATH, map_location=map_location))
    
        optimizer.zero_grad()
        outputs = ddp_model(torch.randn(20, 10))
        labels = torch.randn(20, 5).to(device_ids[0])
        loss_fn = nn.MSELoss()
        loss_fn(outputs, labels).backward()
        optimizer.step()
    
        # Use a barrier() to make sure that all processes have finished reading the
        # checkpoint
        dist.barrier()
    
        if rank == 0:
            os.remove(CHECKPOINT_PATH)
    
        cleanup()
    

      我并没有实际操作, 因为多卡多GPU代码运行起来实在是难受, 一次实验可能就得好几分钟, 要是搞错一点可能就得好几十分钟都跑不起来, 最主要的是还要等能用的GPU. 不过看上面的代码, 最重要的实际是这句 dist.barrier(), 这个是来自torch.distributed.barrier(), 根据pytorch的官网的介绍, 这个函数的功能是同步所有的进程, 直到整组(也就是所有节点的所有GPU)到达这个函数的时候, 才会执行后面的代码, 看上面的代码, 可以看到, 在保存模型的时候, 是只找rank为0的点保存模型, 然后在加载模型的时候, 首先得让所有的节点同步一下, 然后给所有的节点加载上模型, 然后在进行下一步的时候, 还要同步一下, 保证所有的节点都读完了模型. 虽然我不清楚这样做的意义是什么, 但是官网说不这样做会导致一些问题, 我并没有实际操作, 不发表意见.

      至于保存模型的时候, 是保存哪些节点上面的模型, pytorch推荐的是rank=0的节点, 然后我看在论坛上, 有人也会保存所有节点的模型, 然后进行计算, 至于保存哪些, 我并没有做实验, 所以并不清楚到底哪种最好.

    展开全文
  • opencv训练传统分类
  • 1.概述在opencv中有两个类型的分类:opencv_haartraining和opencv_traincascade,后者是2.x版本中基于C++写的新版本的分类。二者最主要的区别是opencv_traincascade支持Haar和LBP。LBP在训练和检测方面要比Haar...
  • 用opencv训练分类

    千次阅读 2015-08-15 14:04:51
    注:本文转自西电之梦《采用opencv_cascadetrain进行训练的步骤及注意事项》,原文链接...OpenCV中有两个程序可以训练级联分类: opencv_haartraining 和opencv_traincascade。opencv_traincascade 是一个
  • 级联分类器训练过程(步骤)

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

    千次阅读 2020-04-27 13:11:39
    作者|OpenCV-Python Tutorials 编译|Vincent ...本文档概述了训练自己的弱分类的级联所需的功能。当前指南将逐步完成所有不同阶段:收集训练数据,准备训练数据并执行实际模型训练。 为了支持本...
  • opencv训练舌头分类

    千次阅读 热门讨论 2018-05-31 13:21:00
    2.使用文本编辑的替换功能,做一些替换工作  替换1:将绝对路径替换成相对路径 替换2:1代表个数,后四个分别对应left top width height 1 0 0 60 60 补充:1代表特征个数,0 0 代表训练特征在图片中...
  • 不得不说,这深度学习框架更新太快了尤其到了Keras2.0版本,快到Keras中文版好多都是错的,快到官方文档也有旧的没更新,前... 笔者先学的caffe,从使用来看,比caffe简单超级,非常好用,特别是重新训练一个模型,但
  • 先进的深度学习模型参数正以指数级速度增长:去年的GPT-2有大约7.5亿个参数,今年的GPT-3有1750亿... 分布式训练作业使您能够克服单GPU内存瓶颈,通过同时利用个GPU来开发更大,功能更强大的模型。 这篇文章是使用tor
  • 训练人脸分类  使用分类进行人脸检测 加载训练环境   训练过程主要依靠OpenCV自带的两个可执行程序opencv_createsamples.exe和opencv_haartraining.exe操作完成的。新建一个文件夹命名为cascadeTrain,将...
  • 训练级联分类

    千次阅读 2013-09-05 16:55:15
    除此之外OpenCV的data目录下有很多训练好的级联分类(如人脸,眼睛检测等),load进来就可以用,无需训练。官方例程中的objectdetection,facedetect等例子就是直接用了这些训练好的分类,如自带的face ...
  • 2. 训练分类 3. 使用训练好的分类进行目标检测   级联分类 源地址http://www.opencv.org.cn/opencvdoc/2.3.2/html/modules/objdetect/doc/cascade_classification.html 基于Haar特征的用于目标检测的级联...
  • 本系列文章旨在学习如何在opencv中基于haar-like特征训练自己的分类,并且用该分类用于模式识别。该过程大致可以分为一下几个大步骤: 1.准备训练样本图片,包括正例及反例样本 2.生成样本描述文件 3.训练...
  • 使用OpenCV训练级联分类

    千次阅读 2014-03-31 22:35:36
    虽然opencv已经自带了人脸、嘴巴、鼻子等分类,但工作中有时候由于项目需要,还是需要自己训练分类,最近我做了一下这方面工作,现在把训练分类的过程写出来,希望对打算做这方面工作的同学有帮助。...
  • 卷积神经网络训练花卉识别分类

    千次阅读 2020-03-27 12:24:52
      花卉分类使用语言:Python,使用深度学习框架:PyTorch,方法:训练卷积神经网络   关于PyTorch的基本用法可以参考博客:PyTorch笔记   Gitee仓库:花卉识别   Github仓库:花卉识别   Git相关用法...
  • PyTorch-训练可视化

    千次阅读 多人点赞 2020-01-30 20:51:44
    介绍使用TensorBoardX对PyTorch模型训练进行可视化监控。
  • 1. 搭建一个简单的图片分类,完成训练和测试 2. 转换pytorch的pth模型到ONNX格式,加载ONNX并测试 项目结构 images目录下存放训练和测试数据集,本例使用了kaggle竞赛的猫狗数据集,统一resize到了120*120...
  • PyTorch读取自己的本地图片数据集训练自编码

    万次阅读 热门讨论 2018-08-28 18:09:46
    下面我就以一些动漫头像为例,来说明怎样利用torch来进行训练和测试数据的预处理。下面是图片的格式: 上述图片一共有51223张,每个图片的大小为3*96*96。下载地址为:百度云链接 网络的基本结构是通过 卷积层*2...
  • Opencv 人脸检测训练分类,及其常见问题

    千次阅读 热门讨论 2017-05-18 13:14:27
    计算机开发视觉之训练分类 翻译时间:2017-5-18 理解概念,参数配置正确,是保证我们检测效率达到指标的前提条件。 正样本图像: 问:什么是正样本图像? 答:一张正样本图像应该包括我们要检测的目标对象,...
  • 9. 对于难例的处理, 所谓的难例就是第一次训练出的分类负样本原图中检测到的有行人的样本, 这些误报使得行人检测的分类不是那么准确, 所以可以将误报的矩形框保存为新的负样本, 对新的负样本进行二次训练, 实现...
  • 同一正样本目标的图像太会使局部特征过于明显,造成这个目标的训练过拟合,影响检测精度,不利于训练器泛化使用。   我们采集视频的人脸,先把视频解码后保存成jpg图片。   此处省略一万字… 创建样本:opencv...
  • 自编码(Autoencoder,AE)是一类在半监督学习和非监督学习中使用的人工神经网络,其功能是通过将输入信息作为学习目标,对输入信息进行表征学习(representation learning)。本文主要对MATLAB2020实现堆栈自编码...
  • OpenCV自学笔记13. 训练自己的分类

    千次阅读 2017-07-06 15:22:54
    训练自己的分类本小节使用的图片为: 最近在项目中遇到了一个问题,需要识别图像中的红色圆形。首先尝试了Hough圆形检测,详细请见这篇文章 http://blog.csdn.net/u010429424/article/details/72989870 ...
  • 但是,使用离线强化学习(RL)(智能体使用以前收集的数据开展训练,在试验和错误中学习的一种方法)来训练,即使是一个单一任务(例如抓取),也可能需要花费成千上万个机器人小时,此外还需要大量的工程来大规模实现...
  • 1、在做深度学习时候,数据量往往非常大,如果一次性加载到内存中,往往会出现OOM问题,为了解决这个问题,我们就不用model.fit()来训练,而用model.fit_generator()来训练。这样来数据就用生成(lazy calculate)的...
  • SVM+HOG:训练分类生成.xml文件

    千次阅读 2017-06-02 17:17:15
    是指利用第一次训练的分类在负样本原图(肯定没有人体)上进行行人检测时所有检测到的矩形框,这些矩形框区域很明显都是误报,把这些误报的矩形框保存为图片,加入到初始的负样本集合中,重新进行SVM的训练,可显著...
  • 计算机视觉—人脸识别(Hog特征+SVM分类) 一、SVM支持向量机 ...给定一组训练样例,每个训练样例被标记为属于两个类别中的一个或另一个,SVM训练算法建立一个模型,将新的例子分配给一个类别或...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 85,738
精华内容 34,295
关键字:

多功能训练器