You can segment the number easily using watershed() for this you need to create markers to distinguish foreground and background.
1. Create Mask: As first step we will create make image, you need to do adaptiveThreshold(), contour finding(largest), convexHull() etc..
Below is the code how to do it
Mat src=imread("src.jpg",1);
Mat thr,gray;
cvtColor(src,gray,CV_BGR2GRAY);
adaptiveThreshold(gray,thr,255,ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY,51,5);
vector< vector <Point> > contours; // Vector for storing contour
vector< Vec4i > hierarchy;
int largest_contour_index=0;
int largest_area=0;
Mat mask(src.rows,src.cols,CV_8UC1,Scalar::all(0)); //create destination image
findContours( thr.clone(), contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image
for( int i = 0; i< contours.size(); i++ ) // iterate through each contour.
{
double a=contourArea( contours[i],false); // Find the area of contour
if(a>largest_area){
largest_area=a;
largest_contour_index=i; //Store the index of largest contour
}
}
vector<vector<Point> >hull(1);
convexHull(contours[largest_contour_index], hull[0],false,true );
drawContours( mask, hull, 0, Scalar(125), -1, 8, vector<Vec4i>(), 0, Point() );
2. Create Foreground: For this you need to do again adaptiveThreshold() but with THRESH_BINARY_INV option, and erode() result to reduce noise, finally find biggest contour which represent your foreground object, here you need to consider the mask while copying to foreground image. The result look like the object to be segmented, but for better result we will move to next steps like background creation, watershed etc..
Mat fg;
adaptiveThreshold(gray,thr,255,ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV,151,5);
erode(thr,thr,Mat(),Point(-1,-1),1);
contours.clear();
hierarchy.clear();
largest_contour_index=0;
largest_area=0;
thr.copyTo(fg,mask),
findContours( fg, contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image
for( int i = 0; i< contours.size(); i++ ) // iterate through each contour.
{
double a=contourArea( contours[i],false); // Find the area of contour
if(a>largest_area){
largest_area=a;
largest_contour_index=i; //Store the index of largest contour
}
}
fg.setTo(0);
drawContours( fg,contours, largest_contour_index, Scalar(255),CV_FILLED, 8, hierarchy );
3. Create Background: Creating background marker is easy as you have mask and foreground just subtract foreground from mask, then apply erode() to make little separation between fg and bg while merging.
Mat bg=mask-fg;
erode(bg,bg,Mat(),Point(-1,-1),7);
4. Create Marker for Watershed: Just add up fg and bg and convert CV_32S for passing watershed()
5. Perform watershed Operation: Here you need to pass this marker image along with your source image.
markers.convertTo(markers, CV_32S);
watershed(src, markers);
markers.convertTo(markers,CV_8U);
imshow("Segmented",markers);
What have you tried? And you might want to follow:
http://stackoverflow.com/questions/15188104/character-recognition-ocr-algorithm
@Nagaraj So your sample image always be like this only ?
@prakharmohan , Ya I tried I have done threshold and segmentation . Due to uneven contrast of the image I will get too much noise and tesseract won't detect . plz can u suggest me how can extract 1 from this image without background .
@Haris Moonamkunnu , Yes my sample image is like this only
@Haris Moonamkunnu, Sir, thanks a lot :)
Welcome.........
@Nagaraj Accept the answer if it is working then!
first you have good lighting. Metal tends to be reflective so it's good that you have the camera above the number and the light source from the side. Next you need a image of each number. I would then think you could use one of the object detectors.
@GrumbleLion thanks for the info :)