Search code examples
javaopencvcaptchajavacv

JavaCV detect captcha letters on a binary image


I'm new to JavaCv. My task is to find symbols on an image and generate pictures with single symbol on each other. Firstly, I have this picture:enter image description here Then I do thresholding and get this: enter image description here I'm trying to use cvFindContours an then draw a rectangle around each symbol, my code:

 String filename = "captcha.jpg";
    IplImage firstImage=cvLoadImage(filename);
    Mat src = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
    Mat dst = new Mat();
   threshold(src, dst, 200, 255, 0);
   imwrite("out.jpg", dst);

    IplImage iplImage=cvLoadImage("out.jpg",CV_8UC1);
    CvMemStorage memStorage=CvMemStorage.create();
    CvSeq contours=new CvSeq();
    cvFindContours(iplImage,memStorage,contours,Loader.sizeof(CvContour.class),CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));
    CvSeq ptr;
    CvRect bb;
    for (ptr=contours;ptr!=null;ptr=ptr.h_next()){
        bb=cvBoundingRect(ptr);
        cvRectangle(firstImage , cvPoint( bb.x(), bb.y() ),
                cvPoint( bb.x() + bb.width(), bb.y() + bb.height()),
                CvScalar.BLACK, 2, 0, 0 );

    }
    cvSaveImage("result.jpg",firstImage);
}

I want to get output like this:enter image description here, but really I get this:enter image description here

Please, need your help.


Solution

  • You're using "out.jpg" image for findContour().
    When you save dst Mat into "out.jpg", JPEG format automatically quantizes your original pixel data and creates noises to your image.

    Save dst to "out.png" rather than "out.jpg", or use dst Mat directly into findContour().

    Source Code ADDED: C++ version

    string filename = "captcha.jpg";
    Mat src = imread(filename);
    Mat gray;
    cvtColor(src, gray, CV_BGR2GRAY);
    Mat thres;
    threshold(gray, thres, 200, 255, 0);
    
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    
    findContours(thres.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
    
    Mat firstImage = src.clone();
    for(int i=0; i< contours.sizes(); i++)
    {
        Rect r = boundingRect(contours[i]);
        rectangle(firstImage, r, CV_RGB(255, 0, 0), 2);
    }
    
    imwrite("result.png", firstImage);