8

Possible Duplicate:
Rotate cv::Mat using cv::warpAffine offsets destination image

Code below can rotate an image successfully but it cuts off corners of the image and it rotates in wrong direction!!

Mat cvImage = Highgui.imread("mnt/sdcard/canvasgrid.png");
int degrees = 20;
Point center = new Point(cvImage.cols()/2, cvImage.rows()/2);
Mat rotImage = Imgproc.getRotationMatrix2D(center, degrees, 1.0);
Mat dummy = cvWaterImage;
Imgproc.warpAffine(cvImage, dummy, rotImage, cvImage.size());
rotatedImage = dummy;

Highgui.imwrite("mnt/sdcard/imageRotate.png",rotatedImage);

original Image

rotated Image

PLUS rotated image's background is black but I want it to be transparent.

Am I doing anything wrong?? Thanks

EDIT SOLVED

first of all get new width/height of rotated image

double radians = Math.toRadians(rotationAngle);
double sin = Math.abs(Math.sin(radians));
double cos = Math.abs(Math.cos(radians));

int newWidth = (int) (scaledImage.width() * cos + scaledImage.height() * sin);
int newHeight = (int) (scaledImage.width() * sin + scaledImage.height() * cos);

int[] newWidthHeight = {newWidth, newHeight};

// create new sized box (newWidth/newHeight)

int pivotX = newWidthHeight[0]/2; 
int pivotY = newWidthHeight[1]/2;

// rotating water image

org.opencv.core.Point center = new org.opencv.core.Point(pivotX, pivotY);
Size targetSize = new Size(newWidthHeight[0], newWidthHeight[1]);

// now create another mat, so we can use it for mapping

Mat targetMat = new Mat(targetSize, scaledImage.type());

int offsetX = (newWidthHeight[0] - scaledImage.width()) / 2;
int offsetY = (newWidthHeight[1] - scaledImage.height()) / 2;

// Centralizing watermark

Mat waterSubmat = targetMat.submat(offsetY, offsetY + scaledImage.height(), offsetX,     offsetX + scaledImage.width());
scaledImage.copyTo(waterSubmat);

Mat rotImage = Imgproc.getRotationMatrix2D(center, waterMarkAngle, 1.0);
Mat resultMat = new Mat(); // CUBIC
Imgproc.warpAffine(targetMat, resultMat, rotImage, targetSize, Imgproc.INTER_LINEAR,    Imgproc.BORDER_CONSTANT, colorScalar);

// your resultMat with look like this NOT CROPPED Image // BTW.. there is a huge differce between provided link and this solution

Community
  • 1
  • 1
Khawar
  • 859
  • 11
  • 30
  • 3
    That the edges are cut off is clear if you don't change the physical size of the canvas and keep the image the same size. You can A) Provide a bigger canvas or B) change the rotation matrix such way, that it shrinks the image while rotating it. – Nippey Oct 12 '12 at 05:19
  • 1
    Thanks for the answer, is there any way to rotate the whole canvas as well?? because I'm overlaying this rotated image on other large image. – Khawar Oct 12 '12 at 05:47
  • 2
    With canvas I meant at this moment the memory the image is saved in. You could rotate your computer.... er no, the way I defined the term canvas, you can't rotate it. ;) In this case it is even so, that you original image's canvas is also the canvas of the other one as you want to draw (and rotate) it onto it. – Nippey Oct 12 '12 at 05:50
  • [1]: http://www.freeimagehosting.net/61zaj this is what i'm doing, so what do you suggest? – Khawar Oct 12 '12 at 05:56
  • 2
    I've changed the physical [size](http://www.freeimagehosting.net/b36kv) of canvas but the image is not moved to center, how to centralize it and background should be transparent as well? – Khawar Oct 18 '12 at 10:47
  • 4
    why would it be a duplicate question?? my rotation could be at any degree not just 90', I just don't want to use transpose method to rotate image by 90'.. – Khawar Nov 07 '12 at 12:13

1 Answers1

2

I just read through the documentation: ImgProc.warpAffine

Just an extract:

void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, [...]);
//Parameters: dsize – Size of the destination image.

Please try the following:

Imgproc.warpAffine(cvImage, dummy, rotImage, dummy.size());

In order to play with the transparency, fiddle with the parameter at the end:

Imgproc.warpAffine(cvImage, dummy, rotImage, dummy.size(), INTER_LINEAR, BORDER_TRANSPARENT);
Nippey
  • 4,708
  • 36
  • 44
  • 1
    Imgproc.warpAffine(cvImage, dummy, rotImage, dummy.size()); – Khawar Oct 12 '12 at 20:02
  • 1
    Hmm? Did I write something wrong? :) – Nippey Oct 12 '12 at 20:54
  • no I mean the results are same! and if go with INTER_LINEAR and BORDER_TRANSPARENT then it writes rotated image on original image (itself) :( – Khawar Oct 13 '12 at 06:33
  • 1
    Imgproc.warpAffine(scaledImage, dummy, rotImage, dummy.size(), Imgproc.INTER_LINEAR, Imgproc.BORDER_TRANSPARENT, new Scalar(0)); this code's [result](http://www.freeimagehosting.net/bkbu3) – Khawar Oct 13 '12 at 06:42
  • Well, I'm sorry to say that this goes beyond my capabilities. I have no functioning environment at this moment where I can test the code :/ – Nippey Oct 13 '12 at 14:39
  • glad you tried to help.. thanks I will try to sort it out and will post the answer if I get any.. – Khawar Oct 13 '12 at 17:24