• 【EmguCV】C#实现HOG与SVM的几个问题


    关于SVM中的alpha、rho向量

    由于EmguCV封装的更加彻底,在C#中并不能跟C++一样通过重载获得这两个中间变量

    //继承自CvSVM的类,因为生成setSVMDetector()中用到的检测子参数时,需要用到训练好的SVM的decision_func参数,  
    //但通过查看CvSVM源码可知decision_func参数是protected类型变量,无法直接访问到,只能继承之后通过函数访问  
    class MySVM : public CvSVM  
    {  
    public:  
        //获得SVM的决策函数中的alpha数组  
        double * get_alpha_vector()  
        {  
            return this->decision_func->alpha;  
        }  
      
        //获得SVM的决策函数中的rho参数,即偏移量  
        float get_rho()  
        {  
            return this->decision_func->rho;  
        }  
    };

    见C++实例:训练SVM分类器进行HOG行人检测 http://blog.csdn.net/pb09013037/article/details/41256945


    为了获取这两个变量用于自定义HOG检测子,暂时想到的几种办法:

    1、C#读取生成的XML文件

    分类器训练好后一般需要进行保存,方便直接预测

    SVM svm = new SVM();
    bool trained = svm.Train(my_train.sampleFeatureMat, my_train.sampleLabelMat, null, null, p);
    svm.Save(@"../HOG_SVM.xml");

    这里给出我的C#提取SVM参数方式:

    (只用于提取训练目标为1与-1两类的XML文件,如果类型大于2,则有多个rho与alpha数组,需要进一步组合)

    using System;
    using System.Text;
    using System.Xml;
    using System.IO;
    
    
    namespace HOG_SVM
    {
        class GetData
        {
            public double[] alpha;
            public double rho;
    
            XmlDocument doc;        
            StreamReader sr;
            int sv_count;
            string alpha_str;
    
            public GetData()
            {
                doc = new XmlDocument();
                doc.Load(Form1.LOAD_PATH);
                XmlNode nodes = doc.DocumentElement;
                get_rho(nodes);
                getAlpha_str(nodes);
                getSv_count(nodes);
                getAlpha(); 
            }
    
            public void get_rho(XmlNode nodes)
            {
                if (nodes.HasChildNodes)
                {
                    foreach (XmlNode node in nodes.ChildNodes)
                    {
                        if (nodes.Name == "rho")
                        {
                            rho = Double.Parse(nodes.InnerText);
                            return;
                        }
                        get_rho(node);
                    }
                }
            }
    
            public void getAlpha_str(XmlNode nodes)
            {
                if (nodes.HasChildNodes)
                {
                    foreach (XmlNode node in nodes.ChildNodes)
                    {
                        if (nodes.Name == "alpha")
                        {
                            //sr = new StreamReader(new Stream(nodes.InnerText));
                            alpha_str = nodes.InnerText;
                            return;
                        }
                        getAlpha_str(node);
                    }
                }
            }
    
            public void getSv_count(XmlNode nodes)
            {
                if (nodes.HasChildNodes)
                {
                    foreach (XmlNode node in nodes.ChildNodes)
                    {
                        if (nodes.Name == "sv_count")
                        {
                            sv_count = int.Parse(nodes.InnerText);
                            return;
                        }
                        getSv_count(node);
                    }
                }
            }
            
            public void getAlpha()
            {
                byte[] array = Encoding.ASCII.GetBytes(alpha_str);
                MemoryStream stream = new MemoryStream(array);             //convert stream 2 string      
                sr = new StreamReader(stream);
                alpha = new double[sv_count];
                sr.ReadLine();
                int i = 0;
                while (true)
                {
    
                    string tmp = sr.ReadLine();
                    if (tmp == "")
                        continue;
    
                    string[] tmp2 = tmp.Split(' ');
                    foreach (string ele in tmp2)
                    {
                        if (ele != "")
                        {
                            alpha[i] = double.Parse(ele);
                            i++;
                        }
                    }
    
                    if (i == sv_count)
                        break;
                }
            }        
        }
    }

    c#读取XML的方式比较多,还可以利用Linq操作xml,另外也可以参考以下链接:

    c# 读取opencv 生成的svm训练好的xml分类器http://blog.csdn.net/yeyang911/article/details/12905153


    2、使用其他C#的SVM库

    关于提取参数,自定义HOG Detector的问题,后来在网上搜到了这种方式

    Training custom SVM to use with HOGDescriptor in OpenCV:

    I was struggling with the same problem. Searching forums I have found, that the detector cannot be trained using CvSVM (I don't know the reason). I used LIBSVM for training the the detector. Here is the code to extract the detector for HOGDescriptor.setSVMDetector( w): For data details see LIBSVM documentation/header. I did all the training in C++, filling the LIBSVM training data from CV to LIBSVM; the code below extracts the detector vector needed for cv::HOGDescriptor. The w parameter is std::vector<float> w   

    const double * const *sv_coef = model.sv_coef;
    const svm_node * const *SV = model.SV;
    int l = model.l;
    model.label;
    
    const svm_node* p_tmp = SV[0];
    int len = 0;
    while( p_tmp->index != -1 )
    {
        len++;
        p_tmp++;
    }
    w.resize( len+1 );
    
    for( int i=0; i<l; i++)
    {
        double svcoef = sv_coef[0][i];
        const svm_node* p = SV[i];
        while( p->index != -1 )
        {
            w[p->index-1] += float(svcoef * p->value);
            p++;
        }
    }
    w[len] = float(-model.rho[0]);

    来自: http://stackoverflow.com/questions/15339657/training-custom-svm-to-use-with-hogdescriptor-in-opencv


    该回答提到的 LIBSVM 库就是比较好的替代手段,应该可以直接获取到这两个中间量,而不用再去解析XML。

    可以去作者主页上下载LIBSVM库:http://www.csie.ntu.edu.tw/~cjlin/libsvm/#csharp


    3、其他相关链接

    • 前些天的【OpenCV】基于HOG与SVM的行人检测学习(原理小结):

        http://www.cnblogs.com/KC-Mei/p/4534009.html

    • training GPU HOGDescriptor for multi scale detection:

        http://answers.opencv.org/question/4351/training-gpu-hogdescriptor-for-multi-scale-detection/

    M$7{){(RJTFFR@RMUB{71QA

  • 相关阅读:
    linux下聊天工具的安装
    Linux上OpenLDAP集群
    Linux下python基础调试
    曾仕强主讲:易经的奥秘(全文讲义)
    Linux单网卡多个IP(或者多个网卡多个IP)设置
    单播、广播、组播的区别和特点
    谷歌招聘 变态15题你会做几道?
    Gartner再评RSA为网络欺诈检测领导者 狼人:
    云安全 安全领域的最大热点之一 狼人:
    金山毒霸专业版高调上线 宣称杀毒速度增3倍 狼人:
  • 原文地址:https://www.cnblogs.com/KC-Mei/p/4553024.html
Copyright © 2020-2023  润新知