MediaProjection 的 CPU 使用率过高,留给 OCR 的 CPU 使用率却很低?

问题描述 投票:0回答:1

我在 Android 上使用两种不同的方法进行截图:

  1. 通过运行
    /system/bin/screencap -p $path
  2. 使用
    MediaProjection
    API。

即使是完全相同的屏幕,在执行 OCR 时(使用

Tesseract
)我得到不同的结果。

使用

/system/bin/screencap
我得到了预期的结果。 使用
MediaProjection
API 无法正确识别任何或所有文本,因此我需要使用二值化算法对图像进行预处理。

这是为什么呢?我检查了 screencap 源代码,似乎使用 PNG 压缩,配置 ARGB_8888 和质量 100%。 正如您在这里看到的:https://android.googlesource.com/platform/frameworks/base/+/master/cmds/screencap/screencap.cpp

这就是我使用

MediaProjection
API 创建位图的方式:

public class ImageTransmogrifier implements ImageReader.OnImageAvailableListener {
  private final int width;
  private final int height;
  private final ImageReader imageReader;
  private final ScreenshotService svc;
  private Bitmap latestBitmap=null;

  ImageTransmogrifier(ScreenshotService svc) {
    this.svc=svc;

    Display display=svc.getWindowManager().getDefaultDisplay();
    Point size=new Point();

    display.getRealSize(size);

    int width=size.x;
    int height=size.y;

    while (width*height > (2<<19)) {
      width=width>>1;
      height=height>>1;
    }

    this.width=width;
    this.height=height;

    imageReader=ImageReader.newInstance(width, height,
        PixelFormat.RGBA_8888, 2);
    imageReader.setOnImageAvailableListener(this, svc.getHandler());
  }

  @Override
  public void onImageAvailable(ImageReader reader) {
    final Image image=imageReader.acquireLatestImage();

    if (image!=null) {
      Image.Plane[] planes=image.getPlanes();
      ByteBuffer buffer=planes[0].getBuffer();
      int pixelStride=planes[0].getPixelStride();
      int rowStride=planes[0].getRowStride();
      int rowPadding=rowStride - pixelStride * width;
      int bitmapWidth=width + rowPadding / pixelStride;

      if (latestBitmap == null ||
          latestBitmap.getWidth() != bitmapWidth ||
          latestBitmap.getHeight() != height) {
        if (latestBitmap != null) {
          latestBitmap.recycle();
        }

        latestBitmap=Bitmap.createBitmap(bitmapWidth,
            height, Bitmap.Config.ARGB_8888);
      }

      latestBitmap.copyPixelsFromBuffer(buffer);
      image.close();

      ByteArrayOutputStream baos=new ByteArrayOutputStream();
      Bitmap cropped=Bitmap.createBitmap(latestBitmap, 0, 0,
        width, height);

      cropped.compress(Bitmap.CompressFormat.PNG, 100, baos);

      byte[] newPng=baos.toByteArray();

      svc.processImage(newPng);
    }
  }

  Surface getSurface() {
    return(imageReader.getSurface());
  }

  int getWidth() {
    return(width);
  }

  int getHeight() {
    return(height);
  }

  void close() {
    imageReader.close();
  }
}

有人告诉我,基本上我使用更多的处理器来进行记录,而留给 OCR 的时间更少。 OCR 的周期较少,因此在给定时间内准确性会降低。 这也是我不需要用 screencap 预处理图像的原因。因为一次性的高档产品很可能不如持续不断的流经。

这有什么依据吗?如果是这样,我应该使用其他东西来代替 MediaProjection 还是简单地预处理图像?

java android ocr cpu-usage android-mediaprojection
1个回答
0
投票

这有什么基础吗?

不清楚“这个”是什么。

也许“这个”是:

有人告诉我,基本上我使用更多的处理器来进行记录,而留给 OCR 的时间更少

您需要联系 OCR 引擎的供应商,询问他们是否以某种方式根据可用的 CPU 时间来扩展 OCR 质量。否则,我预计 OCR 需要花费多少时间才能完成您所要求的操作,而

onImageAvailable()
的速度只是决定了端到端过程需要多长时间。

也许“这个”是指:

这是为什么?

...大概“那个”指的是:

使用

/system/bin/screencap
我得到了预期的结果。使用 MediaProjection API 无法正确识别任何或所有文本,因此我需要使用二值化算法对图像进行预处理。

我首先将媒体投影 PNG 写入文件,然后将其与

screencap
PNG 的结果进行比较。也许您可以识别两者之间的质量差异或某些东西。不要求两者产生相同的图像,但我不认为差异足以影响 OCR。一个例外是,如果正在进行某种动画,则
screencap
能够比媒体投影 API 更好地与动画同步。另一个有趣的项目是您链接到的
ANDROID_BITMAP_FLAGS_ALPHA_PREMUL
源中的
screencap
,以及 alpha 值是否存在可以解释 OCR 行为的情况。

© www.soinside.com 2019 - 2024. All rights reserved.