Abhishek Thakur
Abhishek Thakur

Reputation: 17035

proper visualization of warped image

I am trying to implement image warping in C++ and OpenCV. My code is as follows:

Mat input = imread("Lena.jpg",CV_LOAD_IMAGE_GRAYSCALE);    
Mat out;
double xo, yo;
input.convertTo(input, CV_32FC1);
copyMakeBorder(input, input, 3, 3, 3, 3, 0);

int height = input.rows;
int width = input.cols;

out = Mat(height, width, input.type());


for(int j = 0; j < height; j++){
    for(int i =0; i < width; i++){
        xo = (8.0 * sin(2.0 * PI * j / 128.0));
        yo = (8.0 * sin(2.0 * PI * i / 128.0));
        out.at<float>(j,i) = (float)input.at<float>(((int)(j+yo+height)%height),((int)(i+xo+width)%width));

    }
}
normalize(out, out,0,255,NORM_MINMAX,CV_8UC1);

imshow("output", out);

This produces the following image: warped image

As it is clearly visible, the values near the border are non-zero. Can anyone tell me how do I get black border as shown in the following image instead of artifacts that I get from my code?

required black border

Only the black border of this image should be considered, i.e the image should be wavy (sinusoidal) but without artifacts.

Thanks...

Upvotes: 0

Views: 1695

Answers (1)

JasonD
JasonD

Reputation: 16612

Here:

    xo = (8.0 * sin(2.0 * PI * j / 128.0));
    yo = (8.0 * sin(2.0 * PI * i / 128.0));
    out.at<float>(j,i) = (float)input.at<float>(((int)(j+yo+height)%height),((int)(i+xo+width)%width));

You calculate the location of the source pixel, but you take the mod with width/height to ensure it's within the image. This results in pixels wrapping around at the edge. Instead you need to set any pixel outside of the image to black (or, if your source image has a black border, clamp to the edge).

As you have a border already, you could just clamp the coordinates, like this:

int ix = min(width-1, max(0, (int) (i + xo)));
int iy = min(height-1, max(0, (int) (j + yo)));
out.at<float>(j,i) = (float)input.at<float>(iy,ix);

Upvotes: 2

Related Questions