SVM + HOG,发现的对象总是NULL

SVM + HOG, found object is always NULL

本文关键字:对象 NULL 发现 HOG SVM      更新时间:2023-10-16

我的工作是真菌孢子检测。我有大约359张正面图像(真菌颗粒的裁剪图像)和171张负面图像(灰尘颗粒的裁剪图像)。

pos/nag图像的实际大小与粒子大小相同,约为8x8,但对于SVM训练,我将其调整为30x30,然后使用调整大小的图像来训练SVM分类器。我直接用不带任何特征的图像训练SVM。

在成功训练分类器后,我使用了hog.setSVMDetector(myclassifier)和hog.detectMultiScale,但发现的对象为零。

现在我的问题是我在我的代码做错了什么?请点击下面的链接查看我用于SVM分类器的阴性/阳性图像,测试图像和所需粒子图像。

https://drive.google.com/folderview?id=0B7yRjtOGywg7fnNJTXcxR2NYb3ItWTZ0UjYwUmt6YW96R0NHLWZQbVJucEk0bnJmcFJGS0E& usp =分享

class LinearSVM: public CvSVM {
public:
  void getSupportVector(std::vector<float>& support_vector) const;
};  
void LinearSVM::getSupportVector(std::vector<float>& support_vector) const {
    int sv_count = this->get_support_vector_count();
 //   mexPrintf("size :   %dn",support_vector.size());
    const CvSVMDecisionFunc* df = this->decision_func;
    const double* alphas = df[0].alpha;
    double rho = df[0].rho;
    int var_count = this->get_var_count();
    support_vector.resize(var_count, 0);
    for (unsigned int r = 0; r < (unsigned)sv_count; r++) {
      float myalpha = alphas[r];
      const float* v = this->get_support_vector(r);
      for (int j = 0; j < var_count; j++,v++) {
        support_vector[j] += (-myalpha) * (*v);
      }
    }
    support_vector.push_back(rho);
}
////////////////////////////// main.cpp ///////////////////////////
    int num_files = 359*171;
int img_area = 30*30;
Mat training_mat(num_files,img_area,CV_32FC1);
vector<int> training_Labels;
Mat labels(num_files,1,CV_32FC1);
int imagenum=0;
 for (int pimageNum = 0; pimageNum < 359; pimageNum++)
{
     // reading Positive Images from directory and resize it to 30x30
int ii = 0; // Current column in training_mat
for (int i = 0; i<posImage.rows; i++) {
    for (int j = 0; j < posImage.cols; j++) {
        training_mat.at<float>(imagenum,ii++) = posImage.at<uchar>(i,j);
imagenum++;
    }
}
training_Labels.push_back(1.0);
}
for (int nimageNum = 0; nimageNum < 171; nimageNum++)
{
     // reading Nagative Images from directory and resize it to 30x30
int ii = 0; // Current column in training_mat
for (int i = 0; i<nagImage.rows; i++) {
    for (int j = 0; j < nagImage.cols; j++) {
        training_mat.at<float>(imagenum,ii++) = nagImage.at<uchar>(i,j);
imagenum++;
    }
}
training_Labels.push_back(-1.0);
}
Mat(training_Labels).copyTo(labels);
labels.convertTo(labels, CV_32FC1);
 CvSVMParams SVM_params;
    SVM_params.svm_type = CvSVM::C_SVC;
    SVM_params.kernel_type = CvSVM::LINEAR; //CvSVM::LINEAR;
    SVM_params.degree = 0;
    SVM_params.gamma = 3;
    SVM_params.coef0 = 0;
    SVM_params.C = 1;
    SVM_params.nu = 0;
    SVM_params.p = 0;
    SVM_params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 10, 0.03);
    //Train SVM

    LinearSVM svmClassifier;
    svmClassifier.train(training_mat, labels, Mat(), Mat(), SVM_params);
    svmClassifier.save("D:\svmClassifier.yml");
HOGDescriptor hog;
hog.winSize = Size(8, 8);
std::vector<float> support_vector;
FileStorage fs;
    fs.open("D:\svmClassifier.yml", FileStorage::READ);
    fs["support_vectors"] >> support_vector;
hog.setSVMDetector(support_vector);
vector< Rect> found,found_filtered;
Size padding(Size(0, 0));
Size winStride(Size(8, 8));
cv::Mat test=cv::imread("testimage.bmp",CV_LOAD_IMAGE_GRAYSCALE);
// actual size of test image is 1024x768 which I resize to 400x 300
hog.detectMultiScale(test, found, 0.0, winStride, padding, 1.01, 0);
cout<<""found particles"<< found.size() ;  // it is always zero
size_t i, j;
    for (i=0; i<found.size(); i++)
    {
        Rect r = found[i];
        for (j=0; j<found.size(); j++)
            if (j!=i && (r & found[j])==r)
                break;
        if (j==found.size())
            found_filtered.push_back(r);
    }
    for (i=0; i<found_filtered.size(); i++)
    {
        Rect r = found_filtered[i];
        r.x += cvRound(r.width*0.1);
        r.width = cvRound(r.width*0.8);
        r.y += cvRound(r.height*0.06);
        r.height = cvRound(r.height*0.9);
        rectangle(test, r.tl(), r.br(), cv::Scalar(0,255,0), 2);
    }
    imshow("detected particles", test);
    waitKey(0);

我还没有设法让你的分类器工作,但我已经找到了你当前问题的原因。

我在这里放了一个要点,你可以看看。我已经使用了我自己的文件读取方法来读取图像,所以你必须做一两个更改,以便它为你工作。

没有找到对象的原因是你的分类器向量是空的。是由于错误地读取了yml文件中的节点。'support_vectors'是'my_svm'的子节点。你试图读取它作为一个顶级节点,并得到一个空向量。

在我已经修复的文件读取循环中还有其他一些错误(标记为FIXED) -至少,它们对我来说似乎是不正确的。

这仍然不能正确分类。支持向量数组的格式有一些问题,它破坏了hog描述符。

因此,您需要在这方面投入更多的工作,但希望这将使您朝着正确的方向前进。

我在输出窗口中添加了一个滑块。当您让分类器工作时,您可以使用滑块更改scaleFactor,这将在结果中产生有趣的变化。