尝试在 C++ 中训练 svm + hog 功能时抛出异常

问题描述 投票:0回答:1

当我使用这行代码时,我遇到了这个异常 exception description

svm->train(X, cv::ml::ROW_SAMPLE, labels);

这是堆栈跟踪:

[内嵌框架] svm&ssd_car_ detector.exe!invoke_main() 第 78 行 C++

在此功能中:

cv::Ptr<cv::ml::SVM> train_svm_model(const cv::Mat& X, const cv::Mat& labels) {

    if (X.empty() || labels.empty()) {
        cerr << "Error: Feature matrix (X) or labels matrix is empty." << endl;
        return nullptr;
    }

    // Check if dimensions match
    if (X.rows != labels.rows) {
        cerr << "Error: Number of rows in feature matrix (X) does not match the number of labels." << endl;
        return nullptr;
    }

    // Check data type of X
    if (X.type() != CV_32F) {
        cerr << "Error: Feature matrix (X) should have data type CV_32F." << endl;
        return nullptr;
    }

    // Check data type of labels
    if (labels.type() != CV_32F) {
        cerr << "Error: Labels matrix should have data type CV_32F." << endl;
        return nullptr;
    }


    // Create an SVM object
    cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();

    //Set SVM parameters (adjust as needed)
    svm->setC(1.5);
    svm->setKernel(cv::ml::SVM::POLY);
    svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 100, 1e-6));
  
    try {
        // Train the SVM model
        svm->train(X, cv::ml::ROW_SAMPLE, labels);
    }
    catch (const cv::Exception& e) {
        cerr << "Error during SVM training: " << e.msg << endl;
        return nullptr;
    }
    return svm;
}

我正在使用 Visual Studio 2022 和 opencv 4.8.0 这是我的漏洞代码:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <random>
#include <opencv2/ml.hpp>

using namespace std;





vector<float> get_single_img_hog_features(cv::Mat image, int orient, int pixels_per_cell, int cells_per_block) {
    cv::HOGDescriptor hog;
    hog.winSize = image.size();
    hog.blockSize = cv::Size(cells_per_block * pixels_per_cell, cells_per_block * pixels_per_cell);
    hog.blockStride = cv::Size(pixels_per_cell, pixels_per_cell);
    hog.cellSize = cv::Size(pixels_per_cell, pixels_per_cell);
    hog.nbins = orient;

    // Compute HOG descriptors
    vector<float> features;
    hog.compute(image, features, cv::Size(32, 32));

    
    

    return features;
}




// Function to extract features from a single image window
vector<float> single_img_features(cv::Mat img, int orient, int pix_per_cell, int cell_per_block, int hog_channel) {
    cv::Mat img_features;

    cv::cvtColor(img, img_features, cv::COLOR_BGR2RGB);
    
 
        if (hog_channel == -1) { // Compute HOG features for all channels
            vector<vector<float>> hog_channel_features;
            for (int channel = 0; channel < img_features.channels(); ++channel) {
                cv::Mat channel_image;
                cv::extractChannel(img_features, channel_image, channel);
                vector<float> hog_channel_feature = get_single_img_hog_features(channel_image, orient, pix_per_cell, cell_per_block);
                hog_channel_features.push_back(hog_channel_feature);
            }

            vector<float> flattened_vec;
            for (const auto& inner_vec : hog_channel_features) {
                flattened_vec.insert(flattened_vec.end(), inner_vec.begin(), inner_vec.end());
            }

            return flattened_vec;
  
        }
        else { // Compute HOG features for a single channel
            vector<float> hog_features;
            cv::Mat channel_image;
            cv::extractChannel(img_features, channel_image, hog_channel);
            hog_features = get_single_img_hog_features(channel_image, orient, pix_per_cell, cell_per_block);
            return hog_features;
        }
       
   

      
}

// Function to extract features from a list of images
vector<vector<float>> extract_features(vector<string> imgs, int orient, int pix_per_cell, int cell_per_block, int hog_channel) {
    vector<vector<float>> features;
    for (const auto& file : imgs) {
        cv::Mat img = cv::imread(file);
        if (img.empty()) {
            cout << "image file empty" << endl;
            continue; // Skip if unable to read image
        }
        vector<float> file_features = single_img_features(img,orient, pix_per_cell, cell_per_block, hog_channel);
        features.push_back(file_features);
    }
    return features;
}


// Function to perform feature scaling
cv::Mat featureScaling(const cv::Mat& X) {
    cv::Mat scaled_X;
    cv::Scalar mean, stddev;
    cv::meanStdDev(X, mean, stddev);
    scaled_X = (X - mean) / stddev;
    return scaled_X;
}


// Function to shuffle rows of two matrices simultaneously
void shuffle_matrices(cv::Mat& X, cv::Mat& labels) {
    // Check compatibility of sizes
    if (X.rows != labels.rows) {
        cerr << "Error: Matrix dimensions must be equal for shuffling." << endl;
        return;
    }

    // Create a random number generator
    std::random_device rd;
    std::mt19937 g(rd());

    // Shuffle the indices manually
    for (int i = 0; i < X.rows; ++i) {
        // Generate a random index within the range [0, X.rows - 1]
        int random_index = std::uniform_int_distribution<int>(0, X.rows - 1)(g);

        // Swap the current row with the randomly chosen row
        cv::Mat temp_row = X.row(i);
        X.row(i) = X.row(random_index);
        X.row(random_index) = temp_row;

        cv::Mat temp_row_label = labels.row(i);
        labels.row(i) = labels.row(random_index);
        labels.row(random_index) = temp_row_label;
    }
}

tuple<cv::Mat, cv::Mat> prepare_images_for_processing(const vector<string>& car_img_folders, const vector<string>& noncar_img_folders, const string& image_type, int orient, int pix_per_cell, int cell_per_block, int hog_channel) {
    vector<string> cars;
    for (const auto& folder : car_img_folders) {
        // Find all image files in the current folder with the specified image type
        vector<cv::String> filenames;
        cv::glob(folder + "/*." + image_type, filenames, false);
        for (const auto& filename : filenames) {
            cars.push_back(filename);
        }
    }

    vector<string> notcars;
    for (const auto& folder : noncar_img_folders) {
        // Find all image files in the current folder with the specified image type
        vector<cv::String> filenames;
        cv::glob(folder + "/*." + image_type, filenames, false);
        for (const auto& filename : filenames) {
            notcars.push_back(filename);
        }
    }

    cout << "Cars len: " << cars.size() << endl;
    cout << "Notcars len: " << notcars.size() << endl;


    // Keep distribution even
    int train_size = 8500;
    if (cars.size() > train_size) {
        cars.resize(train_size);
    }
    if (notcars.size() > train_size) {
        notcars.resize(train_size);
    }

    // Extract features for car images
    vector<vector<float>> car_features = extract_features(cars, orient, pix_per_cell, cell_per_block, hog_channel);
    // Extract features for non-car images
    vector<vector<float>> notcar_features = extract_features(notcars, orient, pix_per_cell, cell_per_block, hog_channel);

    cout << car_features.size() << endl;

    cout << notcar_features.size() << endl;

    // Concatenate v1 and v2 vertically into a single cv::Mat
    int num_features = car_features[0].size();
    int total_samples = car_features.size() + notcar_features.size();

    // Create a cv::Mat to hold the concatenated data
    cv::Mat X(total_samples, num_features, CV_32FC1);

    // Copy data from v1 to mat
    for (int i = 0; i < car_features.size(); ++i) {
        for (int j = 0; j < num_features; ++j) {
            X.at<float>(i, j) = car_features[i][j];
        }
    }

    // Copy data from v2 to mat
    for (int i = 0; i < notcar_features.size(); ++i) {
        for (int j = 0; j < num_features; ++j) {
            X.at<float>(i + car_features.size(), j) = notcar_features[i][j];
        }
    }


    // Define the labels vector
    cv::Mat labels(X.rows, 1, CV_32FC1);
    labels.rowRange(0, 8500).setTo(1); // Set car labels to 1
    labels.rowRange(8500, total_samples).setTo(0); // Set non-car labels to 0
 
    // Apply the scaler to X
    cv::Mat scaled_X =featureScaling(X);
   


    shuffle_matrices(scaled_X, labels);

    // Return the scaled X, and labels
    return make_tuple(scaled_X, labels);
    
}

// Function to train an SVM model
cv::Ptr<cv::ml::SVM> train_svm_model(const cv::Mat& X, const cv::Mat& labels) {

    if (X.empty() || labels.empty()) {
        cerr << "Error: Feature matrix (X) or labels matrix is empty." << endl;
        return nullptr;
    }

    // Check if dimensions match
    if (X.rows != labels.rows) {
        cerr << "Error: Number of rows in feature matrix (X) does not match the number of labels." << endl;
        return nullptr;
    }

    // Check data type of X
    if (X.type() != CV_32F) {
        cerr << "Error: Feature matrix (X) should have data type CV_32F." << endl;
        return nullptr;
    }

    // Check data type of labels
    if (labels.type() != CV_32F) {
        cerr << "Error: Labels matrix should have data type CV_32F." << endl;
        return nullptr;
    }


    // Create an SVM object
    cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();

    //Set SVM parameters (adjust as needed)
    svm->setC(1.5);
    svm->setKernel(cv::ml::SVM::POLY);
    svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 100, 1e-6));
  
    try {
        // Train the SVM model
        svm->train(X, cv::ml::ROW_SAMPLE, labels);
    }
    catch (const cv::Exception& e) {
        cerr << "Error during SVM training: " << e.msg << endl;
        return nullptr;
    }
    return svm;
}

// Function to save the trained SVM model
void save_svm_model(cv::Ptr<cv::ml::SVM> svm, const string& filename) {
    svm->save(filename);
}



int main() {
   
    // Define parameters
    vector<string> car_folders = { "C:/Users/DELL/Desktop/vehicle-detection-with-svm/vehicles/GTI_Far", "C:/Users/DELL/Desktop/vehicle-detection-with-svm/vehicles/GTI_Left", "C:/Users/DELL/Desktop/vehicle-detection-with-svm/vehicles/GTI_MiddleClose", "C:/Users/DELL/Desktop/vehicle-detection-with-svm/vehicles/GTI_Right", "C:/Users/DELL/Desktop/vehicle-detection-with-svm/vehicles/KITTI_extracted" };
    vector<string> notcar_folders = { "C:/Users/DELL/Desktop/vehicle-detection-with-svm/non-vehicles/Extras", "C:/Users/DELL/Desktop/vehicle-detection-with-svm/non-vehicles/GTI" };
    string image_type = "png";
    int orient = 9;
    int pix_per_cell = 8;
    int cell_per_block = 2;
    int hog_channel = -1;


   
    tuple<cv::Mat, cv::Mat> processed_data = prepare_images_for_processing(car_folders, notcar_folders, image_type, orient, pix_per_cell, cell_per_block, hog_channel);

    // Unpack the processed data
    cv::Mat scaled_X = get<0>(processed_data);
    cv::Mat labels = get<1>(processed_data);

    // Split data into training and testing sets (adjust split ratio as needed)
    int train_size = 0.8 * scaled_X.rows;
    cv::Mat X_train = scaled_X.rowRange(0, train_size);
    cv::Mat X_test = scaled_X.rowRange(train_size, scaled_X.rows);
    cv::Mat labels_train = labels.rowRange(0, train_size);
    cv::Mat labels_test = labels.rowRange(train_size, labels.rows);



    // Train the SVM model
    cv::Ptr<cv::ml::SVM> svm_model = train_svm_model(X_train, labels_train);

    // Save the trained SVM model
    //save_svm_model(svm_model, "C:/Users/DELL/Desktop/svm_model.xml"); // Replace with your desired filename

    

    return 0;

}
c++ visual-studio opencv svm
1个回答
0
投票

您可以尝试打印 X 和标签的所有值来检查它们是否包含任何 NaN 或 Inf 值。

© www.soinside.com 2019 - 2024. All rights reserved.