在 Android 上模糊图像中的区域(在 Java 中)

Y.S*_*Y.S 7 android opencv

在我的 Android 应用程序中,我从后台服务以编程方式捕获屏幕截图。我以Bitmap.

接下来,我使用以下 Android 框架 API 获取感兴趣区域 (ROI) 的坐标:

Rect ROI = new Rect();
viewNode.getBoundsInScreen(ROI);
Run Code Online (Sandbox Code Playgroud)

这里,getBoundsInScreen()是 Javascript 函数的 Android 等价物getBoundingClientRect()。

RectAndroid 中的A具有以下属性:

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()
Run Code Online (Sandbox Code Playgroud)

Android Rect 对象中的顶部、左侧、右侧和底部是什么意思

而RectOpenCV 中的a具有以下属性

rect.width
rect.height
rect.x    /* x coordinate of the top-left corner  */
rect.y    /* y coordinate of the top-left corner  */
Run Code Online (Sandbox Code Playgroud)

现在,在我们可以执行任何与 OpenCV 相关的操作之前,我们需要将 AndroidRect转换为 OpenCV Rect。

了解 drawRect 或绘图坐标在 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);
Run Code Online (Sandbox Code Playgroud)

现在我正在执行的 OpenCV 操作之一是模糊屏幕截图中的 ROI:

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);
Run Code Online (Sandbox Code Playgroud)

这使我们非常接近预期的结果。几乎在那里,但不完全。目标区域正下方的区域是模糊的。

例如,如果目标感兴趣区域是密码字段,则上述代码会产生以下结果:

左侧是Microsoft Live ROI,右侧是Pinterest ROI:

可以看出,ROI正下方的区域变得模糊。

所以我的问题是,最后,为什么感兴趣的确切区域没有模糊?

  • 通过 Android API 获得的坐标getBoundsInScreen()似乎是正确的。
  • 将 AndroidRect转换为 OpenCVRect似乎也是正确的。或者是吗?
  • 用于模糊感兴趣区域的代码似乎也是正确的。有没有另一种方法可以做同样的事情?

注意:我已经提供了实际的全尺寸屏幕截图。它们已经缩小了 50% 以适应这篇文章,但除此之外,它们与我在 Android 设备上得到的完全一样。

kar*_*lip 4

如果我没记错的话,OpenCVRect会假设x并y指定矩形的左上角:

/* Compute the top-left corner using the center point of the rectangle
 * TODO: take care of float to int conversion
 */
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);
Run Code Online (Sandbox Code Playgroud)