0

I am trying to put a watermark/Image on another image, we can zoom in, zoom out, drag and rotate the watermark image by fingertouch. I am using Open CV library to rotate the image as suggested in this post image rotation with opencv in android cuts off the edges of an image

It works fine until the rotation angle gets in between -75 to -105 and 75 to 105. In this range my image get cropped or it changes its position. I have tried several ways to get the right center point for the watermark image to put it in right position after rotating it but failed to do so.

Here is the code to rotate the image

// CALCULATE ROTATED WATERMARK IMAGE
    private void CreateRotatedWaterMark() 
    {
        // Means rotation took place
        if (waterMarkAngle > 0 || waterMarkAngle < 0) {
            // calculation for new width/height of rotated watermark image
            newWidthHeight = boundingWaterMarkRect();

            // remove when done testing
            double pivotX = newWidthHeight[0] / 2; // 0 is width
            double pivotY = newWidthHeight[1] / 2; // 1 is height

            // rotating water image
            org.opencv.core.Point center;
            Size targetSize;
            Mat targetMat;

            // scalar is color/ RGBA , but alpha doesn't seem to work
            Scalar colorScalar = new Scalar(255, 190, 190, 0);
            double offsetX = (newWidthHeight[0] - scaledImage.width()) / 2;
            double offsetY = (newWidthHeight[1] - scaledImage.height()) / 2;

            // watermark's rotation lays somewhere in between 75' AND 105' OR
            // -75' AND -105'
            Log.e(TAG, "check => offsetX/offsetY Before  => " + offsetX + " / "
                    + offsetY);
            if (offsetX < 0 || offsetY < 0) {
                //this gets true when angle of rotation gets between -75 to -105 and 75 to 105
                // change the offsets, now new newWidth < oldWidth AND newHeight
                // > oldHeight (could be vice versa)
                offsetX = (newWidthHeight[0] - scaledImage.height()) / 2;
                offsetY = (newWidthHeight[1] - scaledImage.width()) / 2;
                // Declaring new target size and target Mat, so rotated image is
                // placed in new target Mat
                targetSize = new Size(newWidthHeight[1], newWidthHeight[0]);
                targetMat = new Mat(targetSize, scaledImage.type(), colorScalar);

                // Getting the reference of center area from target Mat,
                // below we're copying the actual image (scaledImage) to center
                // position to target Mat
                Mat waterSubmat = targetMat.submat((int) offsetX, (int) offsetX
                        + scaledImage.height(), (int) offsetY, (int) offsetY
                        + scaledImage.width());
                scaledImage.copyTo(waterSubmat);

                // Writing target image to sdcard, so we can know if its working
                // properly, remove it when done with testing
                Highgui.imwrite("mnt/sdcard/scaled90.png", targetMat);
                Highgui.imwrite("mnt/sdcard/waterSubmat.png", waterSubmat);
                Highgui.imwrite("mnt/sdcard/ScaledImage.png", scaledImage);

                // targetSize is reverted again, so that target mat is pasted on
                // canvas image
                targetSize = new Size(newWidthHeight[0], newWidthHeight[1]);

                pivotX = newWidthHeight[0] / 2;
                pivotY = newWidthHeight[1] / 2;
                Log.e(TAG, "check => pivotX/pivotY => " + pivotX + " / "
                        + pivotY);
                Log.e(TAG, "check => Angle => " + waterMarkAngle);
                center = new org.opencv.core.Point(pivotX, pivotY);
            } else {
                center = new org.opencv.core.Point(pivotX, pivotY);
                targetSize = new Size(newWidthHeight[0], newWidthHeight[1]);

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

                // Centralizing watermark
                Mat waterSubmat = targetMat.submat((int) offsetY, (int) offsetY
                        + scaledImage.height(), (int) offsetX, (int) offsetX
                        + scaledImage.width());
                scaledImage.copyTo(waterSubmat);
                Highgui.imwrite("mnt/sdcard/scaled10.png", targetMat);

            }
            Mat rotImage = Imgproc.getRotationMatrix2D(center, waterMarkAngle,
                    1.0); // 1.0 means scale 100%
            Highgui.imwrite("mnt/sdcard/Rotated90.png", rotImage);
            // Mat waterSubmat1 = rotImage.submat(0, scaledImage.height(), 0,
            // scaledImage.width());
            Mat resultMat = new Mat();
            // scalar for color, Imagproc.warAffine actually rotates the final
            // watermark on canvas image
            colorScalar = new Scalar(122, 22, 22);
            Imgproc.warpAffine(targetMat, resultMat, rotImage, targetSize,
                    Imgproc.INTER_LINEAR, Imgproc.BORDER_CONSTANT, colorScalar);
            Log.i(TAG, "check MATRIX =  " + resultMat.toString());
            Log.i(TAG, "check Result Mat " + resultMat.size().toString());
            scaledImage = resultMat.clone();
            Highgui.imwrite("mnt/sdcard/Result100.png", targetMat);

            // Log.i(TAG, "check Result postion  =  "+ resultMat.r);
            // WRITE SOME TEXT ON CANVAS IMAGE, its not rotated
            Core.putText(scaledImage, "angle: " + waterMarkAngle,
                    new org.opencv.core.Point(0, scaledImage.height() / 2),
                    Core.FONT_HERSHEY_TRIPLEX, 2, new Scalar(23, 12, 450, 0.5),
                    2); // CV_BLUR_NO_SCALE

        } else {
            // CHANGE OPACITY OF WATERMARK IMAGE
            // Core.multiply(scaledImage, new Scalar(1, 1, 1, 0.6),
            // scaledImage);

            // REMOVE THIS WHEN DONE TESTING
            // Highgui.imwrite("mnt/sdcard/opacityWatermark.png",scaledImage);
        }
    }

private double[] boundingWaterMarkRect() {

    // -----NEW CALCULATION------

    // so we always get positive angle
    double tempAngle = ((waterMarkAngle < 0 ? 360 - waterMarkAngle : waterMarkAngle) % 360);
    double radians = Math.toRadians(tempAngle);

    Log.i(TAG, "check => radian => "+ radians);

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

    double newWidth = (double) (scaledImage.width() * cos + scaledImage.height() * sin);
    double newHeight = (double) (scaledImage.width() * sin + scaledImage.height() * cos);
    double[] wh = {newWidth, newHeight};

    return wh;
}

Following are two images first one is right and the other is rotated wrong

Right Rotated

Wrong/Cropped Rotated

Anyone have got solution for it?

Community
  • 1
  • 1
Nouman Bhatti
  • 1,777
  • 4
  • 28
  • 55
  • May be I misunderstand your problem again, but it seems that you need exhcange hidth and height for center of rotation calculation of your cropped image when you rotate it on this angle. Try run you program with square image. – Andrey Smorodov Oct 25 '13 at 06:07
  • yes your are right it is running fine with square images but i want it to run with all the images.Still have'nt got your point – Nouman Bhatti Oct 25 '13 at 06:23
  • can you pin point the lines of code i need to do editing? – Nouman Bhatti Oct 25 '13 at 06:23
  • I think that it's better to rotate origin centered 4 corner points of cropped image. After that you can get the width and height of region you need for rotated image (just get min/max x-coords and min/max y coords). And it 'll allow you to correctly compute the center of rotation. – Andrey Smorodov Oct 25 '13 at 06:47
  • I am still getting the width and height if you see my code. but its not working – Nouman Bhatti Oct 25 '13 at 06:55
  • But there is no boundingWaterMarkRect() metod source code. I think the result it get may be incorrect at angles you mention. – Andrey Smorodov Oct 25 '13 at 07:16
  • I have added boundingWaterMarkRect() code can you point out whats wrong in it? – Nouman Bhatti Oct 25 '13 at 07:43
  • Rotation matrix is [cos,-sin; sin cos]. It seems you miss "-" sign. http://en.wikipedia.org/wiki/Rotation_matrix – Andrey Smorodov Oct 25 '13 at 08:11

0 Answers0