0

I want to perform image warping using opencv. I have detected 4 corners of the image ((ex) 4000x4000) and got the transform matrix using getPerspectiveTransform in opencv. Now, I want to warp the image at the image center. So I used warpPerspective. Size of Source image that I input is 450x450 and I use the transform matrix that I calculated for whole image.

But nothing is displayed on the screen. Any help is appreciated.

Here is sample code and sample image.

This is source image. This is source image.

This image is detected This image is detected

This is the warping area that I want from the image.(src_crop in code)

enter image description here

This is result.

enter image description here

        source[0] = Point2f(lt.x, lt.y);
        source[1] = Point2f(rt.x, rt.y);
        source[2] = Point2f(rb.x, rb.y);
        source[3] = Point2f(lb.x, lb.y);

        dst[0] = Point2f(6, 10);
        dst[1] = Point2f(3899, 7);
        dst[2] = Point2f(3901, 3899);
        dst[3] = Point2f(9, 3902);

        Mat transformMatrix ;
        transformMatrix = getPerspectiveTransform(source, dst);



        Mat dstFrame ;
        warpPerspective(src_crop, dstFrame, transformMatrix, Size(450, 450));
eonjeo
  • 35
  • 1
  • 6

1 Answers1

1

Your transformation fails since you use the wrong values for your getPerspectiveTransform method. You seem to mix up how you create the output image and how you populate the destination corners from the data of this image.

Also, it is important that you link the right corners in the arrays (left top, right top, left bottom, right bottom), you seem to mix this up.

This example will show you how to connect the right points and output it in an empty output image:

// Assuming your source image is called 'sourceImage' and you have the corner points you need:

// Create vectors to store the corners
vector<Point2f> originalCorners;
vector<Point2f> destinationCorners;

// Put the Sudoku corners in your originalCorners
originalCorners.clear();
originalCorners.push_back(Point2f(lt.x, lt.y);
originalCorners.push_back(Point2f(rt.x, rt.y);
originalCorners.push_back(Point2f(lb.x, lb.y);
originalCorners.push_back(Point2f(rb.x, rb.y);

// Output image size of 450x450
int ouputImageWidth = 450;
int outputImageHeight = 450;

// Create an empty image (450x450) to output your transformation result in
Mat transformedOutputImage(ouputImageWidth, outputImageHeight, sourceImage.type());

// Now put the corners of the output image so the warp knows where to warp to
destinationCorners.clear();
destinationCorners.push_back(Point2f(0, 0));
destinationCorners.push_back(Point2f(ouputImageWidth, 0));
destinationCorners.push_back(Point2f(0, outputImageHeight));
destinationCorners.push_back(Point2f(ouputImageWidth, outputImageHeight));

// Now we have all corners sorted, so we can create the warp matrix
Mat warpMatrix = getPerspectiveTransform(originalCorners, destinationCorners);

// And now we can warp the Sudoku in the new image
warpPerspective(sourceImage, transformedOutputImage, warpMatrix, Size(ouputImageWidth, ouputImageHeight));

Now, this assumes you know the corner points of the part of the image you want to warp. If you don't know how to get the points of the middle square, I recommend you to take a look at these excellent answers.

However, as long as you have the four corner points this method will work. You can even try it by manually looking up the middle square corner points and inserting those.

Community
  • 1
  • 1
Jurjen
  • 1,376
  • 12
  • 19
  • Thanks for your answer. I know transform matrix that is calculate whole image(4000 by 4000). But I input src_crop(450 by 450) image into warpPerspective as source image. So I think also src_crop image is warping using transform matrix. It is impossible? If I don't know src_crop image's corner point, I want to warp image for src_crop image – eonjeo Apr 05 '17 at 13:32
  • You should just use the `sourceImage` (4000x4000) instead of cropping it. The cropping will result in your `originalCorners` array pointing to corners that don't exist. I have never done corpping before warping, but that could result in the fact that your output is completely black? – Jurjen Apr 05 '17 at 13:48
  • Actually I use crop image because to reduce run time of program. I use matchTemplate function to detect center point of crop image. So I guess crop image warping instead of whole image warping is short time for warping. – eonjeo Apr 05 '17 at 14:27
  • I iterates the corners of the entire image to reduce the error around the center in the warping for the whole image. So we get the transformation matrix from the whole image and we try to find the center point by template matching after warping for the cropped image. The reason for this is that the center point error is near the center, but it takes a long time to warp the entire image. Therefore, we try to do final warping to the corners of the whole image where center error is small after warping only around the center. WarpPerspective function is not support that way? – eonjeo Apr 05 '17 at 14:37
  • As far as I know that's not possible. What you should do: crop the image, then detect the corners you want to warp in the cropped image, then warp. Another way is to resize the original image first, then find the corners, but that's probably also slow (although you could see if there's a performance difference). – Jurjen Apr 05 '17 at 15:20
  • Thank you so much your answer. As you said, the transformation matrix obtained from a large image will not work properly when I insert a small-sized image in the warpPerspective function in Opencv? I thinked this way is correct Theoretically..... :-( – eonjeo Apr 05 '17 at 15:41
  • No that doesn't work since you insert coordinates into the warp input array. If you resize the image, these coordinates do not exist anymore. The easiest solution is: resize/crop first, then find the corners, then do the warping etc. If this is somehow not possible, you'll have to calculate the warp matrix yourself based on the scaling you applied to the image. See [this answer on SO](http://stackoverflow.com/a/11622148/7397065) on how you could achieve this. BTW, don't forget to mark this answer as answer if it helped you fix your initial problem! – Jurjen Apr 06 '17 at 08:29