项目迫不得已用到了SVM + HOG
在这里写记录一下 以下只是项目众多分类器中的一种
代码根据书上来的自己进行一些修改
正样本 阀芯的外表面 可以看出还是比较光滑的
负样本 阀芯的外表面有加工的纹路 我之前不想用机器学习的分类器 使用了边缘 差分金字塔 梯度等等 能用的都用了 分类效果很差 所以迫不得已才用HOG + SVM 毕竟老师不给GPU 要不然直接上神经网络了。
首先切图片 图片还是很难切的 这个代码我写了好几个小时 并不是简单的ROI 因为阀芯有时候并不一定是放平的 有时候是歪的 所以我用了一些方法自动切出来需要检测的部分 并统一放缩到192 * 128的大小。
然后就可以进行HOG特征提取 在这里不赘述 SVM采用的是线性核 并没有深究
上训练代码
//创建一个HOG特征对象
HOGDescriptor hogDesc(mypic_xiaci[0].size(), Size(8, 8), Size(4, 4), Size(4, 4), 9);
//放特征的数组
vector<float> desc;
//计算特征
hogDesc.compute(mypic_xiaci[0], desc);
int featureSize = desc.size();
int numberOfSamples = mypic.size() + mypic_xiaci.size();
cout << featureSize << "," << numberOfSamples << endl;
//下面的这个要把所有图像的特征放在一个Mat里面
Mat samples(numberOfSamples, featureSize, CV_32FC1);
for(int i = 0; i < featureSize; i++)
{
samples.ptr<float>(0)[i] = desc[i];
}
for (int j = 1; j < mypic.size(); j++)
{
hogDesc.compute(mypic[j], desc);
for (int i = 0; i < featureSize; i++)
{
samples.ptr<float>(j)[i] = desc[i];
}
}
for (int j = 0; j < mypic_xiaci.size(); j++)
{
hogDesc.compute(mypic_xiaci[j], desc);
for (int i = 0; i < featureSize; i++)
{
samples.ptr<float>(j + mypic.size())[i] = desc[i];
}
}
//标签
Mat labels(numberOfSamples, 1, CV_32SC1);
labels.rowRange(0, mypic.size()) = 1.0;
labels.rowRange(mypic.size(), numberOfSamples) = -1.0;
//SVM部分
Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
svm->setType(cv::ml::SVM::C_SVC);
svm->setKernel(cv::ml::SVM::LINEAR);
cv::Ptr<cv::ml::TrainData> trainingData = cv::ml::TrainData::create(samples, cv::ml::SampleTypes::ROW_SAMPLE, labels);
svm->train(trainingData);
Mat queries(5, featureSize, CV_32FC1);
for (int j = 0; j < mypic_ceshi.size(); j++)
{
hogDesc.compute(mypic_ceshi[j], desc);
for (int i = 0; i < featureSize; i++)
{
queries.ptr<float>(j)[i] = desc[i];
}
}
Mat prediction;
svm->predict(queries, prediction);
for (int i = 0; i < 5; i++)
{
std::cout << "query: " << i << ": " << ((prediction.at<float>(i) < 0.0) ? "Negative" : "Positive") << std::endl;
}
waitKey(0);