因爲EmguCV封裝的更加完全,在C#中並不能跟C++同樣經過重載得到這兩個中間變量html
//繼承自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)node
爲了獲取這兩個變量用於自定義HOG檢測子,暫時想到的幾種辦法:c#
分類器訓練好後通常須要進行保存,方便直接預測數組
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,另外也能夠參考如下連接:this
c# 讀取opencv 生成的svm訓練好的xml分類器:http://blog.csdn.net/yeyang911/article/details/12905153spa
關於提取參數,自定義HOG Detector的問題,後來在網上搜到了這種方式.net
Training custom SVM to use with HOGDescriptor in OpenCV:code
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
前些天的【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/