예제 #1
0
DCTFFTW::DCTFFTW(int _sizex, int _sizey, int _dctmode, int _bitsPerSample) :
    DCTClass(_sizex , _sizey, _dctmode, _bitsPerSample)
{
    int size2d = sizey*sizex;

    int cursize = 1;
    dctshift = 0;
    while (cursize < size2d)
    {
        dctshift++;
        cursize = (cursize<<1);
    }

    dctshift0 = dctshift + 2;

    fSrc = (float *)fftwf_malloc(sizeof(float) * size2d );
    fSrcDCT = (float *)fftwf_malloc(sizeof(float) * size2d );

    g_fftw_plans_mutex.lock();
    dctplan = fftwf_plan_r2r_2d(sizey, sizex, fSrc, fSrcDCT,
            FFTW_REDFT10, FFTW_REDFT10, FFTW_ESTIMATE); // direct fft
    g_fftw_plans_mutex.unlock();
}
예제 #2
0
Image FFTPoisson::apply(Window dx, Window dy, Window target, float targetStrength) {
    
    assert(dx.width == dy.width &&
           dx.height == dy.height &&
           dx.frames == dy.frames &&
           dx.channels == dy.channels,
           "x gradient must be same size as y gradient\n");
    if (target) {
        assert(target.width == dx.width &&
               target.height == dx.height &&
               target.frames == dx.frames &&
               target.channels == dx.channels,
               "target image must have the same size as the gradient images\n");               
    }

    Image fftBuff(dx.width, dx.height, dx.frames, 1);

    //compute two 1D lookup tables for computing the DCT of a 2D Laplacian on the fly    
    Image ftLapY(1, dx.height, 1, 1);
    Image ftLapX(dx.width, 1, 1, 1);

    for(int x = 0; x < dx.width; x++)
        ftLapX(x, 0)[0] = 2.0f * cos((M_PI * x) / (dx.width - 1));
    
    for(int y = 0; y < dx.height; y++)
        ftLapY(0, y)[0] = -4.0f + (2.0f * cos((M_PI * y) / (dx.height - 1)));
    
    // Create a DCT-I plan, which is its own inverse.
    fftwf_plan fftPlan;        
    fftPlan = fftwf_plan_r2r_2d(dx.height, dx.width, 
                                fftBuff(0, 0), fftBuff(0, 0), 
                                FFTW_REDFT00, FFTW_REDFT00, FFTW_ESTIMATE); //use FFTW_PATIENT when plan can be reused
    
    Image out(dx.width, dx.height, dx.frames, dx.channels);

    for (int t = 0; t < dx.frames; t++) {
        for (int c = 0; c < dx.channels; c++) {            

            float dcSum = 0.0f;
            
            // compute h_hat from u, gx, gy (see equation 48 in the paper), as well as the DC term of u's DCT.
            float *fftPtr = fftBuff(0, 0);
            for(int y = 0; y < dx.height; y++) {
                for(int x = 0; x < dx.width; x++) {
                    // Compute DC term of u's DCT without computing the whole DCT.
                    float dcMult = 1.0f;
                    if ((x > 0) && (x < dx.width  - 1))
                        dcMult *= 2.0f;
                    if ((y > 0) && (y < dx.height - 1))
                        dcMult *= 2.0f;
                    
                    if (target) {
                        dcSum += dcMult * target(x, y, t)[c];
                    } else { 
                        // try to read the dc term out of the double
                        // integral of the gradient fields
                        // instead. Works if the gradients were
                        // computed with a zero boundary condition.
                        dcSum += 2.0f*((dx.width-x)*dx(x, y, t)[c] + (dy.height-y)*dy(x, y, t)[c]);
                    }
                    
                    
                    if (target) 
                        *fftPtr = targetStrength * target(x, y, t)[c];                    
                    else 
                        *fftPtr = 0;

                    // Subtract g^x_x and g^y_y, with boundary factor of -2.0 to account for boundary reflections implicit in the DCT
                    if (x == 0) {
                        *fftPtr -= (+2.0f * dx(x+1, y, t)[c]);
                    } else if (x == dx.width - 1) {
                        *fftPtr -= (-2.0f * dx(x, y, t)[c]);
                    } else {
                        *fftPtr -= (dx(x+1, y, t)[c] - dx(x, y, t)[c]);
                    }

                    if (y == 0) {
                        *fftPtr -= (+2.0f * dy(x, y+1, t)[c]);
                    } else if (y == dx.height -1) {
                        *fftPtr -= (-2.0f * dy(x, y, t)[c]);
                    } else {
                        *fftPtr -= (dy(x, y+1, t)[c] - dy(x, y, t)[c]);
                    }

                    
                    fftPtr++;
                }
            }

            //transform h_hat to H_hat by taking the DCT of h_hat
            fftwf_execute(fftPlan);

            //compute F_hat using H_hat (see equation 29 in the paper)
            fftPtr = fftBuff(0, 0);
            for(int y = 0; y < dx.height; y++) {
                for(int x = 0; x < dx.width; x++) {
                    float ftLapResponse = ftLapY(0, y)[0] + ftLapX(x, 0)[0];
                    *fftPtr++ /= (targetStrength - ftLapResponse);
                }
            }
            
            fftBuff(0, 0)[0] = dcSum;
            
            //transform F_hat to f_hat by taking the inverse DCT of F_hat
            fftwf_execute(fftPlan);

            float fftMult = 1.0f / (4.0f * (dx.width-1) * (dx.height-1));

            fftPtr = fftBuff(0, 0);
            
            for(int y = 0; y < dx.height; y++) {
                for(int x = 0; x < dx.width; x++) {
                    out(x, y, t)[c] = (*fftPtr++) * fftMult;
                }
            }
            
        }
    }

    fftwf_destroy_plan(fftPlan);

    return out;
    
}