Do more. Code less. Free software for GPU computing.
<scroll to top>

examples/optical_flow/optical_flow.cpp

#include <string.h>
#include <stdio.h>
#include <arrayfire.h>
#include "../image/ppm_utils.h"

using namespace af;

static void diffs(array &Ix, array &Iy, array &It, array I1, array I2)
{
    //  3x3 derivative kernels
    float dx_kernel[] = {-1.0f / 6.0f, -1.0f / 6.0f, -1.0f / 6.0f,
                          0.0f / 6.0f,  0.0f / 6.0f,  0.0f / 6.0f,
                          1.0f / 6.0f,  1.0f / 6.0f,  1.0f / 6.0f};
    float dy_kernel[] = {-1.0f / 6.0f,  0.0f / 6.0f,  1.0f / 6.0f,
                         -1.0f / 6.0f,  0.0f / 6.0f,  1.0f / 6.0f,
                         -1.0f / 6.0f,  0.0f / 6.0f,  1.0f / 6.0f};
    array dx = array(dim4(3, 3), dx_kernel);
    array dy = array(dim4(3, 3), dy_kernel);
    array dt = ones(1, 2) / 4.0;

    Ix = convolve(I1, dx, afConvSame) + convolve(I2, dx, afConvSame);
    Iy = convolve(I1, dy, afConvSame) + convolve(I2, dy, afConvSame);
    It = convolve(I2, dt, afConvSame) - convolve(I1, dt, afConvSame);
}

static void optical_flow_demo(bool console)
{
    double time_total = 10; // run for N seconds

    const float h_avg_kernel[] = {1.0f / 12.0f, 2.0f / 12.0f, 1.0f / 12.0f,
                                  2.0f / 12.0f,        0.0f,  2.0f / 12.0f,
                                  1.0f / 12.0f, 2.0f / 12.0f, 1.1f / 12.0f};
    array avg_kernel = array(dim4(3, 3), h_avg_kernel, afHostPointer);

    array I1 = load_gray_ppm("circle_left.ppm");
    array I2 = load_gray_ppm("circle_center.ppm");

    array u = zeros(I1.dims()), v = zeros(I1.dims());
    array Ix, Iy, It; diffs(Ix, Iy, It, I1, I2);

    timer time_start, time_last;
    time_start = time_last = timer::tic();
    int iter = 0, iter_last = 0;
    double max_rate = 0;

    while (true) {
        iter++;
        array u_ = convolve(u, avg_kernel, afConvSame);
        array v_ = convolve(v, avg_kernel, afConvSame);

        const float alphasq = 0.1f;
        array num = mul(Ix, u_) + mul(Iy, v_) + It;
        array den = alphasq + mul(Ix, Ix) + mul(Iy, Iy);

        array tmp = 0.01f *  num;
        u = u_ - mul(Ix, tmp) / den;
        v = v_ - mul(Iy, tmp) / den;

        if (!console) {
            subfigure(2,2,1); imgplot(I1);
            subfigure(2,2,3); imgplot(I2);
            subfigure(2,2,2); imgplot(u);
            subfigure(2,2,4); imgplot(v);
        }

        double elapsed = timer::toc(time_last);
        if (elapsed > 1) {
            double rate = (iter - iter_last) / elapsed;
            double total_elapsed = timer::toc(time_start);
            time_last = timer::tic();
            iter_last = iter;
            max_rate = std::max(max_rate, rate);
            if (total_elapsed >= time_total)
                break;
            if (!console)
                printf("  iterations per second: %.0f   (progress %.0f%%)\n",
                       rate, 100.0f * total_elapsed / time_total);
        }
    }

    if (console)
        printf(" ### optical_flow_example: %f Iterations per second (avg)\n", max_rate);

}

int main(int argc, char* argv[]){

    bool console = false;
    if ( argc > 2 || (argc == 2 && strcmp(argv[1],"-")) ){
        printf("usage: optical_flow [-]\n");
        return -1;
    } else if (argc == 2 && !strcmp(argv[1],"-")) {
        console = true;
    }

    printf("Horn-Schunck optical flow\n");
    try {
        optical_flow_demo(console);
    } catch (af::exception& e) {
        fprintf(stderr, "%s\n", e.what());
    }

    #ifdef WIN32 // pause in Windows
    if (!console) {
        printf("hit [enter]...");
        getchar();
    }
    #endif
    return 0;
}
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines