#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)
{
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;
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;
}