yusuketomoto / ofxEvm

EVM(Eulerian Video Magnification) addon for openFrameworks
120 stars 31 forks source link

ideal bandpassing #2

Open wzpan opened 10 years ago

wzpan commented 10 years ago

Hi,

First of all excellent transplanting! However, looks like you stuck on implementing ideal bandpass filter. Maybe another example code can help you.

I've adopt the butterworth filter to ideal bandpass filter, according to Eq.(5.4-1), page 244, paragraph 5.4.1, Gonzalez Woods, "Digital Image Processing 2nd Edition":

/**
 * create_ideal_bandpass_filter -   create a 2-channel ideal band-pass filter
 *      with radius D, order n (assumes pre-aollocated size of dft_Filter specifies dimensions)
 *
 * @param dft_Filter    -   destinate filter
 * @param D             -   radius
 * @param W             -   band width
 */
void create_ideal_bandpass_filter(cv::Mat &dft_Filter, int D, int W)
{
    cv::Mat tmp = cv::Mat(dft_Filter.rows, dft_Filter.cols, CV_32F);

    Point centre = Point(dft_Filter.rows / 2, dft_Filter.cols / 2);
    double radius;

    for (int i = 0; i < dft_Filter.rows; i++)
    {
        for (int j = 0; j < dft_Filter.cols; j++)
        {
            // D(u, v)
            radius = (double) sqrt(pow((i - centre.x), 2.0) + pow((double) (j - centre.y), 2.0));

            if (radius >= D - W/2 && radius <= D + W/2)
                tmp.at<float>(i, j) = 1;
            else
                tmp.at<float>(i, j) = 0;
        }
    }

    cv::Mat toMerge[] = {tmp, tmp};
    merge(toMerge, 2, dft_Filter);
}

To apply this, DFT and IDFT are needed, just like main() function from the above example does. But for the moment I can't figure out how to use this in your addon.

May that help you. ;-)

wzpan commented 10 years ago

Unfortunately I have tried to adopt this to implement an ideal band-pass filter but I just can't make it works like we want. The resulting frames are only black and nothing to see. If you are interested in my implementation, check my forked version.

Another python EVM project gives a very clear implementation, within only 10 lines but works pretty well:

def temporal_bandpass_filter(data, fps, freq_min=0.833, freq_max=1, axis=0):
    print "Applying bandpass between " + str(freq_min) + " and " + str(freq_max) + " Hz"
    # perform FFT on each frame
    fft = scipy.fftpack.fft(data, axis=axis)
    # sampling frequencies, where the step d is 1/samplingRate
    frequencies = scipy.fftpack.fftfreq(data.shape[0], d=1.0 / fps)
    # find the indices of low cut-off frequency
    bound_low = (numpy.abs(frequencies - freq_min)).argmin()
    # find the indices of high cut-off frequency
    bound_high = (numpy.abs(frequencies - freq_max)).argmin()
    # band pass filtering
    fft[:bound_low] = 0
    fft[-bound_low:] = 0
    fft[bound_high:-bound_high] = 0
    # perform inverse FFT
    return scipy.fftpack.ifft(fft, axis=0)

Unfortunately it seems non-trivial to do the frequency sampling in C++. At least I can't find a suitable function that does this job.

If any of you are knowledgeable at(or interested in) implementing ideal band-passing, don't hesitate to contact me and see if we can make this addon more completed.