gpt4 book ai didi

java - Android 实时傅立叶变换 - Renderscript

转载 作者:太空宇宙 更新时间:2023-11-03 10:18:20 25 4
gpt4 key购买 nike

我正在尝试对传入的预览相机帧应用 2D 傅立叶变换。所以这是我在每个 onSurfaceTextureUpdated 上执行的 renderScript 代码:

#pragma version(1)
#pragma rs java_package_name(foo.camerarealtimefilters)

rs_allocation inPixels;
int height;
int width;

void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {

float3 fourierPixel;
for(int k=0; k<=width; k++){
for(int l=0; l<=height; l++){
float3 pixel = convert_float4(rsGetElementAt_uchar4(inPixels, k, l)).rgb;
float greyOrigPixel = (pixel.r + pixel.g + pixel.b)/3;
float angle = 2 * M_PI * ( ((x * k) / width) + ((y * l) / height) );
fourierPixel.rgb = greyOrigPixel*cos(angle);
};
};

out->xyz = convert_uchar3(fourierPixel);
}

inPixels是通过这个方法设置的,

public void setInAllocation(Bitmap bmp) {
inAllocation = Allocation.createFromBitmap(rs, bmp);
fourierScript.set_inPixels(inAllocation);
};

现在我的代码背后的数学?基本上应用欧拉公式,忽略相位项,因为我不能用虚数做太多,只画出幅度,即实数(余弦)部分。如您所见,我当然对图像进行了灰度处理。

这是我的资源:

1) http://homepages.inf.ed.ac.uk/rbf/HIPR2/fourier.htm"...在图像处理中,往往只显示傅立叶变换的幅值,因为它包含了空间域图像几何结构的大部分信息.."

2) http://www.nayuki.io/page/how-to-implement-the-discrete-fourier-transform我从哪里得到欧拉公式,以及我是如何应用它的。

我的问题是,当我启动我的应用程序时,它会给我原始图像,无论相机看到什么,仅此而已。它还会在 2 到 3 秒后卡住。

我的代码有什么问题?处理起来太多了吗?我问的可能吗(我在三星 Galaxy S4 Mini 上运行这个)?我只想在相机框架上应用实时简单 DFT。

最佳答案

如果没有看到 Java 代码,很难说为什么您的图像不会显示更新。不过,这里有一些您可能会尝试提供帮助的事情。

  • 如果您可以处理较低的精度,请使用 float 而不是 double,因为这会提高性能

  • 如果您可以处理较低的精度,请使用 #pragma rs_fp_relaxed 这将有助于提高性能

  • 您可以重新构造您的 RS,使其具有设置函数,该函数应在首次运行之前调用。使用它来设置宽度/高度并预先计算 FFT 方程的固定部分

它看起来像这样:

rs_allocation angles;
uint32_t width;
uint32_t height;
uint32_t total;

void setupPreCalc(uint32_t w, uint32_t h) {
uint32_t x;
uint32_t y;
float curAngle;

width = w;
height = h;
total = w * h;
for (x = 0; x < width; x++) {
for (y = 0; y < height; y++) {
curAngle = 2 * M_PI * (y * width + x);
rsSetElementAt_float(angles, curAngle, x, y);
}
}
}
  • 重新构造您的内核以获取输出 Allocation 元素以及正在操作的 xy 坐标:

void __attribute__((kernel))doFft(uchar4 out, uint32_t x, uint32_t y)

  • 在每一帧之前,将输入分配设置为与您所做的类似,然后重新构建循环以使用角度的预先计算部分。

  • 之前,内核循环遍历输入中的所有坐标,计算灰度像素值,通过类似于您找到的方程式运行它,然后将其设置为新像素值,完成后保存循环最后一次迭代的值作为输出值。这不是你想要的。 RS 已经在输出 Allocation 中为您提供了一个特定位置,因此您需要对与该特定输出点相关的所有输入点进行求和。

使用预计算分配和内核的新形式,它可能看起来像这样:

void __attribute__((kernel)) doFft(uchar4 out, uint32_t x, uint32_t y) {
// Loop over all input allocation points
uint32_t inX;
uint32_t inY;
float curAngle;
float4 curPixel;
float4 curSum = 0.0;

for (inX = 0; inX < width; inX++) {
for (inY = 0; inY < height; inY++) {
curPixel = convert_float4(rsGetElementAt_uchar4(inPixels, x, y));
curPixel.rgb = (curPixel.r + curPixel.g + curPixel.b) / 3;

curAngle = rsGetElementAt_float(angles, inX, inY);
curAngle = curAngle * ((x + (y * width)) / total);

curSum += curPixel * cos(curAngle);
}
}

out = convert_uchar4(curSum);
}

关于java - Android 实时傅立叶变换 - Renderscript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31195653/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com