Exemple #1
0
void recognizeDigits(IplImage* undistorted, int sudo[9][9], int byteOrder) {
    int offset = 5; // offest
    int imgWidth = undistorted->width;
    int imgHeight = undistorted->height;
    int sqrWidth = imgWidth/9+1;
    int sqrHeight = imgWidth/9+1;

    IplImage* greyPic = cvCreateImage(
                            cvGetSize(undistorted),
                            IPL_DEPTH_8U,
                            1
                        );
    int values[] = {0,1,0,1,1,1,0,1,0};
    IplConvKernel* kernal = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CUSTOM,values);
    IplImage* temp = cvCreateImage(cvGetSize(undistorted),IPL_DEPTH_8U,1);
    cvCopy(undistorted,temp);
    cvSmooth(temp,temp,CV_GAUSSIAN,3,3);
    cvAdaptiveThreshold(temp, greyPic, 255, CV_ADAPTIVE_THRESH_MEAN_C,
                        CV_THRESH_BINARY_INV, 5,2);
    cvDilate(greyPic,greyPic,kernal);

    int coX = 0;  // The x coordinate of topleft vertex in the inner box
    int coY = 0;  // The y coordinate of topleft vertex in the inner box
    int coXL = 0; // The x coordinate of left edge
    int coXR = 0; // The x coordinate of right edge
    int coYT = 0; // The y coordinate of top edge
    int coYB = 0; // The y coordinate of bottom edge
    int midX = 0;
    int midY = 0;
    int width = 0;
    int height = 0;
    int detectThresholdX = 0;
    int detectThresholdY = 0;
    int widthThreshold = 0;
    int heightThreshold = 0;
    int areaThreshold = 50;  // areaThreshold
    int row = 0 ;
    int col = 0;
    int digitX = -1;
    int digitY = -1;
    int digitWidth = -1;
    int digitHeight = -1;
    CvPoint maxPoint;
    bool findNO = false;
    IplImage* piece;
    CvConnectedComp a = CvConnectedComp();
    CvConnectedComp* comp = &a;
    char dataPath[] = "/sdcard/Train/myTrainData";
    char labelPath[] = "/sdcard/Train/myTrainClasses";
    DigitReader rd = DigitReader();
    if(rd.train(dataPath,labelPath,byteOrder)) {
        for(row = 0 ; row< 9; row++) {
            coY = row * sqrHeight;
            for(col = 0; col < 9 ; col++) {
                coX = col * sqrWidth;
                digitX = -1;
                digitY = -1;
                digitWidth = -1;
                digitHeight = -1;
                // Calculate the outerbox
                if(coX - offset < 0) {
                    coXL = 0;
                } else {
                    coXL = coX - (1.5)*offset;
                }

                if(coX + offset + sqrWidth >imgWidth) {
                    coXR = imgWidth;
                } else {
                    coXR = coX  + sqrWidth;
                }

                if(coY - offset <0) {
                    coYT = 0;
                } else {
                    coYT = coY - (1.5)*offset;
                }

                if(coY + offset + sqrHeight > imgHeight) {
                    coYB = imgHeight;
                } else {
                    coYB = coY + sqrHeight;
                }

                width = coXR - coXL - offset;
                height = coYB - coYT- offset;

                cvSetImageROI(greyPic,cvRect(coXL,coYT,width,height));
                piece = cvCreateImage(cvGetSize(greyPic),IPL_DEPTH_8U,1);
                cvCopy(greyPic,piece);

                detectThresholdY = height/4 +1;
                detectThresholdX = width/4 +1;
                widthThreshold = 2*width/3;
                heightThreshold = 3*height/4;
                midX = ( width+1 ) / 2;
                midY = ( height+1 ) / 2;
                int x = midX+2*offset;
                int y = midY+2*offset;

                for(; (x>detectThresholdX)&&(y>detectThresholdY); x--, y--) {
                    findNO = false;
                    uchar* ptr = (uchar*)(piece->imageData + y*piece->widthStep);
                    if(ptr[x]>128) {
                        cvFloodFill(piece,cvPoint(x,y),CV_RGB(0,0,64),cvScalarAll(0),cvScalarAll(0),comp);;
                        if((comp->rect.height<heightThreshold)&&(comp->rect.width<widthThreshold)&& (comp->area>areaThreshold)) {
                            findNO = true;
                            maxPoint = cvPoint(x,y);
                            digitX = comp->rect.x;
                            digitY = comp->rect.y;
                            digitWidth = comp->rect.width;
                            digitHeight = comp->rect.height;
                            cvFloodFill(piece,cvPoint(x,y),CV_RGB(0,0,128));
                            break;
                        }
                    }
                }
                if(findNO) {
                    for(int i = 0; i< height ; i++) {

                        uchar* ptr = (uchar*)(piece->imageData + i*piece->widthStep);
                        for(int j = 0; j<width; j++) {

                            if(ptr[j]!=128&&ptr[j]!=0) {
                                if((j==width-1)||(i==height-1)) {

                                } else {
                                    cvFloodFill(piece,cvPoint(j,i),CV_RGB(0,0,0));
                                }
                            }
                        }
                    }
                    cvFloodFill(piece,maxPoint,CV_RGB(0,0,255));
                    cvErode(piece,piece,kernal);

                    CvMat* test = convertFormat(piece,digitX,digitY,digitWidth,digitHeight);
                    int digit = rd.recognize(test);
                    //	int digit = 2;
                    sudo[row][col] = digit;
                } else {
                    sudo[row][col] = 0;
                }

                cvResetImageROI(greyPic);
                cvReleaseImage(&piece);
            }

        }
        cvReleaseImage(&undistorted);
        cvReleaseImage(&greyPic);
    } else {
        sudo = NULL;
    }



}
void detectSudoku(IplImage* pic){

	int offset = 2; // offest
	int imgWidth = pic->width;
	int imgHeight = pic->height;
	int sqrWidth = imgWidth/9+1;
	int sqrHeight = imgWidth/9+1;
	int sudoku[9][9] = {{0}};

	IplImage* greyPic = cvCreateImage(
		cvGetSize(pic),
		IPL_DEPTH_8U,
		1
	);

	IplImage* temp = cvCreateImage(cvGetSize(pic),IPL_DEPTH_8U,1);
	cvCopy(pic,temp);
	//cvDilate(temp,temp);
	cvSmooth(temp,temp,CV_GAUSSIAN,5,5);
	cvAdaptiveThreshold(temp, greyPic, 255, CV_ADAPTIVE_THRESH_MEAN_C,
						CV_THRESH_BINARY_INV, 5,2);
	int coX = 0;  // The x coordinate of topleft vertex in the inner box
	int coY = 0;  // The y coordinate of topleft vertex in the inner box
	int coXL = 0; // The x coordinate of left edge
	int coXR = 0; // The x coordinate of right edge
	int coYT = 0; // The y coordinate of top edge
	int coYB = 0; // The y coordinate of bottom edge
	int midX = 0;
	int midY = 0;
	int width = 0;
	int height = 0;
	int detectThresholdX = 0;
	int detectThresholdY = 0;
	int widthThreshold = 0;
	int heightThreshold = 0;
	int areaThreshold = 50;  // areaThreshold
	int row = 0 ;
	int col = 0;
	int digitX = -1;
	int digitY = -1;
	int digitWidth = -1;
	int digitHeight = -1;
	CvPoint maxPoint;
	bool findNO = false;
	//cvNamedWindow("Piece");
	IplImage* piece;
	CvConnectedComp a = CvConnectedComp();
	CvConnectedComp* comp = &a;
	//char dataPath[] = "Train/train-images.idx3-ubyte";
	//char labelPath[] = "Train/train-labels.idx1-ubyte";
	char dataPath[] = "Train/myTrainData";
	char labelPath[] = "Train/myTrainClasses";
	DigitReader rd = DigitReader();
	rd.train(dataPath,labelPath,LOW_ENDIAN);

	for(row = 0 ; row< 9; row++){
		coY = row * sqrHeight;
		for(col = 0; col < 9 ; col++){
			coX = col * sqrWidth;
			digitX = -1;
			digitY = -1;
			digitWidth = -1;
			digitHeight = -1;
			// Calculate the outerbox
			if(coX - offset < 0){
				coXL = 0;
			}else {
				coXL = coX - offset;
			}

			if(coX + offset + sqrWidth >imgWidth){
				coXR = imgWidth;
			}else{
				coXR = coX + offset + sqrWidth;
			}

			if(coY - offset <0){
				coYT = 0;
			}else{
				coYT = coY - offset;
			}

			if(coY + offset + sqrHeight > imgHeight){
				coYB = imgHeight;
			}else{
				coYB = coY + offset + sqrHeight;
			}

			width = coXR - coXL + 1;
			height = coYB - coYT + 1;

			cvSetImageROI(greyPic,cvRect(coXL,coYT,width,height));
			piece = cvCreateImage(cvGetSize(greyPic),IPL_DEPTH_8U,1);
			cvCopy(greyPic,piece);
			//cvShowImage("Piece",piece);
			//cvWaitKey(0);

			detectThresholdY = height/4 +1;
			detectThresholdX = width/4 +1;
			widthThreshold = 2*width/3;
			heightThreshold = 3*height/4;
			midX = ( width+1 ) / 2;
			midY = ( height+1 ) / 2;
			int x = midX+5;
			int y = midY+5;

			for(;(x>detectThresholdX)&&(y>detectThresholdY); x--, y--){
				findNO = false;
				uchar* ptr = (uchar*)(piece->imageData + y*piece->widthStep);
				if(ptr[x]>128){
					cvFloodFill(piece,cvPoint(x,y),CV_RGB(0,0,64),cvScalarAll(0),cvScalarAll(0),comp);;
					if((comp->rect.height<heightThreshold)&&(comp->rect.width<widthThreshold)&& (comp->area>areaThreshold)){
						findNO = true;
						maxPoint = cvPoint(x,y);
						digitX = comp->rect.x;
						digitY = comp->rect.y;
						digitWidth = comp->rect.width;
						digitHeight = comp->rect.height;
						cvFloodFill(piece,cvPoint(x,y),CV_RGB(0,0,128));
						//cvShowImage("Piece",piece);
						//cvWaitKey(0);
						break;
					}
				}
			}
			if(findNO){
				for(int i = 0; i< height ; i++){

					uchar* ptr = (uchar*)(piece->imageData + i*piece->widthStep);
					for(int j = 0; j<width; j++){

						if(ptr[j]!=128&&ptr[j]!=0){
							if((j==width-1)||(i==height-1)){

							}else{
								cvFloodFill(piece,cvPoint(j,i),CV_RGB(0,0,0));
								//cvShowImage("Piece",piece);
								//cvWaitKey(0);
							}
						}
					}
				}
				cvFloodFill(piece,maxPoint,CV_RGB(0,0,255));
				//cvShowImage("Piece",piece);
				//cvWaitKey(0);
				CvMat* test = convertFormat(piece,digitX,digitY,digitWidth,digitHeight);
				int digit = rd.recognize(test);
				sudoku[row][col] = digit;
			}else{
				sudoku[row][col] = 0;
			}



			//cvShowImage("Piece",piece);
			//cvWaitKey(0);
			cvResetImageROI(greyPic);
			cvReleaseImage(&piece);
		}

	}

	for(int i = 0; i<9;i++){
		for(int j = 0; j<9; j++){
			printf("%d ", sudoku[i][j]);
		}
		printf("\n");
	}

//	cvNamedWindow("GreyPic");
//	cvShowImage("GreyPic",greyPic);
//	cvReleaseImage(&greyPic);

//	cvWaitKey(0);

//	cvDestroyWindow("GreyPic");
}