简体   繁体   English

SVM + HOG,找到的对象始终为NULL

[英]SVM + HOG, found object is always NULL

I am working on fungus spores detection. 我正在研究真菌孢子。 I have about 359 positive images(cropped images of fungus particles) and 171 negative images(cropped images of dust particles). 我大约有359张正面图像(真菌颗粒的裁剪图像)和171张负面图像(灰尘颗粒的裁剪图像)。

the actual size of pos/nag images is same as the size of particle which is around 8x8 but for SVM training I have resize it to 30x30 and then have used resized images to train SVM classifier. pos / nag图像的实际大小与8x8左右的粒子大小相同,但是对于SVM训练,我将其调整为30x30,然后使用调整大小后的图像来训练SVM分类器。 I am directly training the SVM with images not with any features. 我直接使用没有任何功能的图像来训练SVM。

After training the classifier successfully I used hog.setSVMDetector(myclassifier) and hog.detectMultiScale but the found objects is zero. 成功训练分类器后,我使用了hog.setSVMDetector(myclassifier)和hog.detectMultiScale,但是找到的对象为零。

Now my questions is what I am doing wrong in my code? 现在我的问题是我在代码中做错了什么? Please click on the below link for Nagative/Positive images which I used for SVM classifier, test images and the desired particles image. 请单击下面的链接以获取我用于SVM分类器的负/正图像,测试图像和所需的粒子图像。

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

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 :   %d\n",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);

I haven't managed to get your classifier to work, but I have found the cause of your current issue. 我没有设法使您的分类器正常工作,但是我找到了导致您当前问题的原因。

I have put up a gist here so you can check it out. 我在这里放了一个要点以便您可以检查一下。 I have used my own filereading methods to read in the images, so you will have to make one or two changes so that it works for you. 我使用了自己的文件读取方法来读取图像,因此您将不得不进行一到两个更改,以便它对您有用。

The reason that you get no found objects is because your classifier vector is empty. 之所以没有找到对象,是因为您的分类器向量为空。 That is due to incorrect reading of the node from the yml file. 是由于错误地从yml文件中读取了节点。 'support_vectors' is a subnode of 'my_svm'. “ support_vectors”是“ my_svm”的子节点。 You were trying to read it as a top-level node, and were getting back an empty vector. 您试图将其作为顶级节点读取,并且正在获取空向量。

There are also a couple of other errors in the filereading loops which I have fixed (marked FIXED ) - at least, they seemed incorrect to me. 我已修复的文件读取循环中还存在其他一些错误(标记为FIXED )-至少对我来说,它们似乎不正确。

This still won't correctly classify (yet). 仍然无法正确分类(尚未)。 There is some issue with the format of your support vectors array, which breaks the hog descriptor. 支持向量数组的格式存在问题,这会破坏猪描述符。

So you'll need to put a bit more work into this, but hopefully this moves you in the right direction. 因此,您需要为此付出更多的努力,但是希望这会朝着正确的方向前进。

I have added a slider to the output window. 我已将滑块添加到输出窗口。 When you get the classifier to work, you can change the scaleFactor with the slider which should yield interesting variation in the results. 当分类器开始工作时,您可以使用滑块更改scaleFactor,这将在结果中产生有趣的变化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM