Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

How can I get the corner points of the largest contour (in Java/Android preferably)

I Convert an image into a Mat, differentiate the foreground from the background, apply cvtcolor and canny, then find all the contours and select the largest contour among them (The page boundary for for the purpose of scanning app). Now I want to establish 4 corners of the boundary to apply perspective transform but am unable to find them. Any help would be appreciated.

My code till now is as follows

public class MyAsyncTask extends android.os.AsyncTask {
        private static final String TAG = "AsyncTask";
        Bitmap bitmap1;
        Context context;


    //constructor initializing the context field
    public MyAsyncTask(Context context){
        this.context=context;
    }


    //Main method for the computation of the image
    @Override
    protected Bitmap doInBackground(Object[] objects)
    {

        //set-up of the image in the desired format for k-means clustering
        Mat samples = new Mat(((LensActivity)context).src.rows() * ((LensActivity)context).src.cols(), 3, CvType.CV_32F);
        for( int y = 0; y < ((LensActivity)context).src.rows(); y++ )
        {
            for( int x = 0; x < ((LensActivity)context).src.cols(); x++ )
            {
                for( int z = 0; z < 3; z++)
                {
                    samples.put(x + y*((LensActivity)context).src.cols(), z, ((LensActivity)context).src.get(y,x)[z]);
                }
            }
        }

        //applying k-means clustering
        int clusterCount = 2;
        Mat labels = new Mat();
        int attempts = 5;
        Mat centers = new Mat();
        Core.kmeans(samples, clusterCount, labels, new TermCriteria(TermCriteria.MAX_ITER |
                        TermCriteria.EPS, 10000, 0.0001), attempts,
                Core.KMEANS_PP_CENTERS, centers);


        //The image with the colour nearest to white will be considered as foreground
        double dstCenter0 = calcWhiteDist(centers.get(0, 0)[0], centers.get(0, 1)[0], centers.get(0, 2)[0]);
        double dstCenter1 = calcWhiteDist(centers.get(1, 0)[0], centers.get(1, 1)[0], centers.get(1, 2)[0]);
        int paperCluster = (dstCenter0 < dstCenter1)?0:1;


        //definition of 2 Mat objects needed for next step
        Mat srcRes = new Mat( ((LensActivity)context).src.size(), ((LensActivity)context).src.type() );
        Mat srcGray = new Mat();


        //Performing Segmentation ie displaying all foreground pixels as white and all background pixels as black
        for( int y = 0; y < ((LensActivity)context).src.rows(); y++ )
        {
            for( int x = 0; x < ((LensActivity)context).src.cols(); x++)
            {
                int cluster_idx = (int)labels.get(x + y*((LensActivity)context).src.cols(),0)[0];
                if(cluster_idx != paperCluster)
                {
                    srcRes.put(y,x, 0, 0, 0, 255);
                }
                else
                {
                    srcRes.put(y,x, 255, 255, 255, 255);
                }
            }
        }


        //Apply canny edge detection and then find contours
        Imgproc.cvtColor(((LensActivity)context).src, srcGray, Imgproc.COLOR_BGR2GRAY);
        Imgproc.Canny(srcGray, srcGray, 50, 150);
        List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        Mat hierarchy = new Mat();
        Imgproc.findContours(srcGray, contours, hierarchy, Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_SIMPLE);



        //Finding the biggest contour corresponding to the page in the image
        int index = 0;
        double maxim = Imgproc.contourArea(contours.get(0));

        for (int contourIdx = 1; contourIdx < contours.size();contourIdx++)
        {
            double temp;
            temp=Imgproc.contourArea(contours.get(contourIdx));
            if(maxim<temp)
            {
                maxim=temp;
                index=contourIdx;
            }
        }
        Mat drawing = Mat.zeros(srcRes.size(), CvType.CV_8UC1);
        Log.d(TAG,"number of contours " +contours.get(index));

        Imgproc.drawContours(drawing, contours, index, new Scalar(255), 1);



        //lines corresponding to the biggest contours used to find the intersection points of these lines to find the corners
        Mat lines = new Mat();
        Imgproc.HoughLinesP(drawing, lines, 1, Math.PI/180, 70, 30, 10);
        bitmap1 = Bitmap.createBitmap(drawing.width(), drawing.height(), Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(drawing, bitmap1);
        double[] line1 = lines.get(0,0);
        Log.d(TAG, "Point one" + contours.get(index));
        Point[] contourPoints = contours.get(index).toArray();
        Log.d(TAG, "the points are " + contourPoints);
        return bitmap1;
}]

Largest contour - page boundary