1 /**
2 Module containts optical flow plotting functions.
3 
4 Copyright: Copyright Relja Ljubobratovic 2016.
5 
6 Authors: Relja Ljubobratovic
7 
8 License: $(LINK3 http://www.boost.org/LICENSE_1_0.txt, Boost Software License - Version 1.0).
9 */
10 
11 module dcv.plot.opticalflow;
12 
13 import mir.ndslice.slice : Slice, sliced, SliceKind;
14 import mir.ndslice.algorithm;
15 
16 /**
17  * Draw color-coded optical flow.
18  * 
19  * params:
20  * flow = Optical flow displacement vectors.
21  * maxSize = Value which is considered to be the maximal
22  * displacement value for color saturation. Default is 
23  * 0, which gets reset in the algorithm to 10% of image 
24  * diagonal length.
25  * 
26  * returns:
27  * RGB image of color-coded optical flow.
28  */
29 Slice!(SliceKind.contiguous, [3], ubyte*) colorCode(Slice!(SliceKind.contiguous, [3], float*) flow, float maxSize = 0)
30 {
31     import std.math : sqrt;
32     import std.array : array;
33 
34     import dcv.core.algorithm : ranged;
35     import dcv.imgproc.color : hsv2rgb;
36 
37     if (maxSize == 0)
38     {
39         maxSize = (cast(float)(flow.length!0) ^^ 2 + cast(float)(flow.length!1) ^^ 2).sqrt;
40         maxSize *= 0.1; // expect max flow displacement to be 10% of the diagonal
41     }
42 
43     auto hsv = new float[flow.length!0 * flow.length!1 * 3].sliced(flow.length!0, flow.length!1, 3);
44 
45     foreach (r; 0 .. flow.length!0)
46     {
47         foreach (c; 0 .. flow.length!1)
48         {
49             import std.math : sqrt, atan2, PI;
50 
51             float fx = flow[r, c, 0];
52             float fy = flow[r, c, 1];
53 
54             float rad = sqrt(fx * fx + fy * fy);
55             float a = atan2(fy, fx) / PI;
56 
57             auto pix = hsv[r, c];
58             pix[0] = a * 180.0f + 180.0f;
59             pix[1] = rad;
60             pix[2] = 1.0f;
61         }
62     }
63 
64     hsv[0 .. $, 0 .. $, 1].ranged(0.0f, maxSize)[] /= maxSize;
65 
66     return hsv.hsv2rgb!ubyte; // Convert to RGB, and return...
67 }