1
$\begingroup$

I'm working with perspective transformation in opencv for android for a personal project.
The thing I'd like to do is to acquire a document like CamScanner does. For this I import a picture and let the user set the four transformation points needed.
Everything works, except for the fact that the transformation seems to be applied to different points or something like that. I need some fresh eyes to point me to the right direction.
Note that myHandle is a custom class, its only interesting properties in this context are that they are points with x and y coordinates and getX() and getY() are its getters for the coordinates.
Here's my function for the transformation:

public Bitmap addrizzone(Bitmap image, ArrayList<myHandle> sourcePoints){
        // sourcePoints are  expected  to be clockwise ordered
        // [top_left,top_right,bottom_right,bottom_left]
        // getting the size of the output image
        double dst_width = Math.max(sourcePoints.get(0).distanceFrom(sourcePoints.get(1)),sourcePoints.get(3).distanceFrom(sourcePoints.get(2)));
        double dst_height = Math.max(sourcePoints.get(0).distanceFrom(sourcePoints.get(3)),sourcePoints.get(1).distanceFrom(sourcePoints.get(2)));

        //determining point sets to get the transformation matrix
        List<org.opencv.core.Point> srcPts = new ArrayList<org.opencv.core.Point>();
        for (myHandle ball : sourcePoints) {
            srcPts.add(new org.opencv.core.Point((ball.getX()),ball.getY()));
        }

        List<org.opencv.core.Point> dstPoints= new ArrayList<org.opencv.core.Point>();
        dstPoints.add(new org.opencv.core.Point(0,0));
        dstPoints.add(new org.opencv.core.Point(dst_width-1,0));
        dstPoints.add(new org.opencv.core.Point(dst_width-1,dst_height-1));
        dstPoints.add(new org.opencv.core.Point(0,dst_height));

        Mat srcMat = Converters.vector_Point2f_to_Mat(srcPts);
        Mat dstMat = Converters.vector_Point2f_to_Mat(dstPoints);

        //getting the transformation matrix
        Mat perspectiveTransformation = Imgproc.getPerspectiveTransform(srcMat,dstMat);

        //getting the input matrix from the given bitmap
        Mat inputMat = new Mat(image.getHeight(),image.getWidth(),CvType.CV_8UC1);

        Utils.bitmapToMat(image,inputMat);

        Imgproc.cvtColor(inputMat,inputMat,Imgproc.COLOR_RGB2GRAY);

        //getting the output matrix with the previously determined sizes
        Mat outputMat = new Mat((int) dst_height,(int) dst_width,CvType.CV_8UC1);

        //applying the transformation
        Imgproc.warpPerspective(inputMat,outputMat,perspectiveTransformation,new Size(dst_width,dst_height));

        //creating the output bitmap
        Bitmap outputBitmap = Bitmap.createBitmap((int)dst_width,(int)dst_height, Bitmap.Config.RGB_565);

        //Mat to Bitmap
        Imgproc.cvtColor(outputMat,outputMat,Imgproc.COLOR_GRAY2RGB);
        Utils.matToBitmap(outputMat,outputBitmap);

        return outputBitmap;
    }

Some example screenshots: User determined the points
User determined the points
Transformation is not as expected
Transformation is not as expected

$\endgroup$
0
$\begingroup$
        @Override
public boolean onTouchEvent(MotionEvent event){
    boolean value = super.onTouchEvent(event);
    switch ( event.getAction()){
        case MotionEvent.ACTION_DOWN: {
            return true;
        }
        case MotionEvent.ACTION_MOVE:{
            //Point 1
            float x = event.getX();
            float y = event.getY();
            double dx = Math.pow(x - mCircleX,2);
            double dy = Math.pow(y-mCircleY,2);
            if (dx + dy < Math.pow(mCircleRadius,2)){
                //Toucher
                mCircleX = x;
                //Toast.makeText(getContext(),String.valueOf(mCircleX),Toast.LENGTH_SHORT).show();
                mCircleY = y;
                postInvalidate();
                return  true;

            }
            //Point 2
            float x2 = event.getX();
            float y2 = event.getY();
            double dx2 = Math.pow(x2 - mCircleX2,2);
            double dy2 = Math.pow(y2 - mCircleY2,2);
            if (dx2 + dy2 < Math.pow(mCircleRadius2,2)){
                //Toucher
                mCircleX2 = x2;
                mCircleY2 = y2;
                postInvalidate();
                return  true;

            }
            //Point 3
            float x3 = event.getX();
            float y3 = event.getY();
            double dx3 = Math.pow(x3 - mCircleX3,2);
            double dy3 = Math.pow(y3 - mCircleY3,2);
            if (dx3 + dy3 < Math.pow(mCircleRadius3,2)){
                //Toucher
                mCircleX3 = x3;
                mCircleY3 = y3;
                postInvalidate();
                return  true;

            }
            //Point 4
            float x4 = event.getX();
            float y4 = event.getY();
            double dx4 = Math.pow(x4 - mCircleX4,2);
            double dy4 = Math.pow(y4 - mCircleY4,2);
            if (dx4 + dy4 < Math.pow(mCircleRadius4,2)){
                //Toucher
                mCircleX4 = x4;
                mCircleY4 = y4;
                postInvalidate();
                return  true;

            }
            return true;

        }
    }
    return value;
}

}

$\endgroup$
  • $\begingroup$ This is my code to move the points $\endgroup$ – Tuấn Anh Nguyễn Sep 8 '17 at 3:54
  • $\begingroup$ Please consider adding an explanation of your technique: answers containing only code are not very useful, and they are discouraged. $\endgroup$ – MBaz Sep 8 '17 at 13:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.