Вопрос по c++ – SVM-классификатор на основе функций HOG для «обнаружения объектов» в OpenCV

20

У меня есть проект, по которому я хочу обнаруживать объекты на изображениях; Моя цель - использовать функции HOG. Используя реализацию OpenCV SVM, я смог найти код для обнаружения людей, и я прочитал несколько статей о настройке параметров для обнаружения объектов вместо людей. К сожалению, я не мог этого сделать по нескольким причинам; Во-первых, я, вероятно, неправильно настраиваю параметры, во-вторых, я не очень хороший программист на C ++, но я должен делать это с C ++ / OpenCV ...Вот Вы можете найти код для обнаружения функций HOG для людей с помощью C ++ / OpenCV.

Допустим, я хочу обнаружить объект в этомобраз, Теперь я покажу вам, что я пытался изменить в коде, но со мной это не сработало.

Код, который я пытался изменить:

HOGDescriptor hog;
hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());

Я пытался изменитьgetDefaultPeopleDetector() со следующими параметрами, но он не работает:

(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9, 0,-1, 0, 0.2, true, cv::HOGDescriptor::DEFAULT_NLEVELS)

Затем я попытался создать вектор, но когда я хотел напечатать результаты, он кажется пустым.

vector<float> detector;

HOGDescriptor hog(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9, 0,-1, 0, 0.2, true, cv::HOGDescriptor::DEFAULT_NLEVELS);

hog.setSVMDetector(detector);

Пожалуйста, мне нужна помощь в решении этой проблемы.

Я застрял здесь, я хочу знать, что делать или даже показать мне пример Mario
просто хочу знать, если я делаю неправильно в кодировании, я учусь, и это цель вопросов здесь, чтобы получить выгоду Mario

Ваш Ответ

3   ответа
7

собирал образцы положительных и отрицательных изображений, используя HOG для извлечения характеристик автомобиля, обучал набор функций с использованием линейного SVM (я использую SVM light), а затем использовал модель для обнаружения автомобиля с помощью функции многоопределения HOG.

Я получаю много ложных срабатываний, затем переучиваю данные с использованием положительных образцов и ложных положительных + отрицательных образцов. Полученная модель затем снова тестируется. Полученное в результате обнаружение улучшается (меньше ложных срабатываний), но результат неудовлетворительный (средний 50% -й показатель попаданий и 50% ложных срабатываний). Настройка параметров мультидетекта улучшает результат, но ненамного (на 10% меньше ложных срабатываний и увеличение частоты попаданий).

Edit Я могу поделиться с вами исходным кодом, если хотите, и я очень открыт для обсуждения, так как я не получил удовлетворительных результатов при использовании HOG. Во всяком случае, я думаю, что код может быть хорошей отправной точкой при использовании HOG для обучения и обнаружения

Edit: adding code

static void calculateFeaturesFromInput(const string& imageFilename, vector<float>& featureVector, HOGDescriptor& hog) 
{
    Mat imageData = imread(imageFilename, 1);
    if (imageData.empty()) {
        featureVector.clear();
        printf("Error: HOG image '%s' is empty, features calculation skipped!\n", imageFilename.c_str());
        return;
    }
    // Check for mismatching dimensions
    if (imageData.cols != hog.winSize.width || imageData.rows != hog.winSize.height) {
       featureVector.clear();
       printf("Error: Image '%s' dimensions (%u x %u) do not match HOG window size (%u x %u)!\n", imageFilename.c_str(), imageData.cols, imageData.rows, hog.winSize.width, hog.winSize.height);
        return;
    }
    vector<Point> locations;
    hog.compute(imageData, featureVector, winStride, trainingPadding, locations);
    imageData.release(); // Release the image again after features are extracted
}

...

int main(int argc, char** argv) {

    // <editor-fold defaultstate="collapsed" desc="Init">
    HOGDescriptor hog; // Use standard parameters here
    hog.winSize.height = 128;
    hog.winSize.width = 64;

    // Get the files to train from somewhere
    static vector<string> tesImages;
    static vector<string> positiveTrainingImages;
    static vector<string> negativeTrainingImages;
    static vector<string> validExtensions;
    validExtensions.push_back("jpg");
    validExtensions.push_back("png");
    validExtensions.push_back("ppm");
    validExtensions.push_back("pgm");
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Read image files">
    getFilesInDirectory(posSamplesDir, positiveTrainingImages, validExtensions);
    getFilesInDirectory(negSamplesDir, negativeTrainingImages, validExtensions);
    /// Retrieve the descriptor vectors from the samples
    unsigned long overallSamples = positiveTrainingImages.size() + negativeTrainingImages.size();
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Calculate HOG features and save to file">
    // Make sure there are actually samples to train
    if (overallSamples == 0) {
        printf("No training sample files found, nothing to do!\n");
        return EXIT_SUCCESS;
    }

    /// @WARNING: This is really important, some libraries (e.g. ROS) seems to set the system locale which takes decimal commata instead of points which causes the file input parsing to fail
    setlocale(LC_ALL, "C"); // Do not use the system locale
    setlocale(LC_NUMERIC,"C");
    setlocale(LC_ALL, "POSIX");

    printf("Reading files, generating HOG features and save them to file '%s':\n", featuresFile.c_str());
    float percent;
    /**
     * Save the calculated descriptor vectors to a file in a format that can be used by SVMlight for training
     * @NOTE: If you split these steps into separate steps: 
     * 1. calculating features into memory (e.g. into a cv::Mat or vector< vector<float> >), 
     * 2. saving features to file / directly inject from memory to machine learning algorithm,
     * the program may consume a considerable amount of main memory
     */ 
    fstream File;
    File.open(featuresFile.c_str(), ios::out);
    if (File.good() && File.is_open()) {
        File << "# Use this file to train, e.g. SVMlight by issuing $ svm_learn -i 1 -a weights.txt " << featuresFile.c_str() << endl; // Remove this line for libsvm which does not support comments
,        // Iterate over sample images
        for (unsigned long currentFile = 0; currentFile < overallSamples; ++currentFile) {
            storeCursor();
            vector<float> featureVector;
            // Get positive or negative sample image file path
            const string currentImageFile = (currentFile < positiveTrainingImages.size() ? positiveTrainingImages.at(currentFile) : negativeTrainingImages.at(currentFile - positiveTrainingImages.size()));
            // Output progress
            if ( (currentFile+1) % 10 == 0 || (currentFile+1) == overallSamples ) {
                percent = ((currentFile+1) * 100 / overallSamples);
                printf("%5lu (%3.0f%%):\tFile '%s'", (currentFile+1), percent, currentImageFile.c_str());
                fflush(stdout);
                resetCursor();
            }
            // Calculate feature vector from current image file
            calculateFeaturesFromInput(currentImageFile, featureVector, hog);
            if (!featureVector.empty()) {
                /* Put positive or negative sample class to file, 
                 * true=positive, false=negative, 
                 * and convert positive class to +1 and negative class to -1 for SVMlight
                 */
                File << ((currentFile < positiveTrainingImages.size()) ? "+1" : "-1");
                // Save feature vector components
                for (unsigned int feature = 0; feature < featureVector.size(); ++feature) {
                    File << " " << (feature + 1) << ":" << featureVector.at(feature);
                }
                File << endl;
            }
        }
        printf("\n");
        File.flush();
        File.close();
    } else {
        printf("Error opening file '%s'!\n", featuresFile.c_str());
        return EXIT_FAILURE;
    }
    // </editor-fold>

    // <editor-fold defaultsta,te="collapsed" desc="Pass features to machine learning algorithm">
    /// Read in and train the calculated feature vectors
    printf("Calling SVMlight\n");
    SVMlight::getInstance()->read_problem(const_cast<char*> (featuresFile.c_str()));
    SVMlight::getInstance()->train(); // Call the core libsvm training procedure
    printf("Training done, saving model file!\n");
    SVMlight::getInstance()->saveModelToFile(svmModelFile);
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Generate single detecting feature vector from calculated SVM support vectors and SVM model">
    printf("Generating representative single HOG feature vector using svmlight!\n");
    vector<float> descriptorVector;
    vector<unsigned int> descriptorVectorIndices;
    // Generate a single detecting feature vector (v1 | b) from the trained support vectors, for use e.g. with the HOG algorithm
    SVMlight::getInstance()->getSingleDetectingVector(descriptorVector, descriptorVectorIndices);
    // And save the precious to file system
    saveDescriptorVectorToFile(descriptorVector, descriptorVectorIndices, descriptorVectorFile);
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Test detecting vector">

    cout << "Test Detecting Vector" << endl;
    hog.setSVMDetector(descriptorVector); // Set our custom detecting vector
    cout << "descriptorVector size: " << sizeof(descriptorVector) << endl;

    getFilesInDirectory(tesSamplesDir, tesImages, validExtensions);
    namedWindow("Test Detector", 1);

    for( size_t it = 0; it < tesImages.size(); it++ )
    {
        cout << "Process image " << tesImages[it] << endl;
        Mat image = imread( tesImages[it], 1 );
        detectAndDrawObjects(image, hog);

        for(;;)
        {
            int c = waitKey();
            if( (char)c == 'n')
                break;
            else if( (char)c == '\x1b' )
                exit(0);
        }
    }
    // </editor-fold>
    return EXIT_SUCCESS;
}
Error: User Rate Limit Exceeded Mario
Error: User Rate Limit Exceededpost the code anywayError: User Rate Limit Exceeded
Error: User Rate Limit Exceededstackoverflow.com/questions/16214920/…Error: User Rate Limit Exceeded Mario
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
9

C ++ решений, которые я создал ~ & GT; эта обертка SVMLight & lt; ~, которая является статической библиотекой, которая предоставляет классыSVMTrainer а такжеSVMClassifier что упростит обучение до чего-то вроде:

// we are going to use HOG to obtain feature vectors:
HOGDescriptor hog;
hog.winSize = Size(32,48);

// and feed SVM with them:
SVMLight::SVMTrainer svm("features.dat");

тогда для каждого образца обучения:

// obtain feature vector describing sample image:
vector<float> featureVector;
hog.compute(img, featureVector, Size(8, 8), Size(0, 0));

// and write feature vector to the file:
svm.writeFeatureVectorToFile(featureVector, true);      // true = positive sample

доfeatures.dat Файл содержит векторы функций для всех образцов, и в конце вы просто вызываете:

std::string modelName("classifier.dat");
svm.trainAndSaveModel(modelName);

Как только у вас есть файл с моделью (илиfeatures.dat что вы можете просто обучить классификатор):

SVMLight::SVMClassifier c(classifierModelName);
vector<float> descriptorVector = c.getDescriptorVector();
hog.setSVMDetector(descriptorVector);
...
vector<Rect> found;
Size padding(Size(0, 0));
Size winStride(Size(8, 8));
hog.detectMultiScale(segment, found, 0.0, winStride, padding, 1.01, 0.1);

просто проверьте документациюHOGDescriptor для получения дополнительной информации :)

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
36

opencv HOG и классификатора SVM, вам необходимо сначала обучить классификатор. Игра с параметрами здесь не поможет, извините :(.

В общих чертах, вам нужно будет выполнить следующие шаги:

Step 1) Подготовьте несколько обучающих изображений объектов, которые вы хотите обнаружить (положительные образцы). Также вам нужно будет подготовить некоторые изображения без каких-либо объектов интереса (негативные образцы).

Step 2) Определите особенности HOG в обучающем образце и используйте эти функции для обучения классификатора SVM (также имеется в OpenCV).

Step 3) Используйте коэффициенты обученного классификатора SVM в методе HOGDescriptor :: setSVMDetector ().

Только тогда вы можете использовать пример кода peopledetector.cpp для обнаружения объектов, которые вы хотите обнаружить.

Error: User Rate Limit Exceeded Mario
Error: User Rate Limit Exceeded Mario
Error: User Rate Limit Exceeded Mario
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededstd::vector<float>Error: User Rate Limit Exceededhog.setSVMDetector()Error: User Rate Limit Exceeded

Похожие вопросы