如何加快逐像素PImage图像处理的速度?

huangapple go评论61阅读模式
英文:

How to make pixel by pixel PImage manipulation faster?

问题

我正在制作一个安卓应用程序,其中包含一个简单的相机界面以及一个滤镜列表,用于处理相机拍摄的图片。我在Java中使用Processing库(https://processing.org/),以及在Processing IDE中使用Ketai库(http://ketai.org/)。

以下是我的程序主要运行方式:

--- 我有一个相机对象和一个空白图像对象。图像对象的分辨率与相机的分辨率相同。

--- 从相机读取也会返回一个图像对象。让我们将相机返回的图像称为cameraImage,空白图像称为dummyImage。

--- 在每一帧,我使用相机图像的像素数组从相机中读取,将每个像素单独复制到dummyImage的相应坐标位置。

--- 正是在从cameraImage复制到dummyImage时,我根据用户选择的选项来操纵像素。

--- 我提取每个像素的红色、绿色和蓝色值,然后使用位移(以达到最大效率)来进行处理。

--- 在复制到dummyImage完成后,我将dummyImage作为普通图像显示在屏幕上。

现在的问题是,当我直接显示cameraImage时,我可以轻松获得大约50到60帧每秒。但是当我在复制后显示dummyImage时,我只能获得大约1.5帧每秒。

以下代码演示了我如何从cameraImage复制到dummyImage。它没有任何滤镜,但会花费与任何滤镜相同的时间。

  cameraImage.read();
  cameraImage.loadPixels();
  dummyImage.loadPixels();
  for (int x = 0; x < cameraImage.width; x++){
    for (int y = 0; y < cameraImage.height; y++){
      int index = x + (y * cameraImage.width);
      color currentPixel = cameraImage.pixels[index];
      
      float r = currentPixel >> 16 & 0xFF;
      float g = currentPixel >> 8 & 0xFF;
      float b = currentPixel & 0xFF;
      
      dummyImage.pixels[index] = color(r, g, b);
    }
  }
  dummyImage.updatePixels();
  image(dummyImage);

我想知道如何将帧率提高到至少20帧每秒。如果需要额外的信息,请进行评论,我会尽快回复。

英文:

I am making an android app, wherein there is a simple camera UI along with a filter list to manipulate pictures clicked by the camera.
I am using the Processing library (https://processing.org/) in Java along with the Ketai library (http://ketai.org/) in the processing IDE.

Following is how my program primarily runs:

--- I have a camera object and an empty image object. The image object has the same resolution as that of the camera.

--- Reading from the camera also returns an image object. Lets call the image returned by the camera as cameraImage and the empty image as dummyImage.

--- At each frame, I read from the camera using the pixel array of the cameraImage, I copy each pixel individually to the dummyImage at the respective coordinate position.

--- It is at this point of copying from the cameraImage to the dummyImage that I manipulate the pixels according to the options selected by the user.

--- I take the red, green and blue values of each pixel while copying it using bit shifting (to gain maximum efficiency) and then manipulate it.

--- After copying to the dummyImage is done, I display the dummyImage to the screen as a normal Image.

Now the thing is the when I display the cameraImage directly, I am easily able to get around 50 to 60 fps. But when I display the dummyImage after copying, I get approximately 1.5 fps.

The following code demonstrates how I am copying from cameraImage to dummyImage. It doesn't have any filters but would take as much time as with any filters.

  cameraImage.read();
  cameraImage.loadPixels();
  dummyImage.loadPixels();
  for (int x = 0; x &lt; cameraImage.width; x++){
    for (int y = 0; y &lt; cameraImage.height; y++){
      int index = x + (y * cameraImage.width);
      color currentPixel = cameraImage.pixels[index];
      
      float r = currentPixel &gt;&gt; 16 &amp; 0xFF;
      float g = currentPixel &gt;&gt; 8 &amp; 0xFF;
      float b = currentPixel &amp; 0xFF;
      
      dummyImage[index] = color(r, g, b)
    }
  }
  dummyImage.updatePixels();
  image(dummyImage);

I would like to know how I can increase the frames upto atleast 20 per second. Please comment for extra information, I would reply as soon as possible.

答案1

得分: 1

  • = 0xff000000 | ((int) (r) &lt;&lt; 16 | (int) (g) &lt;&lt; 8 | (int) (b)) 替换 = color(r, g, b)
  • 在 Processing 中不能并行进行图形的光栅化,但可以并行读/写 pixels[] 数组(然后在之后使用 updatePixels()),因此可以使用 thread() 将像素迭代分割到多个 CPU 线程上。
  • 不要调用 image(dummyImage),因为这会涉及第二次遍历像素以将它们复制到 PApplet 中,而是直接在循环内部写入 PApplet(删除所有对 dummyImage 的引用,改为使用 pixels[index] = ...)。
  • 由于逐像素计算具有极强的并行性,你甚至可以考虑编写一个 glsl 着色器(Processing 中有许多此类示例),或者使用 Aparapi,它可以将 Java 代码转换为 GPU 可用的 OpenCL 代码(我在使用 Processing 时曾成功使用过这个工具)。
英文:

A few possible optimisations:

  • Replace = color(r, g, b) with = 0xff000000 | ((int) (r) &lt;&lt; 16 | (int) (g) &lt;&lt; 8 | (int) (b)).

  • You can't rasterize graphics in Processing in parallel but you can read/write to the pixels[] array in parallel (then updatePixels() afterwards), so use thread() to split pixel iteration over multiple CPU threads.

  • Rather than calling image(dummyImage), which involves a second pass over the pixels to copy them into the PApplet, write into the PApplet directly within the loop (remove all references to dummyImage and use pixels[index] = ... instead).

  • As pixel-by-pixel computation is embarrassingly parallel, you could even consider writing a glsl shader (there's lots of Processing examples of this) or use Aparapi, which converts Java code to GPU-ready OpenCL (I've had success using this with Processing).

huangapple
  • 本文由 发表于 2020年10月20日 15:31:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/64440485.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定