So, the first problem I ran into was that OpenCV defines its origin about the top left corner rather than the center of the window. This was a problem because I want to just apply a transformation matrix to an image (say a reflection about the x-axis for example) and see it applied "in place", so it stays in the same spot, but is still reflected.
My solution to fix this was to first translate the image to OpenCV's origin, apply my transformation matrix to the image, then translate it back to its original location.
This works fine, however, any part of the image that goes off screen at any point is permanently deleted/cropped. I cannot figure out how to prevent this, I figured there was maybe a flag or something and I tried utilizing BORDER_WRAP rather than BORDER_CONSTANT which almost fixed my problem, but not quite and now I am completely stuck on where to go next.
Here is what I have so far:
int main()
{
// Read in and display input image
Mat src = imread("myImage.png");
imshow("Input Image", src);
// Translate the image to the origin
Mat M = (Mat_<double>(2, 3) << 1, 0, -(src.rows / 2), 0, 1, -(src.cols / 2));
Size dsize = Size(src.rows, src.cols);
warpAffine(src, src, M, dsize, INTER_LINEAR, BORDER_CONSTANT, Scalar());
// Apply the affine transformation
Mat M2 = (Mat_<double>(2, 3) << 1, 0, 0, 0, -1, 0);
dsize = Size(src.rows, src.cols);
warpAffine(src, src, M2, dsize, INTER_LINEAR, BORDER_CONSTANT, Scalar());
// Translate the resulting image back to its original location and display
Mat M3 = (Mat_<double>(2, 3) << 1, 0, (src.rows / 2), 0, 1, (src.cols / 2));
dsize = Size(src.rows, src.cols);
warpAffine(src, src, M3, dsize, INTER_LINEAR, BORDER_CONSTANT, Scalar());
// This is an extremely cropped version of the input image because
// it gets cropped when translated to the origin
imshow("Output Image", src);
waitKey();
return 0;
}
NEW CODE:
// Read in and display input image
Mat src = imread("umichLogo.png");
imshow("Input Image", src);
Mat M = (Mat_<double>(3, 3) << 1, 0, -(src.rows / 2), 0, 1, -(src.cols / 2), 0, 0, 1);
Mat M2 = (Mat_<double>(3, 3) << 1, 0, 0, 0, -1, 0, 0, 0, 1);
Mat M3 = (Mat_<double>(3, 3) << 1, 0, (src.rows / 2), 0, 1, (src.cols / 2), 0, 0, 1);
Mat Composition = M3 * (M2 * M);
Size dsize = Size(src.rows, src.cols);
warpPerspective(src, src, Composition, dsize, INTER_LINEAR, BORDER_CONSTANT, Scalar());
imshow("Output Image", src);
waitKey();
return 0;
CodePudding user response:
To avoid undesired cropping, transform once only (simultaneously).
Mat M = (Mat_<double>(3, 3) << 1, 0, -(src.rows / 2), 0, 1, -(src.cols / 2), 0,0,1);
Mat M2 = (Mat_<double>(3, 3) << 1, 0, 0, 0, -1, 0, 0,0,1);
Mat M3 = (Mat_<double>(3, 3) << 1, 0, (src.rows / 2), 0, 1, (src.cols / 2), 0,0,1);
Mat Composition = M3 * (M2 * M);
Size dsize = Size(src.rows, src.cols);
warpPerspective(src, src, Composition, dsize, INTER_LINEAR, BORDER_CONSTANT, Scalar());
I found that, rows and cols are mistaken (not only for size but also M and M3). Fixed code is :
Mat M = (Mat_<double>(3, 3) << 1, 0, -(src.cols / 2), 0, 1, -(src.rows / 2), 0,0,1);
Mat M2 = (Mat_<double>(3, 3) << 1, 0, 0, 0, -1, 0, 0,0,1);
Mat M3 = (Mat_<double>(3, 3) << 1, 0, (src.cols / 2), 0, 1, (src.rows / 2), 0,0,1);
Mat Comp = M3 * (M2 * M);
warpPerspective(src, src, Comp, src.size(), INTER_LINEAR, BORDER_CONSTANT, Scalar());