openCV c ++: problemas al trabajar con CvBoost (Adaboost classifer)
Estoy creando una aplicación para clasificar a los humanos en imágenes de entornos urbanos.
Entreno a un clasificador de la siguiente manera:
int main (int argc, char **argv)
{
/* STEP 2. Opening the file */
//1. Declare a structure to keep the data
CvMLData cvml;
//2. Read the file
cvml.read_csv ("directory/train_rand.csv");
//3. Indicate which column is the response
cvml.set_response_idx (0);
/* STEP 3. Splitting the samples */
//1. Select 4000 for the training
CvTrainTestSplit cvtts (4000, true);
//2. Assign the division to the data
cvml.set_train_test_split (&cvtts);
printf ("Training ... ");
/* STEP 4. The training */
//1. Declare the classifier
CvBoost boost;
//2. Train it with 100 features
boost.train (&cvml, CvBoostParams (CvBoost::REAL,100, 0, 1, false, 0),
false);
/* STEP 5. Calculating the testing and training error */
// 1. Declare a couple of vectors to save the predictions of each sample
std::vector<float> train_responses, test_responses;
// 2. Calculate the training error
float fl1 = boost.calc_error (&cvml, CV_TRAIN_ERROR, &train_responses);
// 3. Calculate the test error
float fl2 = boost.calc_error (&cvml, CV_TEST_ERROR, &test_responses);
cout<<"Error train: "<<fl1<<endl;
cout<<"Error test: "<<fl2<<endl;
/* STEP 6. Save your classifier */
// Save the trained classifier
boost.save ("./trained_boost_4000samples-100ftrs.xml", "boost");
return 0;
}
train_rand.csv es un archivo donde la primera columna es la categoría. El resto de las columnas serán las características del problema. Por ejemplo, podría haber usado tres características. Cada uno de ellos representa el promedio de rojo, azul y verde por píxel en la imagen. Así que mi archivo csv debería verse así. Tenga en cuenta que en la primera columna estoy usando un carácter, por lo que OpenCV reconoce eso como una categoría.
B,124.34,45.4,12.4
B,64.14,45.23,3.23
B,42.32,125.41,23.8
R,224.4,35.34,163.87
R,14.55,12.423,89.67
...
Para mi problema real, estoy usando 100 características y 8000 muestras. Entreno al clasificador con la mitad de los datos y los pruebo con el resto.
Después del entrenamiento, obtengo un error de prueba de alrededor del 5% (lo cual es bastante bueno para solo 100 funciones).
Ahora quiero usar el clasificador en nuevos datos:
CvBoost boost
boost.load("directory/trained_boost_4000samples-100ftrs.xml");
float x = boost.predict(SampleData,Mat(),Range::all(),false,false);
cout<<x;
Estoy ejecutando este código en miles de muestras y siempre genera el mismo valor, que es 2. Realmente no entiendo lo que estoy haciendo mal aquí, pero incluso si entrenara para clasificar de forma incorrecta, no clasificaría el 100% de las veces de la misma manera, el error de prueba que calculé antes muestra que El clasificador debería funcionar bien.
Una cosa que me molesta es que SampleData tiene que tener el mismo número de columnas que la muestra que solía entrenar. La cuestión es que los datos utilizados para entrenar tienen 100 columnas + 1 respuesta, y si intento ejecutar el clasificador con solo 100 características, se produce una excepción que dice que los tamaños no coinciden. Si ejecuto el clasificador con 101 características (lo cual es absolutamente arbitrario), funciona, pero los resultados no tienen ningún sentido.
Puede alguien ayudarme con esto? ¡Gracias por adelantado!
Saludos