Ask Your Question
0

PCA returns NaN

asked 2016-08-02 07:55:51 -0600

ahmad_asadi gravatar image

updated 2016-08-02 08:35:38 -0600

Hi everybody,

I'm attempting to classify 10 classes of hand pictures using a specific feature space. Training data is converted to a Mat object containing 240 rows (number of training pictures) and 480 cols (number of features) normalized between 0 and 1. The type of training data mat is CV_64FC1. I'm going to pass this matrix to PCA in order to extract useful features. After that I want to pass PCA result to SVM in order to train a classifier.

The PCA object returns all -NaN and Inf after creating the object:

PCA pca(training_data_mat, Mat(), CV_PCA_DATA_AS_ROW);

training_data_mat is the matrix of the training data with 240 rows and 450 cols for 240 training images and 450 features. It is created in the following line:

training_data_mat.push_back(extract_features_mat(descriptor,hog_ders)) ;

the extract_features_mat function is written such that returns a 1 row Mat of type CV_64FC1 containing features of the image. The following line is return value of the extract_features_mat function:

return Mat (1,feature_size, CV_64FC1, feature_value) ;

and feature_value is a double array defined and filled in this function.

I'm totally confused what is wrong!

This is my extract_features_mat function:

Mat extract_features_mat(Mat descriptor, std::vector<float> hog_ders)
{
        int feature_size = descriptor.cols + hog_ders.size() ;
        double feature_value[feature_size] ;
        double gamma = 0.05 ;
        for(int j = 0 ; j < descriptor.cols ; j++)
        {
            feature_value[j] = 0 ;
            for(int h = 0 ; h < descriptor.rows ; h++)
            {
                double to_be_added_value = (descriptor.at<double>(h,j)/pow(10,15) ) ;
                feature_value[j] += to_be_added_value;
                if(feature_value[j] > 1)
                    feature_value[j] = 1 ;
            }   
        }

        float max = 0 ;
        for(int j = 0 ; j < descriptor.cols ; j++)
        {
            if(feature_value[j] < 0.1 )
                feature_value[j] = 0.1 ;
            feature_value[j] = 1 * pow(feature_value[j],gamma) ;
            if(max < feature_value[j])
                max = feature_value[j] ;
        }

        for(int j =0 ; j < descriptor.cols ; j++)
            feature_value[j] = feature_value[j] / max ; 
        max = 0 ;
        for(int j = descriptor.cols ; j < descriptor.cols + hog_ders.size() ; j++)
        {
            feature_value[j] = hog_ders.at(j - descriptor.cols) ;
            if(max < feature_value[j])
                max = feature_value[j] ;
        }   
        for(int j = descriptor.cols ; j < descriptor.cols + hog_ders.size() ; j++)
            feature_value[j] = feature_value[j] / max ; 

        return Mat(1,feature_size, CV_64FC1, feature_value) ;
}
edit retag flag offensive close merge delete

Comments

are you sure about CV_64F ? if it's hog descriptors, those are CV_32F.

berak gravatar imageberak ( 2016-08-02 08:00:39 -0600 )edit
1

hog_ders is right now the vector of image histogram not HOG descriptors. However, converting the type to CV_32F does not change anything.

ahmad_asadi gravatar imageahmad_asadi ( 2016-08-02 08:03:42 -0600 )edit

where exactly do you get those NaN's ? can you show more code ?

also, if your goal is, to reduce the number of cols, you'd want to pass the new number as last arg to the PCA()

berak gravatar imageberak ( 2016-08-02 08:08:30 -0600 )edit

I check eigenvalues after that. All values are -NaN:

Mat average = Mat();
PCA pca(training_data_mat, average, CV_PCA_DATA_AS_ROW);

cout << "checking pca... " << endl ;
cout << pca.eigenvalues << endl ;
ahmad_asadi gravatar imageahmad_asadi ( 2016-08-02 08:13:38 -0600 )edit

In addition, transposing data_training_mat tends to appearance of some small numbers inside a bunch of NaNs and Infs in eigenvalues, if it clarifies some points!

ahmad_asadi gravatar imageahmad_asadi ( 2016-08-02 08:23:57 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2016-08-02 08:44:20 -0600

berak gravatar image

updated 2016-08-02 09:12:34 -0600

your returned Mat from extract_features_mat() is invalid.

if you construct a Mat with a "borrowed" data pointer, it is just doing a "shallow" copy, only the pointer gets copiied, not the data, so once the original pointer goes out of scope (because it is local, and you return from the function), you got a "dangling" pointer.

try :

return Mat(1, feature_size, CV_64FC1, feature_value).clone() ;

to achieve a "deep" copy.

better even, avoid the whole situation, allocate your Mat properly at the beginning of your function, and use it's data, instead of a seperate double []:

Mat extract_features_mat(Mat descriptor, std::vector<float> hog_ders)
{
        int feature_size = descriptor.cols + hog_ders.size() ;
        Mat result(1, feature_size, CV_64FC1) ; 
        double *feature_value = result.ptr<double>(0);

        //
        // calculate feature_value, like before
        //

        return result;
}
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2016-08-02 07:55:51 -0600

Seen: 782 times

Last updated: Aug 02 '16