上篇使用 OpenCV FaceRecognizer 快速基線,本文介紹經典 HOG + SVM 管線:HOG 提取梯度方向直方圖特徵,SVM 解決二分類(男/女)。OpenCV 對兩者均有成熟封裝,調用便捷。
CvSVM 支持 C_SVC、RBF 核等。路徑;標籤(0/1)。void read_csv(const string& csvPath, vector& paths, vector& labels, char sep=';') {
ifstream f(csvPath);
string line, path, label;
while (getline(f, line)) {
stringstream ss(line);
getline(ss, path, sep);
getline(ss, label);
if (!path.empty() && !label.empty()) {
paths.push_back(path);
labels.push_back(stoi(label));
}
}
}
const int NUM_TRAIN = 800;
Mat trainDataHog, trainLabel = Mat::zeros(NUM_TRAIN, 1, CV_32FC1);
HOGDescriptor hog(Size(64,64), Size(16,16), Size(8,8), Size(8,8), 9);
for (int i = 0; i < NUM_TRAIN; ++i) {
Mat img = imread(paths[i], 1);
resize(img, img, Size(64,64));
vector desc;
hog.compute(img, desc, Size(1,1), Size(0,0));
if (i == 0) trainDataHog = Mat::zeros(NUM_TRAIN, desc.size(), CV_32FC1);
for (size_t j = 0; j < desc.size(); ++j)
trainDataHog.at(i, j) = desc[j];
trainLabel.at(i, 0) = labels[i];
}
CvSVM svm;
CvSVMParams params(CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL,
cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON));
svm.train(trainDataHog, trainLabel, Mat(), Mat(), params);
svm.save("SVM_SEX_Model.txt");
Mat test = imread("test_female.bmp", 1);
resize(test, test, Size(64,64));
vector desc; hog.compute(test, desc);
Mat testHog(1, desc.size(), CV_32FC1);
for (size_t j = 0; j < desc.size(); ++j) testHog.at(0, j) = desc[j];
int pred = svm.predict(testHog); // 0/1 對應性別
vecTrainPath、matTrainData,類型前綴+語義駝峰,大型項目必備。vector 動態擴容、RAII、迭代器遍歷,優於手動 new[]。cv::String/cv::Vector 等為 STL 別名,勿混淆。見正文 GenderSVM.cpp,含讀取、訓練、保存、測試全流程,可直接編譯運行(需配置 OpenCV 環境)。