首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Halide中进行正反FFT

如何在Halide中进行正反FFT
EN

Stack Overflow用户
提问于 2019-12-17 08:10:29
回答 1查看 240关注 0票数 0

我目前正在尝试先做一个正向fft,然后再做一个反向fft,但是它似乎不起作用。我使用的快速傅立叶变换是在fft.cpp (Halide/apps/ FFT )中找到的。我目前的目标只是尝试保存16x16平铺的图像。该16x16瓦片应该是正向的,然后是16x16瓦片的反向fft。我的问题是,由于某种原因,我的输出缓冲区的值是9000。下面是我的代码:

代码语言:javascript
复制
//A program to make an fft of an image both ways (r2c, c2r)
//Plan of action:
//1.)Load in image into buffer using load_image (uint8)
//2.)Then cast it to a float
//3.)Then convert float buffer to a function
//4.)Then set fft2d settings
//5.)Then call real to complex
//6.)Then call complex to real
//7.)Then realize it to an output buffer
//8.)Then save the image

#include <stdio.h>
#include "Halide.h"
#include "fft.h"
#include "halide_image_io.h"

using namespace Halide;
using namespace Halide::Tools;
using namespace std;


template <typename Type1, typename Type2>
void compare(Halide::Buffer<Type1> org, Halide::Buffer<Type2> other);

Var x{"x"}, y{"y"}, c{"c"};
Func real_result;
ComplexFunc complex_result("Complex_Result");
int colour_channel_to_fft = 1; //or 1 , or 2
int tileSize = 16;

int main(){
    Halide::Buffer<uint8_t> unsignedIntTempBuffer = load_image("rgb.png");

    //2.) Then cast it to a float
    Func uint8_tToFloat;
    uint8_tToFloat(x,y,c) = Halide::cast<float>(unsignedIntTempBuffer(x,y,c));

    Halide::Buffer<float> input;
    input = uint8_tToFloat.realize(unsignedIntTempBuffer.width(),unsignedIntTempBuffer.height(),unsignedIntTempBuffer.channels()); //Input becomes a float buffer

    //3.)Then convert float buffer to a greysacle function
    Func in;
    in(x,y) = input(x,y,colour_channel_to_fft); //Third parameter states which RGB grey scale to use

    Halide::Buffer<float> temp;
    temp = in.realize(input.width(), input.height());

    //4.)Then set fft2d settings - the current setting are defaulted
    Fft2dDesc desc;
    desc.gain = 1.0f;
    desc.vector_width = 0;
    desc.parallel = false;

    //5.)Then call real to complex
    complex_result = fft2d_r2c(in, tileSize, tileSize,get_jit_target_from_environment(), desc);    //Max dimension size of 767

    //Load the complex result into the complexBuffer
    Halide::Buffer<float> complexBuffer;
    complexBuffer = complex_result.realize();

    ComplexFunc cmplxIn;
    cmplxIn(x, y) = ComplexExpr(re(complexBuffer(x, y)), im(complexBuffer(x, y))); //IN GENERATOR THEY USE CHANNEL 1 & 0? Not possible due to us only using one channel for real input
    //6.)Then call complex to real
    real_result = fft2d_c2r(cmplxIn,tileSize,tileSize,get_jit_target_from_environment(),desc);
    Halide::Buffer<float>output;
    output = real_result.realize(); // as output(x,y,c) = re(complex_result(x,y)); doesn't work (seg fault)

    Func floatToUInt8;
    floatToUInt8(x,y,c) = Halide::cast<uint8_t>(output(x,y));

    Halide::Buffer<uint8_t> finalOutput = floatToUInt8.realize(tileSize, tileSize, input.channels());//, input.channels());
    save_image(finalOutput, "forwardThenReverseFFT.png");
    cout << "Success" << endl;
    //Func -> Buffer must use a realize
}

template <typename Type1, typename Type2>
void compare(Halide::Buffer<Type1> org, Halide::Buffer<Type2> other){
    string channel = "";
    if (colour_channel_to_fft == 0) channel = "Red";
    else if (colour_channel_to_fft == 1) channel = "Green";
    else if (colour_channel_to_fft == 2) channel = "Blue";
    else cout<< "You have chosen an incorrect channel";
    std::cout << "Original: " << std::endl << channel << " channel value at (0,0) = " << org(3,3) << std::endl;
    std::cout << "FFTd: " << std::endl << channel << " channel value at (0,0) = " << other(0,0) << std::endl << std::endl;
}

保存的图像是:https://i.stack.imgur.com/9Rqtm.png,它似乎与任何通道上的原始图像没有相关性。

你知道我做错了什么吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-18 14:14:48

SleuthEye的发展方向是正确的。我认为问题的一部分是fft2d_r2c的结果是一个元值函数(参见https://halide-lang.org/tutorials/tutorial_lesson_13_tuples.html)。ComplexExpr/ComplexFunc是围绕Tuple和元值Func的包装器,令人有点惊讶的是,它甚至会编译/运行来将这一点的实现分配给Halide::Buffer

另一个问题是实现需要一个大小。(您可能不需要这样做,因为FFT对输出的边界有要求。)对于FFT来说,这有点棘手,因为复杂的域只有部分定义。对于16x16FFT,复数域是16x9,其余的域可以通过利用FFT的共轭对称特性来计算。(https://github.com/halide/Halide/blob/b465318a583ff58114ac63ecd8125ca7e648ae35/apps/fft/fft.h#L55-L56)。

我猜想这就是你所需要的:

代码语言:javascript
复制
//Load the complex result into the complexBuffer
Halide::Realization complexBuffer = complex_result.realize(16, 9);
Halide::Buffer<float> realPart = complexBuffer[0];
Halide::Buffer<float> imagPart = complexBuffer[1];

// Now construct the complex part for `fft2d_c2r` from these two buffers.

我认为,如果你试图认识到(在复杂的域中去往/离开Halide ),事情将会比必要的更困难。通常,如果您使用fft2d_r2c,做一些工作,然后使用fft2d_c2r,所有这些都在一个管道中,Halide的边界推断将意味着您不需要太担心DFT域的奇数边界。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59365930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档