opencv +Hog + SVM 車輛檢測
阿新 • • 發佈:2018-11-06
最近嘗試了一下用opencv做了一下車輛檢測
其中hog特徵使用opencv自帶函式庫進行提取描述如下:
HOGDescriptor *hog = new HOGDescriptor(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9);
上述引數中第一個size代表讀入訓練資料中影象的大小
第二個為滑動視窗大小
第三個滑動步長
第四個cell的大小
然後就是SVM的使用了
Ptr < SVM > svm = SVM::create(); //建立物件 svm->setType(SVM::C_SVC); svm->setKernel(SVM::LINEAR); //線性核 //匯入特徵矩陣 每一行代表一個特徵向量 最後為特徵標籤 Ptr<TrainData> tData = TrainData::create(sample_feature_mat, ROW_SAMPLE,sample_label_mat); //自動設定相應引數並訓練 svm->trainAuto(tData);
再看看為什麼hog特徵能較好的對車輛分類
下圖顯示了我對100個包含車輛的樣本(影象上部)與200個不包含車輛的樣本(影象下部)進行視覺化,顯然包含車輛的特徵向量與不包含車輛的特徵向量有明顯區別
所以hog特徵能較強的描述目標物體的形狀資訊
而一般影象中物體特徵的表達通常用形狀、紋理或者顏色等特徵來描述
一般人體或車輛等能夠被形狀較強的表徵,而hog特徵正好適合來表徵物體的形狀資訊,所以一般用hog特徵來做行人或者車輛檢測等等…
完整程式碼如下:
//我用的是opencv3.4 HOG與SVM的使用與2.X版本的有些區別 string pos_path = "正樣本路徑"; string neg_path = "負樣本路徑"; Mat sample_feature_mat,sample_label_mat; ifstream input_pos_sample(pos_path); ifstream input_neg_sample(neg_path); vector<string>pos_sample_path,neg_sample_path,feature_dim; string str; int pos_sample_num,neg_sample_num ; while (getline(input_pos_sample, str)) pos_sample_path.push_back(str); while (getline(input_neg_sample, str)) neg_sample_path.push_back(str); pos_sample_num = pos_sample_path.size(); neg_sample_num = neg_sample_path.size(); input_pos_sample.close(); input_neg_sample.close(); HOGDescriptor *hog = new HOGDescriptor(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9); //正樣本hog特徵提取 for (int i = 0; i < pos_sample_num; ++i) { Mat input_img = imread(pos_sample_path[i],0); Mat train_data(64, 64, CV_32FC1); resize(input_img, train_data, Size(64, 64)); vector<float>descriptor; hog->compute(train_data, descriptor, Size(8, 8)); if (i == 0) { feature_dim = descriptor.size(); sample_feature_mat = Mat::zeros(pos_sample_num + neg_sample_num, feature_dim, CV_32FC1); sample_label_mat = Mat::zeros(pos_sample_num + neg_sample_num, 1, CV_32SC1); } float *pf = sample_feature_mat.ptr<float>(i); int *pl = sample_label_mat.ptr<int>(i); for (int j = 0; j < feature_dim; ++j) { *pf++ = descriptor[j]; } *pl++ = 1; } //負樣本hog特徵提取 for (int i = 0; i < neg_sample_num; ++i) { Mat input_img = imread(neg_sample_path[i],0); Mat train_data(64, 64, CV_32FC1); resize(input_img, train_data, Size(64, 64)); vector<float>descriptor; hog->compute(train_data, descriptor, Size(8, 8)); float *pf = sample_feature_mat.ptr<float>(i + pos_sample_num); int *pl = sample_label_mat.ptr<int>(i + pos_sample_num); for (int j = 0; j < feature_dim; ++j) { *pf++ = descriptor[j]; } *pl++ = -1; } //訓練資料 Ptr < SVM > svm = SVM::create(); svm->setType(SVM::C_SVC); svm->setKernel(SVM::LINEAR); Ptr<TrainData> tData = TrainData::create(sample_feature_mat, ROW_SAMPLE,sample_label_mat); cout << "train begin" << endl; svm->trainAuto(tData); svm->save("D:\\traindata\\SVM_Model.xml"); //訓練結果儲存檔案 cout << "train done" << endl;
我用100個正樣本200個負樣本訓練車輛檢測
結果對於KITTI的車輛資料分類正確率大約90%
分類結果還行,增加訓練資料還能達到更高的準確率
網上也很多例程,我就不詳細說明了