Seb
Seb

Reputation: 3564

How to get smooth perspective warping in OpenCV

I am trying to create a way to be able to smoothly generate images at different perspectives. The best way I can describe this is if I loop through the angles I can get a smooth rotating image, however, what I am trying to do here is to get a smooth tilting image, similar to a person viewing a billboard from different angles. I have included some sample images of proper perspective transformations as well as some invalid transformations that have seemed to return. Also if anyone can explain why or how these images look like shattered glass would help me understand what the cvWarpPerspective function is doing in the background.

EDIT

I've included some additional code below to describe what I am currently doing to get these images. I am currently trying to get any value and compare to what is described as being a valid range to work with.

srcQuad[0].x = 0; //src Top left
srcQuad[0].y = 0;
srcQuad[1].x = src->width - 1; //src Top right
srcQuad[1].y = 0;
srcQuad[2].x = 0; //src Bottom left
srcQuad[2].y = src->height - 1;
srcQuad[3].x = src->width - 1; //src Bot right
srcQuad[3].y = src->height - 1;
dstQuad[0].x = src->width*theRNG().uniform(0.1, 1.);//dst Top left
dstQuad[0].y = src->height*theRNG().uniform(0.1, 1.);
dstQuad[1].x = src->width*theRNG().uniform(0.1, 1.);//dst Top right
dstQuad[1].y = src->height*theRNG().uniform(0.1, 1.);
dstQuad[2].x = src->width*theRNG().uniform(0.1, 1.);//dst Bottom left
dstQuad[2].y = src->height*theRNG().uniform(0.1, 1.);
dstQuad[3].x = src->width*theRNG().uniform(0.1, 1.);//dst Bot right
dstQuad[3].y = src->height*theRNG().uniform(0.1, 1.);
cvGetPerspectiveTransform(
    srcQuad,
    dstQuad,
    warp_matrix
    );

cvWarpPerspective( src, dst, warp_matrix );

Proper transforms:

enter image description here enter image description here

Invalid, shattered glass, transforms:

enter image description here enter image description here

Any advice would be greatly appreciated.

Upvotes: 2

Views: 1671

Answers (1)

SSteve
SSteve

Reputation: 10728

That's happening because your left point is to the right of your right point and/or your top point is below your bottom point, so you're basically turning your image inside-out.

Here's a version that won't do that. I generate a random multiplier between 0 and 0.5 for the left and top coordinates and a multiplier between 0.5 and 1.0 for the right and bottom coordinates.

using namespace cv;

RNG rng;

int main(int argc, const char * argv[]) {

    Mat target(Size(601,601), CV_8UC3);
    for (int i=4; i>=0; i-=1) {
        circle(target, Point(300,300), i * 50, Scalar((i & 1) * 255, (i & 1) * 255, 255), 100, 8);
    }

    Point2f srcQuad[4], dstQuad[4];

    srcQuad[0] = Point2f(0,0); //src Top left
    srcQuad[1] = Point2f(0, target.cols-1); //src Top right
    srcQuad[2] = Point2f(target.rows-1, 0); //src Bottom left
    srcQuad[3] = Point2f(target.rows-1, target.cols-1); //src Bottom Right

    Mat warpTarget;

    int keystroke = 0;

    do {
        dstQuad[0] = Point2f(target.rows * rng.uniform(0.0f, 0.5f), target.cols * rng.uniform(0.0f, 0.5f)); //src Top left
        dstQuad[1] = Point2f(target.rows * rng.uniform(0.0f, 0.5f), target.cols * rng.uniform(0.5f, 1.0f)); //src Top right
        dstQuad[2] = Point2f(target.rows * rng.uniform(0.5f, 1.0f), target.cols * rng.uniform(0.0f, 0.5f)); //src Bottom left
        dstQuad[3] = Point2f(target.rows * rng.uniform(0.5f, 1.0f), target.cols * rng.uniform(0.5f, 1.0f)); //src Bottom Right

        Mat warpMatrix = getPerspectiveTransform(srcQuad, dstQuad);

        warpPerspective(target, warpTarget, warpMatrix, Size(600,600));

        // create image window named "so7149300"
        namedWindow("so7149300");
        // show the image on window
        imshow("so7149300", warpTarget);
        // wait for key
        keystroke = waitKey(0);
    } while (keystroke != 27);

    return 0;
}

Upvotes: 1

Related Questions