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"); }