精华内容
下载资源
问答
  • CvSVM
    2021-06-24 10:53:13

    编译错误

    In file included from /home/dong/color/color-detector/test.cpp:7:0:
    /home/dong/color/color-detector/colorDetector.cpp:142:35: error: 'CvSVM' has not been declared
     void trainSVM(vector dirs,CvSVM& SVM){
                                       ^
    /home/dong/color/color-detector/colorDetector.cpp: In function 'void trainSVM(std::vector >, int&)':
    /home/dong/color/color-detector/colorDetector.cpp:179:5: error: 'CvSVMParams' was not declared in this scope
         CvSVMParams params;
         ^
    /home/dong/color/color-detector/colorDetector.cpp:180:5: error: 'params' was not declared in this scope
         params.svm_type    = CvSVM::C_SVC;
         ^
    /home/dong/color/color-detector/colorDetector.cpp:180:26: error: 'CvSVM' has not been declared
         params.svm_type    = CvSVM::C_SVC;
                              ^
    /home/dong/color/color-detector/colorDetector.cpp:181:26: error: 'CvSVM' has not been declared
         params.kernel_type = CvSVM::POLY;
                              ^
    /home/dong/color/color-detector/colorDetector.cpp:187:9: error: request for member 'train' in 'SVM', which is of non-class type 'int'
         SVM.train(trainingData, labels, Mat(), Mat(), params);
             ^
    /home/dong/color/color-detector/colorDetector.cpp: At global scope:
    /home/dong/color/color-detector/colorDetector.cpp:191:25: error: 'CvSVM' has not been declared
     int testSVM(Mat testImg,CvSVM& SVM){
                             ^
    /home/dong/color/color-detector/colorDetector.cpp: In function 'int testSVM(cv::Mat, int&)':
    /home/dong/color/color-detector/colorDetector.cpp:194:20: error: request for member 'predict' in 'SVM', which is of non-class type 'int'
         response = SVM.predict(testImg);
                        ^
    /home/dong/color/color-detector/test.cpp: In function 'int main()':
    /home/dong/color/color-detector/test.cpp:18:5: error: 'CvSVM' was not declared in this scope
         CvSVM SVM;
         ^
    /home/dong/color/color-detector/test.cpp:19:5: error: 'SVM' was not declared in this scope
         SVM.load("../modell.xml");

    原因

    3.4版本OpenCV的分类器代码有很多的改动,命名方式也有所不同

    使用定义 cv::ml::SVM SVM;

        // Train the SVM
        Ptr svm = SVM::create();
        svm->setType(SVM::C_SVC);
        svm->setKernel(SVM::LINEAR);
        svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
        svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);

    2.4.9版本的分类器定义如下:

    // SVM model
    class CV_EXPORTS_W CvSVM : public CvStatModel
    {
    public:
        // SVM type
        enum { C_SVC=100, NU_SVC=101, ONE_CLASS=102, EPS_SVR=103, NU_SVR=104 };

        // SVM kernel type
        enum { LINEAR=0, POLY=1, RBF=2, SIGMOID=3 };

        // SVM params type
        enum { C=0, GAMMA=1, P=2, NU=3, COEF=4, DEGREE=5 };

    }

    使用定义    CvSVM SVM;

    更多相关内容
  • cvSVM

    2014-03-05 14:42:42
    param= CvSVMParams (CvSVM::C_SVC, CvSVM::RBF, 10.0, 8.0, 1.0, 10.0, 0.5, 0.1, NULL, criteria); svm.train(data, res, cv::Mat(), cv::Mat(), param); for (int i= 0; i; i++) { for (int j= 0; j; ...

    http://blog.csdn.net/firefight/article/details/6400060

     

    // svm.cpp : Defines the entry point for the console application.
    //
    #include "stdafx.h"
    #include <cv.h>
    #include <highgui.h>
    using namespace std;
    #include <ml.h>  
    
    void drawCross(cv::Mat &img, cv::Point center, cv::Scalar color)
    {
    	int col = center.x > 2 ? center.x : 2;
    	int row = center.y> 2 ? center.y : 2;
    
    	line(img, cv::Point(col -2, row - 2), cv::Point(col + 2, row + 2), color);  
    	line(img, cv::Point(col + 2, row - 2), cv::Point(col - 2, row + 2), color);  
    }
    
    int newSvmTest(int rows, int cols, int testCount,std::string dst)
    {
    	if(testCount > rows * cols)
    		return 0;
    	cv::Mat img = cv::Mat::zeros(rows, cols, CV_8UC3);
    	cv::Mat testPoint = cv::Mat::zeros(rows, cols, CV_8UC1);
    	cv::Mat data =cv::Mat::zeros(testCount, 2, CV_32FC1);
    	cv::Mat res = cv::Mat::zeros(testCount, 1, CV_32SC1);
    
    	//Create random test points
    	for (int i= 0; i< testCount; i++) 
    	{ 
    		int row = rand() % rows;
    		int col = rand() % cols;
    
    		if(testPoint.at<unsigned char>(row, col) == 0)
    		{
    			testPoint.at<unsigned char>(row, col) = 1;
    			data.at<float>(i, 0) = float (col) / cols; 
    			data.at<float>(i, 1) = float (row) / rows; 
    		}
    		else
    		{
    			i--;
    			continue;
    		}
    
    		if (row > ( 50 * cos(col * CV_PI/ 100) + 200) )
    		{ 
    			drawCross(img, cv::Point(col, row), CV_RGB(255, 0, 0));
    			res.at<unsigned int>(i, 0) = 1; 
    		} 
    		else 
    		{ 
    			if (col > 200) 
    			{ 
    				drawCross(img, cv::Point(col, row), CV_RGB(0, 255, 0));
    				res.at<unsigned int>(i, 0) = 2; 
    			} 
    			else 
    			{ 
    				drawCross(img, cv::Point(col, row), CV_RGB(0, 0, 255));
    				res.at<unsigned int>(i, 0) = 3; 
    			} 
    		} 
    
    	}
    
    	imshow(dst, img);
    	//
    	//	/START SVM TRAINNING//
    	CvSVM svm = CvSVM(); 
    	CvSVMParams param; 
    	CvTermCriteria criteria;
    
    	criteria= cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON); 
    	param= CvSVMParams (CvSVM::C_SVC, CvSVM::RBF, 10.0, 8.0, 1.0, 10.0, 0.5, 0.1, NULL, criteria); 
    
    	svm.train(data, res, cv::Mat(), cv::Mat(), param);
    
    	for (int i= 0; i< rows; i++) 
    	{ 
    		for (int j= 0; j< cols; j++) 
    		{ 
    			cv::Mat m = cv::Mat::zeros(1, 2, CV_32FC1);
    			m.at<float>(0,0) = float (j) / cols;
    			m.at<float>(0,1) = float (i) / rows;
    
    			float ret = 0.0; 
    			ret = svm.predict(m); 
    			cv::Scalar rcolor; 
    
    			switch ((int) ret) 
    			{ 
    			case 1: rcolor= CV_RGB(100, 0, 0); break; 
    			case 2: rcolor= CV_RGB(0, 100, 0); break; 
    			case 3: rcolor= CV_RGB(0, 0, 100); break; 
    			} 
    
    			line(img, cv::Point(j,i), cv::Point(j,i), rcolor);
    		} 
    	}
    
    	cvShowImage("2",&IplImage(img));
    	//	//Show support vectors
    	int sv_num= svm.get_support_vector_count(); 
    	for (int i= 0; i< sv_num; i++) 
    	{ 
    		const float* support = svm.get_support_vector(i); 
    		circle(img, cv::Point((int) (support[0] * cols), (int) (support[1] * rows)), 5, CV_RGB(200, 200, 200)); 
    	}
    
    	cvShowImage("3",&IplImage(img));
    	cv::waitKey(0);
    
    	return 0;
    }
    
    int main(int argc, char** argv)
    {
    	cv::namedWindow("a",CV_WINDOW_NORMAL);
    	cv::moveWindow("a", 10, 600);
    	return newSvmTest(400, 600, 100,"a");
    }


     

    展开全文
  • CvSVM::predict函数解析:不管是Mat接口还是CvMat接口最终都是通过指针的形式调用的,也就是最终都是调用的以下函数实现的 float CvSVM::predict( const float* row_sample, int row_len, bool returnDFVal ) const...
    CvSVM::predict函数解析:不管是Mat接口还是CvMat接口最终都是通过指针的形式调用的,也就是最终都是调用的以下函数实现的
    float CvSVM::predict( const float* row_sample, int row_len, bool returnDFVal ) const
    {
         // 首先确保创建了核函数输入了样本
        assert( kernel );
        assert( row_sample );
         // 样本的长度,也就是特征的维数必须匹配
        int var_count = get_var_count();
        assert( row_len == var_count );
        (void)row_len; // 不知道干啥的
         // 计算类别数目
        int class_count = class_labels ? class_labels->cols :
                      params.svm_type == ONE_CLASS ? 1 : 0;
        float result = 0;
        cv::AutoBuffer<float> _buffer(sv_total + (class_count+1)*2);
        float* buffer = _buffer;
         // 对于回归或者一类使用以下函数
        if( params.svm_type == EPS_SVR ||
            params.svm_type == NU_SVR ||
            params.svm_type == ONE_CLASS )
        {
            CvSVMDecisionFunc* df = (CvSVMDecisionFunc*)decision_func;
            int i, sv_count = df->sv_count;
            double sum = -df->rho;
            // 计算最优平面与当前样本点之间的距离
             kernel->calc( sv_count, var_count, (const float**)sv, row_sample, buffer );
            for( i = 0; i < sv_count; i++ )
                sum += buffer[i]*df->alpha[i];
            result = params.svm_type == ONE_CLASS ? (float)(sum > 0) : (float)sum;
        }
         // 对于分类问题使用以下方法
        else if( params.svm_type == C_SVC ||
                 params.svm_type == NU_SVC )
        {
            CvSVMDecisionFunc* df = (CvSVMDecisionFunc*)decision_func;
            int* vote = (int*)(buffer + sv_total);
            int i, j, k;
            memset( vote, 0, class_count*sizeof(vote[0]));
             // 计算样本点到所有支持向量之间的距离,sum(xi-yi),其中xi表示样本点,yi表示支持向量,i=1:N,N表示一个样本的特征维度
             kernel->calc( sv_total, var_count, (const float**)sv, row_sample, buffer );
            double sum = 0.;
            // 对于二分类问题以下函数只执行一遍
            for( i = 0; i < class_count; i++ )
            {
                for( j = i+1; j < class_count; j++, df++ )
                {
                     // 获取样本点到最优分界面的距离:buffer中存放测试样本与每个支持向量距离度量值
                    sum = -df->rho;
                    int sv_count = df->sv_count;
                    for( k = 0; k < sv_count; k++ )
                        sum += df->alpha[k]*buffer[df->sv_index[k]];  // sv_index存储的是支持向量index,对于2分类实际sv_index[k]=k
                    // sum大于0表示属于第一个类别,也就是类别标记较小的那个类别,对于二分类问题也就是负样本
                    vote[sum > 0 ? i : j]++;
                }
            }
             // 统计每个类别的投票次数, 注意大于0投票给了0也就是0为负样本,如果一次也没有投票的话,默认输出的也是负样本
            for( i = 1, k = 0; i < class_count; i++ )
            {
                if( vote[i] > vote[k] )
                    k = i;
            }
             // returnDFVal只对于2分类问题有效,sum大于0表示属于类别标记较小的那个类别也就是-1,sum小于0表示属于类别标记较大的那个类别也就是+1
            result = returnDFVal && class_count == 2 ? (float)sum : (float)(class_labels->data.i[k]);
        }
        else
            CV_Error( CV_StsBadArg, "INTERNAL ERROR: Unknown SVM type, "
                                    "the SVM structure is probably corrupted" );
        return result;
    }

    kernel->calc( sv_total, var_count, (const float**)sv, row_sample, buffer ); 
    计算样本点到支持向量点间的距离,结果存储到buffer中,以线性核函数为例

    从上面的分析可以看出,如果不更改rho或者alpha的符号,计算的是-rho+w*x的结果,大于0表示负样本,小于0表示正样本;因此在HOGDescriptor中需要将alpha更改符号,直接保存rho即可,这样给出的结果rho-alpha*x,大于0表示正样本!
    w=alpha*sv; alpha中存放每个支持向量的权重,sv表示每个支持向量,w为加权后的支持向量

    void CvSVMKernel::calc( int vcount, int var_count, const float** vecs,
                            const float* another, Qfloat* results )
    {
        const Qfloat max_val = (Qfloat)(FLT_MAX*1e-3);
        int j;
         // 对于核函数为Liner时调用线性核函数进行计算
         (this->*calc_func)( vcount, var_count, vecs, another, results );
        // 检查是否越界
        for( j = 0; j < vcount; j++ )
        {
            if( results[j] > max_val )
                results[j] = max_val;
        }
    }
    线性核函数又调用non_rbf_base核函数进行计算
    void CvSVMKernel::calc_linear( int vcount, int var_count, const float** vecs,
                                   const float* another, Qfloat* results )
    {
        calc_non_rbf_base( vcount, var_count, vecs, another, results, 1, 0 );
    }
    vcount表示支持向量的个数,也就是位于正负样本分界面上的正负样本总数
    var_count表示样本的特征维度
    vecs表示支持向量,也就是位于正负样本分解面上的正负样本
    another表示测试样本
    result表示对于每个支持向量的累加结果值
    void CvSVMKernel::calc_non_rbf_base( int vcount, int var_count, const float** vecs,
                                         const float* another, Qfloat* results,
                                         double alpha, double beta )
    {
        int j, k;
         // 对于每一个支持向量,或者每一个位于分界面的训练样本
        for( j = 0; j < vcount; j++ )
        {
             // 获取第j个支持向量或者说第j个样本
            const float* sample = vecs[j];
            double s = 0;
             // 特征维度大于4的时候进行优化
            for( k = 0; k <= var_count - 4; k += 4 )
                s += sample[k]*another[k] + sample[k+1]*another[k+1] +
                     sample[k+2]*another[k+2] + sample[k+3]*another[k+3];
             // 计算其余的维度
            for( ; k < var_count; k++ )
                s += sample[k]*another[k];
             // 计算测试样本与第j个样本之间的距离
            results[j] = (Qfloat)(s*alpha + beta); // 注意这里的alpha和beta为每个支持向量的权重,对于线性核函数而言alpha=1,beta=0可以从 calc_linear函数看出
        }
    }
    // RBF核函数,遵循RBF核函数公式
    void CvSVMKernel::calc_rbf( int vcount, int var_count, const float** vecs,
                                const float* another, Qfloat* results )
    {
        CvMat R = cvMat( 1, vcount, QFLOAT_TYPE, results );
        double gamma = -params->gamma;
        int j, k;
         // vcount=sv_count
        for( j = 0; j < vcount; j++ )
        {
            const float* sample = vecs[j];
            double s = 0;
            // var_count=feature_num
            for( k = 0; k <= var_count - 4; k += 4 )
            {
                double t0 = sample[k] - another[k];
                double t1 = sample[k+1] - another[k+1];

                s += t0*t0 + t1*t1;

                t0 = sample[k+2] - another[k+2];
                t1 = sample[k+3] - another[k+3];

                s += t0*t0 + t1*t1;
            }

            for( ; k < var_count; k++ )
            {
                double t0 = sample[k] - another[k];
                s += t0*t0;
            }
            results[j] = (Qfloat)(s*gamma);
        }

        if( vcount > 0 )
            cvExp( &R, &R );
    }

    // 根据交叉次数自动训练函数,CvParamGrid为训练参数构造函数,其包含三个参数(min_val,max_val,step)
    // Param Grid的检查函数,最大值不小于最小值,最小值不小于DBL_EPSILON,step不小于1(应该是不小于等于1)
    bool CvParamGrid::check() const
    {
        bool ok = false;

        CV_FUNCNAME( "CvParamGrid::check" );
        __BEGIN__;

        if( min_val > max_val )
            CV_ERROR( CV_StsBadArg, "Lower bound of the grid must be less then the upper one" );
        if( min_val < DBL_EPSILON )
            CV_ERROR( CV_StsBadArg, "Lower bound of the grid must be positive" );
        if( step < 1. + FLT_EPSILON )
            CV_ERROR( CV_StsBadArg, "Grid step must greater then 1" );

        ok = true;

        __END__;

        return ok;
    }

    如果不确定参数的值的范围可以通过以下函数获得,当然也可以通过一次次实验不断调整,最后得到一个大概的范围后采用train_auto函数进行训练
    CvParamGrid CvSVM::get_default_grid( int param_id )
    {
        CvParamGrid grid;
        if( param_id == CvSVM::C )
        {
            grid.min_val = 0.1;
            grid.max_val = 500;
            grid.step = 5; // total iterations = 5
        }
        else if( param_id == CvSVM::GAMMA )
        {
            grid.min_val = 1e-5;
            grid.max_val = 0.6;
            grid.step = 15; // total iterations = 4
        }
        else if( param_id == CvSVM::P )
        {
            grid.min_val = 0.01;
            grid.max_val = 100;
            grid.step = 7; // total iterations = 4
        }
        else if( param_id == CvSVM::NU )
        {
            grid.min_val = 0.01;
            grid.max_val = 0.2;
            grid.step = 3; // total iterations = 3
        }
        else if( param_id == CvSVM::COEF )
        {
            grid.min_val = 0.1;
            grid.max_val = 300;
            grid.step = 14; // total iterations = 3
        }
        else if( param_id == CvSVM::DEGREE )
        {
            grid.min_val = 0.01;
            grid.max_val = 4;
            grid.step = 7; // total iterations = 3
        }
        else
            cvError( CV_StsBadArg, "CvSVM::get_default_grid", "Invalid type of parameter "
                "(use one of CvSVM::C, CvSVM::GAMMA et al.)", __FILE__, __LINE__ );
        return grid;
    }

    bool CvSVM::train_auto( const CvMat* _train_data, const CvMat* _responses,
        const CvMat* _var_idx, const CvMat* _sample_idx, CvSVMParams _params, int k_fold,
        CvParamGrid C_grid, CvParamGrid gamma_grid, CvParamGrid p_grid,
        CvParamGrid nu_grid, CvParamGrid coef_grid, CvParamGrid degree_grid,
        bool balanced)
    {
        bool ok = false;
        CvMat* responses = 0;
        CvMat* responses_local = 0;
        CvMemStorage* temp_storage = 0;
        const float** samples = 0;
        const float** samples_local = 0;

        CV_FUNCNAME( "CvSVM::train_auto" );
        __BEGIN__;

        int svm_type, sample_count, var_count, sample_size;
        int block_size = 1 << 16;
        double* alpha;
        RNG* rng = &theRNG();

        // all steps are logarithmic and must be > 1
         // 步长都必须大于1,因为等于1的时候会造成死循环!,默认step=10
        double degree_step = 10, g_step = 10, coef_step = 10, C_step = 10, nu_step = 10, p_step = 10;
        double gamma = 0, curr_c = 0, degree = 0, coef = 0, p = 0, nu = 0;
        double best_degree = 0, best_gamma = 0, best_coef = 0, best_C = 0, best_nu = 0, best_p = 0;
        float min_error = FLT_MAX, error;
        
         // SVMType为ONE_CLASS的时候不能进行自动训练
        if( _params.svm_type == CvSVM::ONE_CLASS )
        {
            if(!train( _train_data, _responses, _var_idx, _sample_idx, _params ))
                EXIT;
            return true;
        }

        clear();

         // 选择的交叉验证层数必须大于等于2,等于2的时候就是使用一个训练另外一个测试,训练两次,测试两次
        // 等于10表示训练10次,测试10次,选择一组测试其余9组训练
        if( k_fold < 2 )
            CV_ERROR( CV_StsBadArg, "Parameter <k_fold> must be > 1" );

        CV_CALL(set_params( _params ));
        svm_type = _params.svm_type;

        // All the parameters except, possibly, <coef0> are positive.
        // <coef0> is nonnegative
         // 检查各个参数的值是否满足要求,这是第一步检查(步长不能小于1),后面根据SVM类型与Kernel类型还会进行二次检查
        if( C_grid.step <= 1 )
        {
            C_grid.min_val = C_grid.max_val = params.C;
            C_grid.step = 10;
        }
        else
            CV_CALL(C_grid.check());

        if( gamma_grid.step <= 1 )
        {
            gamma_grid.min_val = gamma_grid.max_val = params.gamma;
            gamma_grid.step = 10;
        }
        else
            CV_CALL(gamma_grid.check());

        if( p_grid.step <= 1 )
        {
            p_grid.min_val = p_grid.max_val = params.p;
            p_grid.step = 10;
        }
        else
            CV_CALL(p_grid.check());

        if( nu_grid.step <= 1 )
        {
            nu_grid.min_val = nu_grid.max_val = params.nu;
            nu_grid.step = 10;
        }
        else
            CV_CALL(nu_grid.check());

        if( coef_grid.step <= 1 )
        {
            coef_grid.min_val = coef_grid.max_val = params.coef0;
            coef_grid.step = 10;
        }
        else
            CV_CALL(coef_grid.check());

        if( degree_grid.step <= 1 )
        {
            degree_grid.min_val = degree_grid.max_val = params.degree;
            degree_grid.step = 10;
        }
        else
            CV_CALL(degree_grid.check());

        // these parameters are not used:
         // 二次检查参数的值,根据核函数类型与SVM类型优化参数
        if( params.kernel_type != CvSVM::POLY )
            degree_grid.min_val = degree_grid.max_val = params.degree;
        if( params.kernel_type == CvSVM::LINEAR )
            gamma_grid.min_val = gamma_grid.max_val = params.gamma;
        if( params.kernel_type != CvSVM::POLY && params.kernel_type != CvSVM::SIGMOID )
            coef_grid.min_val = coef_grid.max_val = params.coef0;
        if( svm_type == CvSVM::NU_SVC || svm_type == CvSVM::ONE_CLASS )
            C_grid.min_val = C_grid.max_val = params.C;
        if( svm_type == CvSVM::C_SVC || svm_type == CvSVM::EPS_SVR )
            nu_grid.min_val = nu_grid.max_val = params.nu;
        if( svm_type != CvSVM::EPS_SVR )
            p_grid.min_val = p_grid.max_val = params.p;

        CV_ASSERT( g_step > 1 && degree_step > 1 && coef_step > 1);
        CV_ASSERT( p_step > 1 && C_step > 1 && nu_step > 1 );

         /* Prepare training data and related parameters */
        // 实现数据的转存,放到指针中
        CV_CALL(cvPrepareTrainData( "CvSVM::train_auto", _train_data, CV_ROW_SAMPLE,
                                     svm_type != CvSVM::ONE_CLASS ? _responses : 0,
                                     svm_type == CvSVM::C_SVC ||
                                     svm_type == CvSVM::NU_SVC ? CV_VAR_CATEGORICAL :
                                     CV_VAR_ORDERED, _var_idx, _sample_idx,
                                     false, &samples, &sample_count, &var_count, &var_all,
                                     &responses, &class_labels, &var_idx ));

        sample_size = var_count*sizeof(samples[0][0]);

        // make the storage block size large enough to fit all
        // the temporary vectors and output support vectors.
        block_size = MAX( block_size, sample_count*(int)sizeof(CvSVMKernelRow));
        block_size = MAX( block_size, sample_count*2*(int)sizeof(double) + 1024 );
        block_size = MAX( block_size, sample_size*2 + 1024 );

        CV_CALL( storage = cvCreateMemStorage(block_size + sizeof(CvMemBlock) + sizeof(CvSeqBlock)));
        CV_CALL(temp_storage = cvCreateChildMemStorage(storage));
        CV_CALL(alpha = (double*)cvMemStorageAlloc(temp_storage, sample_count*sizeof(double)));

        create_kernel();
        create_solver();

        {
        const int testset_size = sample_count/k_fold;  // 每组测试集合大小
        const int trainset_size = sample_count - testset_size;  // 每组训练集合大小
        const int last_testset_size = sample_count - testset_size*(k_fold-1);  // 最后一组测试集合大小,实际为testset_size
        const int last_trainset_size = sample_count - last_testset_size;  // 最后一组训练集合大小,实际trainset_size 
        const bool is_regression = (svm_type == EPS_SVR) || (svm_type == NU_SVR);

        size_t resp_elem_size = CV_ELEM_SIZE(responses->type);
        size_t size = 2*last_trainset_size*sizeof(samples[0]);

        samples_local = (const float**) cvAlloc( size );
        memset( samples_local, 0, size );

        responses_local = cvCreateMat( 1, trainset_size, CV_MAT_TYPE(responses->type) );
        cvZero( responses_local );

        // randomly permute samples and responses
         // 随机变更样本和标签的顺序为了获取分组
        for(int i = 0; i < sample_count; i++ )
        {
            int i1 = (*rng)(sample_count);
            int i2 = (*rng)(sample_count);
            const float* temp;
            float t;
            int y;

            CV_SWAP( samples[i1], samples[i2], temp );
            if( is_regression )
                CV_SWAP( responses->data.fl[i1], responses->data.fl[i2], t );
            else
                CV_SWAP( responses->data.i[i1], responses->data.i[i2], y );
        }
         // 如果是分类问题,并且是2分类,并且需要均衡化分组
        if (!is_regression && class_labels->cols==2 && balanced)
        {
             // count class samples
            // responses中存放0和1,class_label中存放为0和1就对了,因此注意负样本的标签为0,正样本的标签为1!!
            int num_0=0,num_1=0;
            for (int i=0; i<sample_count; ++i)
            {
                if (responses->data.i[i]==class_labels->data.i[0])
                    ++num_0;
                else
                    ++num_1;
            }
             // 哪个类别是较大的
            int label_smallest_class;
            int label_biggest_class;
            if (num_0 < num_1)
            {
                label_biggest_class = class_labels->data.i[1];
                label_smallest_class = class_labels->data.i[0];
            }
            else
            {
                label_biggest_class = class_labels->data.i[0];
                label_smallest_class = class_labels->data.i[1];
                int y;
                CV_SWAP(num_0,num_1,y);
            }
            const double class_ratio = (double) num_0/sample_count;
            // calculate class ratio of each fold
            indexedratio *ratios=0;
            ratios = (indexedratio*) cvAlloc(k_fold*sizeof(*ratios));
            for (int k=0, i_begin=0; k<k_fold; ++k, i_begin+=testset_size)
            {
                int count0=0;
                int count1=0;
                int i_end = i_begin + (k<k_fold-1 ? testset_size : last_testset_size);
                for (int i=i_begin; i<i_end; ++i)
                {
                    if (responses->data.i[i]==label_smallest_class)
                        ++count0;
                    else
                        ++count1;
                }
                ratios[k].ind = k;
                ratios[k].count_smallest = count0;
                ratios[k].count_biggest = count1;
                ratios[k].eval();
            }
            // initial distance
            qsort(ratios, k_fold, sizeof(ratios[0]), icvCmpIndexedratio);
            double old_dist = 0.0;
            for (int k=0; k<k_fold; ++k)
                old_dist += abs(ratios[k].val-class_ratio);
            double new_dist = 1.0;
            // iterate to make the folds more balanced
            while (new_dist > 0.0)
            {
                if (ratios[0].count_biggest==0 || ratios[k_fold-1].count_smallest==0)
                    break; // we are not able to swap samples anymore
                // what if we swap the samples, calculate the new distance
                ratios[0].count_smallest++;
                ratios[0].count_biggest--;
                ratios[0].eval();
                ratios[k_fold-1].count_smallest--;
                ratios[k_fold-1].count_biggest++;
                ratios[k_fold-1].eval();
                qsort(ratios, k_fold, sizeof(ratios[0]), icvCmpIndexedratio);
                new_dist = 0.0;
                for (int k=0; k<k_fold; ++k)
                    new_dist += abs(ratios[k].val-class_ratio);
                if (new_dist < old_dist)
                {
                    // swapping really improves, so swap the samples
                    // index of the biggest_class sample from the minimum ratio fold
                    int i1 = ratios[0].ind * testset_size;
                    for ( ; i1<sample_count; ++i1)
                    {
                        if (responses->data.i[i1]==label_biggest_class)
                            break;
                    }
                    // index of the smallest_class sample from the maximum ratio fold
                    int i2 = ratios[k_fold-1].ind * testset_size;
                    for ( ; i2<sample_count; ++i2)
                    {
                        if (responses->data.i[i2]==label_smallest_class)
                            break;
                    }
                    // swap
                    const float* temp;
                    int y;
                    CV_SWAP( samples[i1], samples[i2], temp );
                    CV_SWAP( responses->data.i[i1], responses->data.i[i2], y );
                    old_dist = new_dist;
                }
                else
                    break; // does not improve, so break the loop
            }
            cvFree(&ratios);
        }

         // 遍历每个参数进行测试,将最小错误率的检测结果保存下来
        // 在自动话训练时是按照如下方式进行的,当然针对不同的核函数与不同的SVM类型进行了优化
        while(cur_val=min_val; cur_val<=max_val; cur_val*=step)
        int* cls_lbls = class_labels ? class_labels->data.i : 0;
        curr_c = C_grid.min_val;
        do
        {
          params.C = curr_c;
          gamma = gamma_grid.min_val;
          do
          {
            params.gamma = gamma;
            p = p_grid.min_val;
            do
            {
              params.p = p;
              nu = nu_grid.min_val;
              do
              {
                params.nu = nu;
                coef = coef_grid.min_val;
                do
                {
                  params.coef0 = coef;
                  degree = degree_grid.min_val;
                  do
                  {
                    params.degree = degree;

                    float** test_samples_ptr = (float**)samples;
                    uchar* true_resp = responses->data.ptr;
                    int test_size = testset_size;
                    int train_size = trainset_size;

                    // 根据每轮训练中最小错误率保存结果
                    // 一组测试,其余组用于训练,根据总的错误率作为最佳结果
                    error = 0;
                    for(int k = 0; k < k_fold; k++ )
                    {
                         // 分段拷贝训练样本与训练样本标签
                        memcpy( samples_local, samples, sizeof(samples[0])*test_size*k );
                        memcpy( samples_local + test_size*k, test_samples_ptr + test_size,
                            sizeof(samples[0])*(sample_count - testset_size*(k+1)) );

                        memcpy( responses_local->data.ptr, responses->data.ptr, resp_elem_size*test_size*k );
                        memcpy( responses_local->data.ptr + resp_elem_size*test_size*k,
                            true_resp + resp_elem_size*test_size,
                            resp_elem_size*(sample_count - testset_size*(k+1)) );

                        if( k == k_fold - 1 )
                        {
                            test_size = last_testset_size;
                            train_size = last_trainset_size;
                            responses_local->cols = last_trainset_size;
                        }

                         // Train SVM on <train_size> samples
                        // 分组测试
                        if( !do_train( svm_type, train_size, var_count,
                            (const float**)samples_local, responses_local, temp_storage, alpha ) )
                            EXIT;

                         // Compute test set error on <test_size> samples
                        // 统计错误样本个数
                        for(int i = 0; i < test_size; i++, true_resp += resp_elem_size, test_samples_ptr++ )
                        {
                            float resp = predict( *test_samples_ptr, var_count );
                            error += is_regression ? powf( resp - *(float*)true_resp, 2 )
                                : ((int)resp != cls_lbls[*(int*)true_resp]);
                        }
                    }
                     // 保存具有最小错误样本个数的训练参数
                    if( min_error > error )
                    {
                        min_error   = error;
                        best_degree = degree;
                        best_gamma  = gamma;
                        best_coef   = coef;
                        best_C      = curr_c;
                        best_nu     = nu;
                        best_p      = p;
                    }
                    degree *= degree_grid.step;
                  }
                  while( degree < degree_grid.max_val );
                  coef *= coef_grid.step;
                }
                while( coef < coef_grid.max_val );
                nu *= nu_grid.step;
              }
              while( nu < nu_grid.max_val );
              p *= p_grid.step;
            }
            while( p < p_grid.max_val );
            gamma *= gamma_grid.step;
          }
          while( gamma < gamma_grid.max_val );
          curr_c *= C_grid.step;
        }
        while( curr_c < C_grid.max_val );
        }
         // 计算错误率
        min_error /= (float) sample_count;

        params.C      = best_C;
        params.nu     = best_nu;
        params.p      = best_p;
        params.gamma  = best_gamma;
        params.degree = best_degree;
        params.coef0  = best_coef;

         // 根据最佳的参数做一次最后的训练,因此分组测试的目的是为了寻找最佳参数
        CV_CALL(ok = do_train( svm_type, sample_count, var_count, samples, responses, temp_storage, alpha ));

        __END__;

        delete solver;
        solver = 0;
        cvReleaseMemStorage( &temp_storage );
        cvReleaseMat( &responses );
        cvReleaseMat( &responses_local );
        cvFree( &samples );
        cvFree( &samples_local );

        if( cvGetErrStatus() < 0 || !ok )
            clear();

        return ok;
    }
    总结:
    1) predict函数首先计算测试样本到每个支持向量sv[j]之间的距离,然后乘以每个支持向量的权重alpha[i]结果得到一个数,该值减去rho,如果大于0表示为负样本,否则为正样本
    2) 对于二分类使用balanced=true的train_auto而言,负样本标签必须为0,这样就可以通过统计正负样本的比例而得到一个较好的平衡结果

    展开全文
  • OpenCV中的CvSVM使用方法

    千次阅读 2018-05-25 10:34:57
    转自:https://blog.csdn.net/armily/article/details/8483098描述:opecv的线性...2)设置SVM参数利用CvSVMParams类实现类内的成员变量的表示3)训练SVM调用CvSVM::train函数建立SVM模型,第一个参数为训练数据...

    转自:https://blog.csdn.net/armily/article/details/8483098

    描述:opecv的线性分类器SVM使用简洁高效,这里列出其使用方法

    1)设置训练样本集需要两组数据,一组是数据的类别,一组是数据的向量信息。

    2)设置SVM参数利用CvSVMParams类实现类内的成员变量的表示

    3)训练SVM调用CvSVM::train函数建立SVM模型,第一个参数为训练数据,第二个参数为分类结果,最后一个参数即CvSVMParams

    4)用这个SVM进行分类调用函数CvSVM::predict实现分类

    5)获得支持向量除了分类,也可以得到SVM的支持向量,调用函数CvSVM::get_support_vector_count获得支持向量的个数,CvSVM::get_support_vector获得对应的索引编号的支持向量。

    小例子如下:

    int main( int argc, char** argv )   
      {       
          bool  train_update = false;       
          int   train_sample_count = 100;      
          int   train_sample_size = 10;    //维度       
          CvMat  *data_mat = NULL;   //要训练的数据       
          CvMat  *class_mat = NULL;  //数据的类别     
         
          class_mat = cvCreateMat(train_sample_count, 1, CV_32FC1);       
          data_mat = cvCreateMat(train_sample_count, train_sample_size, CV_32FC1);    
       
          for(i = 0; i < train_sample_count; i++)       
         {           
              class_mat->data.fl[ i] = value;    //assign the class or regression value           
              for(j = 0; j < train_sample_size; j++)           
                 {               
                       data_mat->data.fl[i*train_sample_size+ j] = val;  //assing data sample value           
                 }       
         }    
              
         CvSVMParams svm_param;       
         svm_param.svm_type = CvSVM::NU_SVR;       
         svm_param.kernel_type = CvSVM::RBF;       
         svm_param.gamma = 1./train_sample_size;       
         svm_param.nu = 0.5;       
         svm_param.C = 8;       
         svm_param.term_crit.epsilon = 0.001;       
         svm_param.term_crit.max_iter = 50;       
         svm_param.term_crit.type = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS;         
       
         CvSVM *tSvm = new CvSVM();       
         tSvm->train(data_mat, class_mat, 0, 0, svm_param);      
         tSvm->save("filename.xml", 0);     
       
         //For prediction       
         CvSVM *pSvm = new CvSVM();       
         pSvm->load("filename.xml", 0);         
         CvMat *sample = cvCreateMat(1, train_sample_size, CV_32FC1);       
         for(i = 0; i < train_sample_size; i++)       
        {           
             sample->data.fl[i] = val ;//assign value       
        }    
           
        float pred = pSvm->predict(sample);       
        printf("n %.3f", pred);   
    }  

    附加:libSVM的使用总体思路:

    1、提取正负样本hog特征

    2、投入svm分类器训练,得到model

    3、由model生成检测子

    4、利用检测子检测负样本,得到hardexample

    5、提取hardexample的hog特征并结合第一步中的特征一起投入训练,得到最终检测子。


    展开全文
  • 【opencv】支持向量机CvSVM分类

    千次阅读 2016-05-11 16:03:46
    C++: float CvSVM::predict(const CvMat* sample, bool returnDFVal=false ) const C++: float CvSVM::predict(const CvMat* samples, CvMat* results) const 参数 sample – 需要预测的输入样本。 samples ...
  • cvSVM及trainSVM参数

    2014-05-07 10:08:23
    CvSVM   支持矢量机 class CvSVM : public CvStatModel //继承自基类CvStatModel { public:  // SVM type  enum { C_SVC=100, NU_SVC=101, ONE_CLASS=102, EPS_SVR=103, NU_SVR=104 };//SVC...
  • cvSVM及trainSVM参数详解

    万次阅读 2014-03-18 15:39:53
    CvSVM   支持矢量机 class CvSVM : public CvStatModel //继承自基类CvStatModel { public:  // SVM type  enum { C_SVC=100, NU_SVC=101, ONE_CLASS=102, EPS_SVR=103, NU_SVR=104 };//SVC...
  • CvSVM svmClassifier(trainingData, classes, Mat(), Mat(), SVM_params); cout !" ; FileStorage fsTo("..\\out\\svm.xml", cv::FileStorage::WRITE);//训练数据存档 svmClassifier.write(*fsTo, "svm"); ...
  • ![图片说明](https://img-ask.csdn.net/upload/201507/22/1437577564_815702.png) “CvSVM”: 未声明的标识符
  • CVSVM 还没看太懂

    千次阅读 2015-04-10 13:49:20
    params.kernel_type = CvSVM::LINEAR; params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6); // Train the SVM CvSVM SVM; SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params); Vec...
  • CvSVM::EPS_SVR train_auto assertion sv_count != 0 failed原因:  出现这种情况,一般表示你的训练集和结果数据集,没有输入到你的Mat结构中,如果用Mat初始化方法没法进行正确的输入, 可以使用数组循环的...
  • CvSVM的依赖项则为ml.lib 在版本2.0的openCV中,即为ml200d.lib, 在版本2.1的openCV中,即为ml210d.lib   HOGDescriptor 的依赖项则为cvaux210d.lib 为项目的Debug配置增加依赖的库: cv210d.lib cvaux...
  • I am using the SVM implementation of OpenCV (based on LibSVM) on iOS. Is it possible to obtain the weight vector after training?Thank you!解决方案After dealing with it I have been able to obtain the ...
  • CvSVM的用法

    万次阅读 2012-09-03 17:02:43
    #include "cv.h" #include "highgui.h" ... CvSVM svm=CvSVM(); svm.train(&matd,&matl,NULL,NULL); float f = svm.predict(&mtestd); printf("f: %d\n", int(f)); return 0; }  
  • 关于SVM简介见上篇《libsvm支持向量机应用编程》,Opencv的SVM是在...CvSVM参数跟libsvm的参数基本一样,不过没有libsvm那么多,很多东西简化了。 SVM类型: C_SVC:C类支持向量分类机。n类分组(n≥2),允许用异
  • Opencv中SVM的使用问题

    千次阅读 2018-08-20 14:57:20
    CvSVM svm;// = CvSVM();//新建一个SVM CvSVMParams param;//这里是参数 CvTermCriteria criteria; criteria = cvTermCriteria( CV_TERMCRIT_EPS, 1000, FLT_EPS...
  • grid(CvSVM::C), CvParamGrid gammaGrid=CvSVM::get_default_grid(CvSVM::GAMMA), CvParamGrid pGrid=CvSVM::get_default_grid(CvSVM::P), CvParamGrid nuGrid=CvSVM::get_default_grid(CvSVM::NU), CvParamGrid ...
  • 1、链接错误如下: 2、错误原因 opencv的工程属性中没有添加机器学习库。 3、解决办法 添加依赖库:opencv_ml231.lib,如下截图:
  • 存储好点的信息,下面就需要进行训练了,训练需要实例化向量机,因此创建CvSVM类型的对象SVM,CVSVM的训练方法为: CvSVM::train(const CvMat* trainData, const CvMat* responses, const CvMat* varIdx=0, ...
  • opencv+svm实现图像分类代码+训练图片,新建opencv工程,导入两个文件就可以了。
  • OpenCV之CvANN_MLP和CvSVM测试

    千次阅读 2013-10-17 17:41:19
    params.kernel_type = CvSVM::LINEAR; params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6); // step 3: CvSVM SVM; SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params); ...
  • 5)获取支持向量(CvSVM::get_support_vector_count,CvSVM::get_support_vector ) 开发环境: VS2012 + OpenGl(GLUT3.7) + OpenCv2.4.9 + Halcon10.0 时间地点: 陕西师范大学 文津楼----2017.3.2 作 者: ...
  • OpenCV 2.4.9 支持向量机(SVM)说明

    千次阅读 2017-06-14 21:29:32
    svm_type(CvSVM::C_SVC), kernel_type(CvSVM::RBF), degree( 0 ), gamma( 1 ), coef0( 0 ), C( 1 ), nu( 0 ), p( 0 ), class_weights( 0 ) { term_crit = cvTermCriteria( CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1000...
  •  CvSVM::ONE_CLASS 单分类器,所有的训练数据提取自同一个类里,然后SVM建立了一个分界线以分割该类在特征空间中所占区域和其它类在特征空间中所占区域。  CvSVM::EPS_SVR \epsilon类支持向量回归机。训练集中的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,134
精华内容 453
关键字:

CvSVM