使用带有OpenCV的SVM提高预测灵敏度

时间:2015-04-08 10:48:13

标签: opencv classification svm

我正在尝试对图像进行分类,无论字符是否打印在表面上。

这样做。

首先,我使用真实图像拍摄图像的冲浪功能,并手动删除真实图像,尝试创建一个单词到xml文件,然后尝试预测。

然而,除非我使用完全不同的图像或完全裁剪的图像,否则我的SVM分类器会预测它是正确的。

这些是我用于火车的图像

https://www.dropbox.com/sh/xked9ywnibzv3tt/AADC0lP4WYAo3ddEDgvHpFhha/negative?dl=0

这是我的代码。

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "opencv2/core/core.hpp"
#include<dirent.h>
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/ml/ml.hpp>

using namespace cv;
using namespace std;


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/", filepath;
    DIR *dp;
    struct dirent *dirp;
    struct stat filestat;

    cout << "Add Features to KMeans" << endl;
    addFeaturesToBOWKMeansTrainer("/positive/", bowTrainer);
    addFeaturesToBOWKMeansTrainer("/negative/", 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/", trainingData, labels, bowDE, 1);
    computeFeaturesWithBow("/negative/", trainingData, labels, bowDE, 0);

    CvSVMParams params;
    params.kernel_type=CvSVM::LINEAR;
    params.svm_type=CvSVM::C_SVC;
    params.gamma=5;
    params.C=100;
    params.term_crit=cvTermCriteria(CV_TERMCRIT_NUMBER,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");

        vector<KeyPoint> cameraKeyPoints;
    Mat rotated = imread("test.jpg",0);
    Mat featuresFromimage;

        detector->detect(rotated, cameraKeyPoints);
        bowDE.compute(rotated, cameraKeyPoints, featuresFromimage);

        cout <<"anar:"<< svm.predict(featuresFromimage) << endl;
        imshow("edges", rotated);
    cvWaitKey(0);


    return 0;
}

问题1 :由于这些图像太熟悉我怎么能做预测呢

if  similiarity > %80 
     "correct"
else 
     "defected"

问题2 由于这种角色背叛在工厂中非常罕见,因此很难获得大量缺陷图像进行训练。手动创建此图像上的缺陷是正确的解决方案吗?如果不是我能真正做到的?

问题3

我可以在这种图像上实际采用哪种预处理方法来提高SVM的准确性?

谢谢

0 个答案:

没有答案