I am currently making an app that performs a perspective transform of an image using OpenCV, as in the user defines 4 corners and it "crops" the image to those four corners, even if the corners don't form a rectangle. As an example, I have it working with this original image, being cropped with the points:
//the order of these is top left, bottom left, bottom right, then top right
Point ocvPIn1 = new Point(10, 10);
Point ocvPIn2 = new Point(10, 600);
Point ocvPIn3 = new Point(500, 400);
Point ocvPIn4 = new Point(500, 10);
Before perspective transformation:
After transformation:
That part which I've shown is working correctly, so the transformation math is all working. I now have it in the app where I made a draggable quadrilateral so the user can drag each corner and define what the transformation is. The only problem is, after trying to get the coordinates of the corners of the quadrilateral and make it perfectly line up with the correct points over the image, I get the following in my logs as an example:
12-05 21:23:21.294 18073-18073/appI/sscan﹕ Final points:
12-05 21:23:21.294 18073-18073/app I/sscan﹕ 100.0, 276.0
12-05 21:23:21.294 18073-18073/app I/sscan﹕ 101.0, 1544.0
12-05 21:23:21.294 18073-18073/app I/sscan﹕ 725.0, 1544.0
12-05 21:23:21.294 18073-18073/app I/sscan﹕ 726.0, 276.0
12-05 21:23:21.294 18073-18073/app I/sscan﹕ Bitmap dimensions: 675, 1200
These points obviously go outside the bounds of the image, which is incorrect. In that example, the corners were defined over the image. I am trying to figure out where my math is going wrong, and have been looking over and over to try and see where it's going wrong but haven't been able to pin it down. Here is my code for how I am getting these numbers (I'm leaving out the code that performs the actual transformation as I know it is working correctly if given the correct points on the image).
//this is where the points are actually defined, cropController.c1 and c2 and so forth are the four corners that the user drags,
//I'm trying to get the positioning of that relative to the image. This is tricky as the image is in an imageView but has a stretch so that there might be margins on the sides or top/bottom of the image,
//which is why I'm subtracting by the leftImageEdge and topImageEdge to try to get the coordinates in terms of the image itself
Point ocvPIn1 = new Point(getCornerRelativeLeft(cropController.c1) - cropController.c1.leftImageEdge, getCornerRelativeTop(cropController.c1) - cropController.c1.topImageEdge);
Point ocvPIn2 = new Point(getCornerRelativeLeft(cropController.c4) - cropController.c1.leftImageEdge, getCornerRelativeTop(cropController.c4) - cropController.c1.topImageEdge);
Point ocvPIn3 = new Point(getCornerRelativeLeft(cropController.c3) - cropController.c1.leftImageEdge, getCornerRelativeTop(cropController.c3) - cropController.c1.topImageEdge);
Point ocvPIn4 = new Point(getCornerRelativeLeft(cropController.c2) - cropController.c1.leftImageEdge, getCornerRelativeTop(cropController.c2) - cropController.c1.topImageEdge);
//this is where the corner's left and top space from the sides of the layout are calculated
private int getCornerRelativeLeft(View myView) {
if (myView.getParent() == myView.getRootView())
return myView.getLeft();
else
return myView.getLeft() + getCornerRelativeLeft((View) myView.getParent());
}
private int getCornerRelativeTop(View myView) {
if (myView.getParent() == myView.getRootView())
return myView.getTop();
else
return myView.getTop() + getCornerRelativeTop((View) myView.getParent());
}
//and lastly this is where the space on the side or top of the image from the edge of its parent container is calculated, since its using a center fit scaling
private void calculateImageDimensionsOnScreen(){
//calculate "false margins" of image to get the edge points in pixels
Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
double bitmapRatio = ((double)bitmap.getWidth())/bitmap.getHeight();
double imageRatio = ((double)image.getWidth())/image.getHeight();
if(bitmapRatio > imageRatio){
//left is flush to edge
double drawHeight = (imageRatio/bitmapRatio) * image.getHeight();
topImageEdge = (int)Math.round((image.getHeight() - drawHeight)/2);
bottomImageEdge = container.getHeight() - topImageEdge;
leftImageEdge = 0;
rightImageEdge = container.getWidth();
} else {
//top is flush to edge
double drawWidth = (bitmapRatio/imageRatio) * image.getWidth();
leftImageEdge = (int)Math.round((image.getWidth() - drawWidth)/2);
rightImageEdge = container.getWidth() - leftImageEdge;
topImageEdge = 0;
bottomImageEdge = container.getHeight();
}
}
0 comments:
Post a Comment