문제

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...

도움이 되었습니까?

해결책

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);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top