Deskew Image using FitElipse angle

asked 2017-11-30 16:27:17 -0500

rc gravatar image

updated 2017-12-02 15:47:40 -0500

I am preparing an image containing a character (the digit '4') for subsequent OCR.

I start by fit an ellipse to a thresholded image, then deskew it using the angle of the elipse as the input to a rotation matix followed by an affine transform.C:\fakepath\4.png

Despite my best attempts and the various workarounds suggested for the angle returned from fitelipse, i cannot get the letter vertically aligned.

code is as follows and the results attached

C:\fakepath\elipse.png C:\fakepath\threshold.png C:\fakepath\Rotated.png

Latest Rotated

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

    int affineFlags = WARP_INVERSE_MAP|INTER_LINEAR;
    Mat input = Imgcodecs.imread("4.png");
    Mat grayImage = new Mat(input.size(), CV_8UC1 );

    // convert the frame in gray scale
    Imgproc.cvtColor(input, grayImage, Imgproc.COLOR_BGR2GRAY);

    Core.bitwise_not(grayImage, grayImage);
    Mat threshold = new Mat(grayImage.rows(), grayImage.cols(),grayImage.type());
    Imgproc.threshold(grayImage, threshold, 0, 255, THRESH_OTSU);

    Imgcodecs.imwrite("threshold.png", threshold);
    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
    Mat hierarchy = new Mat();

    Imgproc.findContours(threshold, contours, new Mat(), Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);

    double angle=0;

    for(MatOfPoint mp : contours)
    {
        //RotatedRect rr = Imgproc.minAreaRect(new MatOfPoint2f(mp.toArray()));

        if(mp.total() > 35) // Cheat to find the biggest contour.
        {
            RotatedRect elipse = Imgproc.fitEllipse(new MatOfPoint2f(mp.toArray()));
            Imgproc.ellipse(input, elipse, new Scalar(0,255,0));
            angle = elipse.angle;               
        }

    }

    Imgcodecs.imwrite("elipse.png", input);


    Point center = new Point(threshold.cols() /2 ,threshold.rows()/2);

    Mat rotMat = Imgproc.getRotationMatrix2D(center,angle , 1.0 );
    Mat imgOut = Mat.zeros(input.rows(), input.cols(), input.type());
    Imgproc.warpAffine(threshold, imgOut, rotMat, imgOut.size(), affineFlags);
    Imgcodecs.imwrite("Rotated.png", imgOut);
edit retag flag offensive close merge delete

Comments

It looks like it's just more rotated. Try removing the WARP_INVERSE flag.

Tetragramm gravatar imageTetragramm ( 2017-12-02 15:01:14 -0500 )edit

I removed WARP_INVERSE. It's better, but still over-rotated more than i would expect, albeit in the opposite direction now. I've added the latest image to my original post. I want it to be 'vertical', if possible.

rc gravatar imagerc ( 2017-12-02 15:46:24 -0500 )edit

That looks like it matches the ellipse, if not the letter. You should probably now focus on a better fit. Whether using contours, moments, or skeletonization.

Tetragramm gravatar imageTetragramm ( 2017-12-03 18:57:57 -0500 )edit