Пример #1
0
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;
}
Пример #3
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;
}