Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何正确使用BoW训练OpenCV支持向量机_Opencv_Svm_Surf_Object Detection - Fatal编程技术网

如何正确使用BoW训练OpenCV支持向量机

如何正确使用BoW训练OpenCV支持向量机,opencv,svm,surf,object-detection,Opencv,Svm,Surf,Object Detection,我无法训练SVM来识别我的对象。我正在尝试使用SURF+文字包+SVM来实现这一点。我的问题是分类器没有检测到任何东西。所有结果均为0 这是我的密码: Ptr<FeatureDetector> detector = FeatureDetector::create("SURF"); Ptr<DescriptorExtractor> descriptors = DescriptorExtractor::create("SURF"); string to_string(con

我无法训练SVM来识别我的对象。我正在尝试使用SURF+文字包+SVM来实现这一点。我的问题是分类器没有检测到任何东西。所有结果均为0

这是我的密码:

Ptr<FeatureDetector> detector = FeatureDetector::create("SURF");
Ptr<DescriptorExtractor> descriptors = DescriptorExtractor::create("SURF");

string to_string(const int val) {
    int i = val;
    std::string s;
    std::stringstream out;
    out << i;
    s = out.str();
    return s;
}

Mat compute_features(Mat image) {
    vector<KeyPoint> keypoints;
    Mat features;

    detector->detect(image, keypoints);
    KeyPointsFilter::retainBest(keypoints, 1500);
    descriptors->compute(image, keypoints, features);

    return features;
}

BOWKMeansTrainer addFeaturesToBOWKMeansTrainer(String dir, BOWKMeansTrainer& bowTrainer) {
    DIR *dp;
    struct dirent *dirp;
    struct stat filestat;

    dp = opendir(dir.c_str());


    Mat features;
    Mat img;

    string filepath;
    #pragma loop(hint_parallel(4))
    for (; (dirp = readdir(dp));) {
        filepath = dir + dirp->d_name;

        cout << "Reading... " << filepath << endl;

        if (stat( filepath.c_str(), &filestat )) continue;
        if (S_ISDIR( filestat.st_mode ))         continue;

        img = imread(filepath, 0);

        features = compute_features(img);
        bowTrainer.add(features);
    }


    return bowTrainer;
}

void computeFeaturesWithBow(string dir, Mat& trainingData, Mat& labels, BOWImgDescriptorExtractor& bowDE, int label) {
    DIR *dp;
    struct dirent *dirp;
    struct stat filestat;

    dp = opendir(dir.c_str());

    vector<KeyPoint> keypoints;
    Mat features;
    Mat img;

    string filepath;

    #pragma loop(hint_parallel(4))
    for (;(dirp = readdir(dp));) {
        filepath = dir + dirp->d_name;

        cout << "Reading: " << filepath << endl;

        if (stat( filepath.c_str(), &filestat )) continue;
        if (S_ISDIR( filestat.st_mode ))         continue;

        img = imread(filepath, 0);

        detector->detect(img, keypoints);
        bowDE.compute(img, keypoints, features);

        trainingData.push_back(features);
        labels.push_back((float) label);
    }

    cout << string( 100, '\n' );
}

int main() {
    initModule_nonfree();

    Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");

    TermCriteria tc(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 10, 0.001);
    int dictionarySize = 1000;
    int retries = 1;
    int flags = KMEANS_PP_CENTERS;
    BOWKMeansTrainer bowTrainer(dictionarySize, tc, retries, flags);
    BOWImgDescriptorExtractor bowDE(descriptors, matcher);

    string dir = "./positive_large", filepath;
    DIR *dp;
    struct dirent *dirp;
    struct stat filestat;

    cout << "Add Features to KMeans" << endl;
    addFeaturesToBOWKMeansTrainer("./positive_large/", bowTrainer);
    addFeaturesToBOWKMeansTrainer("./negative_large/", bowTrainer);

    cout << endl << "Clustering..." << endl;

    Mat dictionary = bowTrainer.cluster();
    bowDE.setVocabulary(dictionary);

    Mat labels(0, 1, CV_32FC1);
    Mat trainingData(0, dictionarySize, CV_32FC1);


    cout << endl << "Extract bow features" << endl;

    computeFeaturesWithBow("./positive_large/", trainingData, labels, bowDE, 1);
    computeFeaturesWithBow("./negative_large/", trainingData, labels, bowDE, 0);

    CvSVMParams params;
    params.kernel_type=CvSVM::RBF;
    params.svm_type=CvSVM::C_SVC;
    params.gamma=0.50625000000000009;
    params.C=312.50000000000000;
    params.term_crit=cvTermCriteria(CV_TERMCRIT_ITER,100,0.000001);
    CvSVM svm;

    cout << endl << "Begin training" << endl;

    bool res=svm.train(trainingData,labels,cv::Mat(),cv::Mat(),params);

    svm.save("classifier.xml");

    //CvSVM svm;
    svm.load("classifier.xml");

    VideoCapture cap(0); // open the default camera

    if(!cap.isOpened())  // check if we succeeded
        return -1;

    Mat featuresFromCam, grey;
    vector<KeyPoint> cameraKeyPoints;
    namedWindow("edges",1);
    for(;;)
    {
        Mat frame;
        cap >> frame; // get a new frame from camera
        cvtColor(frame, grey, CV_BGR2GRAY);
        detector->detect(grey, cameraKeyPoints);
        bowDE.compute(grey, cameraKeyPoints, featuresFromCam);

        cout << svm.predict(featuresFromCam) << endl;
        imshow("edges", frame);
        if(waitKey(30) >= 0) break;
    }   

        return 0;
}
Ptr-detector=FeatureDetector::create(“SURF”);
Ptr描述符=描述符牵引器::创建(“SURF”);
字符串到_字符串(常量int val){
int i=val;
std::字符串s;
std::stringout;
外检测(图像、关键点);
KeyPointsFilter::retainBest(keypoints,1500);
描述符->计算(图像、关键点、特征);
返回特性;
}
BowKMeanFilter为BowKMeanFilter添加功能(管柱方向、BowKMeanFilter和bowTrainer){
DIR*dp;
结构方向*dirp;
struct stat filestat;
dp=opendir(dir.c_str());
垫特征;
Mat-img;
字符串文件路径;
#pragma循环(提示_并行(4))
对于(;(dirp=readdir(dp));){
filepath=dir+dirp->d_name;

cout首先,使用现有项目中的相同参数并不能证明您使用的参数是正确的。事实上,在我看来,这是一种完全没有意义的方法(无意冒犯)这是因为,SVM参数直接受到数据集和描述符提取方法的影响。为了获得正确的参数,您必须进行交叉验证。因此,如果这些参数是从不同的识别任务中获得的,则没有任何意义。例如,在我的人脸验证项目中,最佳参数为0.0625和10分别表示
gamma
C

你的方法的另一个重要问题是测试图像。据我从你的代码中看到的,你没有使用来自磁盘的图像来测试你的分类器,所以从这里的其余部分,我将做一些假设。如果你的测试图像,即你从相机获得的图像与你的正面图像不同,它将失败。我的意思是不同;你必须确保您的测试图像仅由方向盘组成,因为您的培训图像仅包含方向盘。如果您的测试图像包含(例如,带方向盘的汽车座椅),则测试图像的弓描述符将与您的火车图像弓描述符完全不同。因此,简单地说,您的测试图像不应包含方向盘对于其他一些对象,它们应仅包含方向盘

如果您满足这些要求,那么使用培训映像测试系统是最基本的方法。即使在这种情况下您失败了,您也可能会遇到一些植入问题。其他方法可以是:将培训数据拆分为两个,这样您就有四个分区:

  • 正面列车图像
  • 负片列车图像
  • 阳性测试图像
  • 阴性测试图像
仅使用训练映像来训练系统,并使用测试映像对其进行测试。同样,您必须通过交叉验证来指定参数

除此之外,在执行我之前所写的操作之前,您可能需要检查一些特定的步骤以定位问题:

  • 每个图像检测到多少个关键点?相似的图像应导致相似数量的关键点
  • 你知道弓形描述符是图像的冲浪描述符的直方图。确保相似的图像产生相似的直方图(弓形描述符)。最好通过可视化直方图来检查这一点
  • 如果前一步得到满足,问题很可能是SVM训练步骤,这是一个非常重要的步骤(可能是最重要的步骤)
  • 我希望我能够强调交叉验证的重要性。做交叉验证


    祝你好运!

    谢谢你的详细回答!!!我需要问你一些问题。假设我的方向盘主要是白色背景的方向盘。你是在告诉我如果我的测试图像有背景(车速表、座椅等)它不起作用?事实上我不是这个意思,但这也可能是原因。这取决于图像中除方向盘以外的描述符数量。我的意思是,如果你的测试图像是方向盘、狗和自行车(都在一张图像中),它不会起作用。我想说的是,它不仅是关于背景,它也是关于方向盘周围的其他部分。好的,让它足够清楚。这是一个好的测试图像吗:?不完美,它可能会起作用,但很可能会失败。因为,与I相比,SURF会在这张图像中找到更多的关键点白色背景的法师。所以,你的弓描述符会有所不同。试着用训练图像进行测试。这意味着SVM在实际情况下不会有用,因为方向盘的背景是速度表和其他东西?