【发布时间】:2020-02-21 07:14:38
【问题描述】:
在我的 Android 应用中,我以编程方式从后台服务捕获屏幕截图。我以Bitmap 的形式获得它。
接下来,我使用以下 Android 框架 API 获取感兴趣区域 (ROI) 的坐标:
Rect ROI = new Rect();
viewNode.getBoundsInScreen(ROI);
这里,getBoundsInScreen() 是 Javascript 函数 getBoundingClientRect() 的 Android 等效项。
Android 中的Rect 具有以下属性:
rect.top
rect.left
rect.right
rect.bottom
rect.height()
rect.width()
rect.centerX() /* rounded off to integer */
rect.centerY()
rect.exactCenterX() /* exact value in float */
rect.exactCenterY()
What does top, left, right and bottom mean in Android Rect object
而 OpenCV 中的 Rect 具有以下属性
rect.width
rect.height
rect.x /* x coordinate of the top-left corner */
rect.y /* y coordinate of the top-left corner */
现在,在我们执行任何与 OpenCV 相关的操作之前,我们需要将 Android Rect 转换为 OpenCV Rect。
Understanding how actually drawRect or drawing coordinates work in Android
有两种方法可以将 Android Rect 转换为 OpenCV Rect(正如 Karl Phillip 在他的回答中所建议的那样)。两者都生成相同的值并产生相同的结果:
/* Compute the top-left corner using the center point of the rectangle. */
int x = androidRect.centerX() - (androidRect.width() / 2);
int y = androidRect.centerY() - (androidRect.height() / 2);
// OR simply use the already available member variables:
x = androidRect.left;
y = androidRect.top;
int w = androidRect.width();
int h = androidRect.height();
org.opencv.core.Rect roi = new org.opencv.core.Rect(x, y, w, h);
现在我正在执行的 OpenCV 操作之一是blurring the ROI within the screenshot:
Mat originalMat = new Mat();
Bitmap configuredBitmap32 = originalBitmap.copy(Bitmap.Config.ARGB_8888, true);
Utils.bitmapToMat(configuredBitmap32, originalMat);
Mat ROIMat = originalMat.submat(roi).clone();
Imgproc.GaussianBlur(ROIMat, ROIMat, new org.opencv.core.Size(0, 0), 5, 5);
ROIMat.copyTo(originalMat.submat(roi));
Bitmap blurredBitmap = Bitmap.createBitmap(originalMat.cols(), originalMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(originalMat, blurredBitmap);
这使我们非常接近预期的结果。快到了,但没有 相当。 目标区域正下方的区域模糊了。
例如,如果目标感兴趣区域是密码字段,则上述代码会产生以下结果:
左侧是Microsoft Live ROI,右侧是Pinterest ROI:
可以看出,ROI 正下方的区域变得模糊。
所以我的问题是,最后,为什么不是确切的感兴趣区域 模糊?
- 通过 Android API
getBoundsInScreen()获得的坐标似乎是正确的。- 将 Android
Rect转换为 OpenCVRect似乎也是正确的。是吗?- 用于模糊感兴趣区域的代码似乎也是正确的。有没有其他方法可以做同样的事情?
注意:我提供了实际的全尺寸屏幕截图。它们被缩小了 50% 以适应这篇文章,但除此之外,它们与我在 Android 设备上得到的完全一样。
【问题讨论】:
-
我建议使用标记来调整图像的大小,这样问题会更悦目。
-
@karlphillip:好主意。但是,我在获取它们时提供了实际的全尺寸屏幕截图。它们被缩小了 50% 以适应这篇文章,但除此之外,它们与我在 Android 设备上得到的完全一样。我不想错过任何可能导致此问题的上下文。
-
在那里,我编辑了问题以改进格式。您仍然可以右键单击图像并在新选项卡中打开它们以查看全分辨率图像。编辑问题并观察用于调整图像大小的标记代码。它极大地提高了问题的可读性。