openCL optical flow

Here's how to do optical flow in openCL. I converted this from an openGL shader here http://002.vade.info/?p=32

__kernel void optical_flow(read_only image2d_t srcImage1, read_only image2d_t srcImage2, write_only image2d_t dstImage, const float scale, const float offset, const float lambda, const float threshold) {
int2 coords = (int2)(get_global_id(0), get_global_id(1));
float4 a = read_imagef(srcImage1, CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST, coords);
float4 b = read_imagef(srcImage2, CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST, coords);
int2 x1 = (int2)(offset, 0.f);
int2 y1 = (int2)(0.f, offset);
//get the difference
float4 curdif = b - a;
 
//calculate the gradient
float4 gradx = read_imagef(srcImage2, CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST, coords+x1)
- read_imagef(srcImage2, CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST, coords-x1);
 
gradx += read_imagef(srcImage1, CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST, coords+x1)
- read_imagef(srcImage1, CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST, coords-x1);
 
float4 grady = read_imagef(srcImage2, CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST, coords+y1)
- read_imagef(srcImage2, CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST, coords-y1);
 
grady += read_imagef(srcImage1, CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST, coords+y1)
- read_imagef(srcImage1, CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST, coords-y1);
float4 sqr = (gradx*gradx)+(grady*grady)+(float4)(lambda,lambda, lambda, lambda);
float4 gradmag = sqrt(sqr);
 
 
float4 vx = curdif*(gradx/gradmag);
 
 
float vxd = vx.x;//assumes greyscale
 
//format output for flowrepos, out(-x,+x,-y,+y)
float2 xout = (float2)(fmax(vxd,0.f),fabs(fmin(vxd,0.f)));
xout *= scale;
 
float4 vy = curdif*(grady/gradmag);
float vyd = vy.x;//assumes greyscale
//format output for flowrepos, out(-x,+x,-y,+y)
float2 yout = (float2)(fmax(vyd,0.f),fabs(fmin(vyd,0.f)));
yout *= scale;
 
 
float4 out = (float4)(xout, yout);
float cond = (float)isgreaterequal(length(out), threshold);
out *= cond;
write_imagef(dstImage, coords, out);
}

Comments

Marek, thanks for this example.

I have ported this to QC, a fairly trivial exercise, mostly being a matter of setting the terms in the kernel function from

 read_only image2d_t

to

 __rd image2d_t

or

 __wr image2d_t .

See OpenCL Optical Flow Port.

Still a work in progress, but fun.

Cheers, cybero

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <c>, <cpp>, <drupal5>, <drupal6>, <java>, <javascript>, <php>, <python>, <ruby>. The supported tag styles are: <foo>, [foo].
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <c>, <cpp>, <drupal5>, <drupal6>, <java>, <javascript>, <php>, <python>, <ruby>. The supported tag styles are: <foo>, [foo].
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Type the characters you see in this picture. (verify using audio)
Type the characters you see in the picture above; if you can't read them, submit the form and a new image will be generated. Not case sensitive.