0

我正在尝试将水印/图像放在另一张图像上,我们可以通过手指触摸放大、缩小、拖动和旋转水印图像。我正在使用 Open CV 库来旋转图像,如这篇文章中建议的那样, 在 android 中使用 opencv 进行图像旋转会切断图像的边缘

它工作正常,直到旋转角度介于 -75 到 -105 和 75 到 105 之间。在这个范围内,我的图像被裁剪或改变了它的位置。我尝试了几种方法来获得水印图像的正确中心点,使其在旋转后放置在正确的位置,但未能这样做。

这是旋转图像的代码

// 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;
}

以下是两张图片,第一张正确,另一张旋转错误

向右旋转

错误/裁剪旋转

有人有解决方案吗?

4

0 回答 0