我正在尝试将水印/图像放在另一张图像上,我们可以通过手指触摸放大、缩小、拖动和旋转水印图像。我正在使用 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;
}
以下是两张图片,第一张正确,另一张旋转错误
有人有解决方案吗?