image_processing/optical_flow.cpp
/*******************************************************
* Copyright (c) 2014, ArrayFire
* All rights reserved.
*
* This file is distributed under 3-clause BSD license.
* The complete license agreement can be obtained at:
* https://arrayfire.com/licenses/BSD-3-Clause
********************************************************/
#include <arrayfire.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
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 = constant(1, 1, 2) / 4.0;
Ix = convolve(I1, dx) + convolve(I2, dx);
Iy = convolve(I1, dy) + convolve(I2, dy);
It = convolve(I2, dt) - convolve(I1, dt);
}
static void optical_flow_demo(bool console) {
af::Window wnd("Horn-Schunck Optical Flow Demo");
wnd.setColorMap(AF_COLORMAP_COLORS);
double time_total = 10; // run for N seconds
const float h_mean_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 mean_kernel = array(dim4(3, 3), h_mean_kernel, afHost);
array I1 =
loadImage(ASSETS_DIR "/examples/images/circle_left.ppm"); // grayscale
array I2 = loadImage(ASSETS_DIR "/examples/images/circle_center.ppm");
array u = constant(0, I1.dims()), v = constant(0, I1.dims());
array Ix, Iy, It;
diffs(Ix, Iy, It, I1, I2);
timer time_start, time_last;
time_start = time_last = timer::start();
int iter = 0, iter_last = 0;
double max_rate = 0;
while (true) {
iter++;
array u_ = convolve(u, mean_kernel);
array v_ = convolve(v, mean_kernel);
const float alphasq = 0.1f;
array num = Ix * u_ + Iy * v_ + It;
array den = alphasq + Ix * Ix + Iy * Iy;
array tmp = 0.01 * num;
u = u_ - (Ix * tmp) / den;
v = v_ - (Iy * tmp) / den;
if (!console) {
wnd.grid(2, 2);
wnd(0, 0).image(I1, "I1");
wnd(1, 0).image(I2, "I2");
wnd(0, 1).image(u, "u");
wnd(1, 1).image(v, "v");
wnd.show();
}
double elapsed = timer::stop(time_last);
if (elapsed > 1) {
double rate = (iter - iter_last) / elapsed;
double total_elapsed = timer::stop(time_start);
time_last = timer::start();
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 %f iterations per second (max)\n", max_rate);
}
}
int main(int argc, char* argv[]) {
int device = argc > 1 ? atoi(argv[1]) : 0;
bool console = argc > 2 ? argv[2][0] == '-' : false;
try {
af::setDevice(device);
printf("Horn-Schunck optical flow\n");
optical_flow_demo(console);
} catch (af::exception& e) {
fprintf(stderr, "%s\n", e.what());
throw;
}
return 0;
}
af::dim4
Generic object that represents size and shape.
Definition: dim4.hpp:33
af::info
AFAPI void info()
af::constant
array constant(T val, const dim4 &dims, const dtype ty=(af_dtype) dtype_traits< T >::ctype)
af::setDevice
AFAPI void setDevice(const int device)
Sets the current device.
af::timer::start
static AFAPI timer start()
af::array
A multi dimensional data container.
Definition: array.h:35
afHost
@ afHost
Host pointer.
Definition: defines.h:234
af
Definition: algorithm.h:15
af::max
AFAPI array max(const array &in, const int dim=-1)
C++ Interface for maximum values in an array.
AF_COLORMAP_COLORS
@ AF_COLORMAP_COLORS
Colors, aka. Rainbow.
Definition: defines.h:456
afcl::array
static af::array array(af::dim4 idims, cl_mem buf, af::dtype type, bool retain=false)
Create an af::array object from an OpenCL cl_mem buffer.
Definition: opencl.h:327
af::exception
An ArrayFire exception class.
Definition: exception.h:29
af::array::dims
dim4 dims() const
Get dimensions of the array.
af::loadImage
AFAPI array loadImage(const char *filename, const bool is_color=false)
C++ Interface for loading an image.
af::timer::stop
static AFAPI double stop()
arrayfire.h
af::timer
Internal timer object.
Definition: timing.h:36
af::exception::what
virtual const char * what() const
Returns an error message for the exception in a string format.
Definition: exception.h:60
af::convolve
AFAPI array convolve(const array &signal, const array &filter, const convMode mode=AF_CONV_DEFAULT, const convDomain domain=AF_CONV_AUTO)
C++ Interface for convolution any(one through three) dimensional signals.
af::Window
Window object to render af::arrays.
Definition: graphics.h:37