int classify_emotion(Mat& face, const char* ann_file, int tagonimg) { int ret = 0; Mat output(1, OUTPUT_SIZE, CV_64FC1); Mat data(1, nn_input_size, CV_64FC1); CvANN_MLP nnetwork; nnetwork.load(ann_file, "facial_ann"); vector<Point_<double> > points; vector<double> distances; if(!get_facial_points(face, points)) { return -1; } get_euler_distance_sets(points, distances); int j = 0; while(!distances.empty()) { data.at<double>(0,j) = distances.back(); distances.pop_back(); j++; } nnetwork.predict(data, output); /* Find the biggest value in the output vector, that is what we want. */ double b = 0; int k = 1; for (j = 0; j < OUTPUT_SIZE; j++) { cout<<output.at<double>(0, j)<<" "; if (b < output.at<double>(0, j)) { b = output.at<double>(0, j); k = j + 1; } } /* Print the result on the image. */ if (tagonimg) { putText(face, get_emotion(k), Point(30, 30), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 255, 0), 2); draw_distance(face, points); } return k; }
static int build_mlp_classifier( char* data_filename, char* filename_to_save, char* filename_to_load ) { const int class_count = 26; CvMat* data = 0; CvMat train_data; CvMat* responses = 0; CvMat* mlp_response = 0; int ok = read_num_class_data( data_filename, 16, &data, &responses ); int nsamples_all = 0, ntrain_samples = 0; int i, j; double train_hr = 0, test_hr = 0; CvANN_MLP mlp; if( !ok ) { printf( "Could not read the database %s\n", data_filename ); return -1; } printf( "The database %s is loaded.\n", data_filename ); nsamples_all = data->rows; ntrain_samples = (int)(nsamples_all*0.8); // Create or load MLP classifier if( filename_to_load ) { // load classifier from the specified file mlp.load( filename_to_load ); ntrain_samples = 0; if( !mlp.get_layer_count() ) { printf( "Could not read the classifier %s\n", filename_to_load ); return -1; } printf( "The classifier %s is loaded.\n", data_filename ); } else { // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // // MLP does not support categorical variables by explicitly. // So, instead of the output class label, we will use // a binary vector of <class_count> components for training and, // therefore, MLP will give us a vector of "probabilities" at the // prediction stage // // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CvMat* new_responses = cvCreateMat( ntrain_samples, class_count, CV_32F ); // 1. unroll the responses printf( "Unrolling the responses...\n"); for( i = 0; i < ntrain_samples; i++ ) { int cls_label = cvRound(responses->data.fl[i]) - 'A'; float* bit_vec = (float*)(new_responses->data.ptr + i*new_responses->step); for( j = 0; j < class_count; j++ ) bit_vec[j] = 0.f; bit_vec[cls_label] = 1.f; } cvGetRows( data, &train_data, 0, ntrain_samples ); // 2. train classifier int layer_sz[] = { data->cols, 100, 100, class_count }; CvMat layer_sizes = cvMat( 1, (int)(sizeof(layer_sz)/sizeof(layer_sz[0])), CV_32S, layer_sz ); mlp.create( &layer_sizes ); printf( "Training the classifier (may take a few minutes)...\n"); mlp.train( &train_data, new_responses, 0, 0, CvANN_MLP_TrainParams(cvTermCriteria(CV_TERMCRIT_ITER,300,0.01), #if 1 CvANN_MLP_TrainParams::BACKPROP,0.001)); #else CvANN_MLP_TrainParams::RPROP,0.05)); #endif cvReleaseMat( &new_responses ); printf("\n"); } mlp_response = cvCreateMat( 1, class_count, CV_32F ); // compute prediction error on train and test data for( i = 0; i < nsamples_all; i++ ) { int best_class; CvMat sample; cvGetRow( data, &sample, i ); CvPoint max_loc = {0,0}; mlp.predict( &sample, mlp_response ); cvMinMaxLoc( mlp_response, 0, 0, 0, &max_loc, 0 ); best_class = max_loc.x + 'A'; int r = fabs((double)best_class - responses->data.fl[i]) < FLT_EPSILON ? 1 : 0; if( i < ntrain_samples ) train_hr += r; else test_hr += r; } test_hr /= (double)(nsamples_all-ntrain_samples); train_hr /= (double)ntrain_samples; printf( "Recognition rate: train = %.1f%%, test = %.1f%%\n", train_hr*100., test_hr*100. ); // Save classifier to file if needed if( filename_to_save ) mlp.save( filename_to_save ); cvReleaseMat( &mlp_response ); cvReleaseMat( &data ); cvReleaseMat( &responses ); return 0; }
int CTrain::excuteIndefine() { char path[256] = {0}; int i_c = 4; sprintf_s(path,"./sample/%d (%d).bmp",i_c,5); IplImage *pSourec = cvLoadImage(path); if(nullptr == pSourec){ cout<<"features:"<<path<<" is not vailed"<<endl; return -1; } cout<<"start idenfie:" << path<<endl; #ifdef Debug cvNamedWindow("source"); cvShowImage("source", pSourec); #endif //out IplImage *pOut = nullptr; //opencv 灰度化 IplImage *gray = cvCreateImage(cvGetSize(pSourec), IPL_DEPTH_8U, 1); cvCvtColor(pSourec, gray, CV_BGR2GRAY); //opencv 二值化 cvThreshold(gray, gray, 175, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); //去边框 cvRectangle(gray, cvPoint(0, 0), cvPoint(gray->width-1, gray->height-1), CV_RGB(255, 255, 255)); #ifdef Debug cvNamedWindow("cvRectangle"); cvShowImage("cvRectangle", gray); #endif //去噪 //IplConvKernel *se = cvCreateStructuringElementEx(2, 2, 1, 1, CV_SHAPE_CROSS); //cvDilate(gray, gray, se); #ifdef Debug //cvNamedWindow("IplConvKernel"); //cvShowImage("IplConvKernel", gray); #endif //计算连通域contoure cvXorS(gray, cvScalarAll(255), gray, 0); #ifdef Debug cvNamedWindow("cvXorS"); cvShowImage("cvXorS", gray); #endif CvMemStorage *storage = cvCreateMemStorage(); CvSeq *contour = nullptr; cvFindContours(gray, storage, &contour, sizeof(CvContour),CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); //分析连通域 CvSeq *p = contour; while(p){ CvRect rect = cvBoundingRect(p, 0); if(rect.height < 10){//图像文字需要15像素高度 p = p->h_next; continue; } //绘制该连通到character cvZero(gray); IplImage *character = cvCreateImage(cvSize(rect.width, rect.height), IPL_DEPTH_8U, 1); cvZero(character); cvDrawContours(character, p, CV_RGB(255, 255, 255), CV_RGB(0, 0, 0), -1, -1, 8, cvPoint(-rect.x, -rect.y)); #ifdef Debug cvNamedWindow("character"); cvShowImage("character", character); #endif // 归一化 pOut = cvCreateImage(cvSize(16, 16), IPL_DEPTH_8U, 1); cvResize(character, pOut, CV_INTER_AREA); #ifdef Debug cvNamedWindow("cvResize"); cvShowImage("cvResize", pOut); #endif // 修正 cvThreshold(pOut, pOut, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); #ifdef Debug cvNamedWindow("show"); cvShowImage("show", pOut); #endif //cvReleaseImage(&character); p = p->h_next; } // 计算输入向量 float input[256]; for(int i=0; i<256; i++) input[i] = (pOut->imageData[i]==-1); // 识别 CvANN_MLP mlp; mlp.load( "mpl.xml" ); CvMat* output = cvCreateMat( 1, 36, CV_32F ); CvMat inputMat = cvMat( 1, 256, CV_32F, input); mlp.predict( &inputMat, output ); CvPoint max_loc = {0,0}; cvMinMaxLoc( output, NULL, NULL, NULL, &max_loc, NULL ); int best = max_loc.x;// 识别结果 char c = (char)( best<10 ? '0'+best : 'A'+best-10 ); cout<<"indefine="<<c<<"<=====>pratics="<<i_c<<endl; cvReleaseMat( &output ); cvReleaseImage(&gray); cvReleaseImage(&pOut); cvReleaseImage(&pSourec); cvReleaseMemStorage(&storage); //cvReleaseStructuringElement(&se); #ifdef Debug cvWaitKey(0); cvDestroyAllWindows(); #endif return 0; }