英文:
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 < 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[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) << 16 | (int) (g) << 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) << 16 | (int) (g) << 8 | (int) (b))
. -
You can't rasterize graphics in Processing in parallel but you can read/write to the
pixels[]
array in parallel (thenupdatePixels()
afterwards), so usethread()
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 thePApplet
, write into the PApplet directly within the loop (remove all references todummyImage
and usepixels[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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论