3 #include "opticalflow.h"
5 #include <opencv2/core/core_c.h>
6 #include <opencv2/imgproc/imgproc_c.h>
7 #include <opencv2/video/tracking.hpp>
8 #include "dir_seperator.h"
10 int flow_enable = 0, flow_window, flow_view_vector, flow_view_uv;
12 void flow_default(void)
15 flow_view_vector = 16;
16 flow_view_uv = 0; /* disabled */
19 /* draw flow matrix as lines */
20 static void draw_lines_from_matrix(CvMat *flow, int width, int height, int steps, int color, IplImage *image)
22 int flow_width = width / steps;
23 int flow_height = height / steps;
27 for (i = 0, y = steps/2; i < flow_height && y < height; i++, y += steps) {
28 f = (const float *)(flow->data.ptr + flow->step * y);
29 for (j = 0, x = steps/2; j < flow_width && x < width; j++, x += steps) {
31 cvPoint(cvRound(x), cvRound(y)),
32 cvPoint(cvRound(f[2*x] + x), cvRound(f[2*x+1] + y)),
33 CV_RGB(color,color,color),
39 /* take flow matrix to generate a map */
40 static void copy_matrix_to_map(CvMat *flow, int width, int height, double *flow_map_x, double *flow_map_y)
45 for (y = 0; y < height; y++) {
46 f = (const float *)(flow->data.ptr + flow->step * y);
47 for (x = 0; x < width; x++) {
57 * img_prev_buffer = image buffer of previous image (or NULL)
58 * img_next_buffer = image buffer of next image (or NULL)
59 * img_buffer = current image buffer
60 * width, height = dimensions of image buffer
61 * steps = pixles between each feature = size of grid to track
62 * win_size = flow algorithm window size
63 * max_flow = maximum length of allowed flow vector (to avoid errors)
64 * flow_map_x_prev = flow map for delta x of previous image (result is stored here)
65 * flow_map_y_prev = flow map for delta y of previous image (result is stored here)
66 * flow_map_x_next = flow map for delta x of next image (result is stored here)
67 * flow_map_y_next = flow map for delta y of next image (result is stored here)
70 void *create_flow_maps(const double *img_prev_buffer, const double *img_next_buffer, const double *img_buffer, int width, int height, int win_size, int steps, double *flow_map_x_prev, double *flow_map_y_prev, double *flow_map_x_next, double *flow_map_y_next, void *_image_preview)
72 IplImage *image_prev = NULL, *image = NULL, *image_next = NULL, *image_preview = _image_preview;
77 const float pyrScale = 0.5;
78 const float levels = 3;
79 const float winsize = win_size;
80 const float iterations = 8;
81 const float polyN = 5;
82 const float polySigma = 1.2;
85 flow = cvCreateMat(height, width, CV_32FC2);
87 fprintf(stderr, "failed to allocate opencv matrix\n");
91 /* apply images to opencv image */
94 if (img_prev_buffer) {
95 image_prev = cvCreateImage(size, IPL_DEPTH_32F, 1);
98 image = cvCreateImage(size, IPL_DEPTH_32F, 1);
100 if (img_next_buffer) {
101 image_next = cvCreateImage(size, IPL_DEPTH_32F, 1);
105 for (i = 0; i < height; i++) {
106 for (j = 0; j < width; j++) {
107 CV_IMAGE_ELEM(image_prev, float, i, j) = img_prev_buffer[i*width+j] * 65535.0;
112 for (i = 0; i < height; i++) {
113 for (j = 0; j < width; j++) {
114 CV_IMAGE_ELEM(image, float, i, j) = img_buffer[i*width+j] * 65535.0;
116 CV_IMAGE_ELEM(image_preview, uchar, i, j) = (img_buffer[i*width+j] / 2) * 255.0;
121 for (i = 0; i < height; i++) {
122 for (j = 0; j < width; j++) {
123 CV_IMAGE_ELEM(image_next, float, i, j) = img_next_buffer[i*width+j] * 65535.0;
128 /* optical flow and compose previous and next image with current image */
132 cvCalcOpticalFlowFarneback(image, image_prev, flow, pyrScale, levels, winsize, iterations, polyN, polySigma, flags);
133 if (image_preview && steps > 1)
134 draw_lines_from_matrix(flow, width, height, steps, 255, image_preview);
135 if (flow_map_x_prev && flow_map_y_prev)
136 copy_matrix_to_map(flow, width, height, flow_map_x_prev, flow_map_y_prev);
139 cvCalcOpticalFlowFarneback(image, image_next, flow, pyrScale, levels, winsize, iterations, polyN, polySigma, flags);
140 if (image_preview && steps > 1)
141 draw_lines_from_matrix(flow, width, height, steps, 192, image_preview);
142 if (flow_map_x_next && flow_map_y_next)
143 copy_matrix_to_map(flow, width, height, flow_map_x_next, flow_map_y_next);
148 #include<opencv/highgui.h>
149 cvNamedWindow( "Display window", 0 );// Create a window for display.
150 cvShowImage( "Display window", image ); // Show our image inside it.
154 cvReleaseImage(&image);
156 cvReleaseImage(&image_prev);
158 cvReleaseImage(&image_next);
162 return image_preview;
166 * use img_buffer and create view of optical flow between this image, previous image and next image.
168 * filename_prev = name of previous image
169 * filename_next = name of next image
170 * img_buffer = current image buffer
171 * width, height = dimensions of image buffer
172 * win_size = flow algorithm window size
173 * steps = pixles between each feature to visualize vectors (1 to disable)
174 * uv_scale = apply vector (pointing to next plane) by applying uv-color (0 to disable)
177 void create_flow_view(const char *filename_prev, const char *filename_next, unsigned short *_img_buffer, int width, int height, int win_size, int steps, int uv_scale)
179 double *img_prev_buffer = NULL, *img_next_buffer = NULL, *img_buffer;
180 double *flow_map_x_prev = NULL, *flow_map_y_prev = NULL, *flow_map_x_next = NULL, *flow_map_y_next = NULL;
181 IplImage *image_preview = NULL;
190 cvInitMatHeader(&kernel, 3, 3, CV_64FC1, vals, 0);
193 //printf("%s %s\n", filename_prev, filename_next);
195 /* convert current image to double */
196 img_buffer = (double *)malloc(width*height*3*sizeof(double));
198 printf("%s:failed to allocate memory\n", __func__);
201 img2array_short(_img_buffer, width, height, img_buffer, width, height);
202 rgb2yuv(img_buffer, img_buffer, width, height);
204 /* read previous image */
206 img = load_img(&w, &h, filename_prev, 0);
208 if (w == width && h == height) {
209 img_prev_buffer = (double *)malloc(w*h*3*sizeof(double));
210 if (img_prev_buffer) {
211 img2array_short(img, w, h, img_prev_buffer, w, h);
212 rgb2yuv(img_prev_buffer, img_prev_buffer, width, height);
219 /* read next image */
221 img = load_img(&w, &h, filename_next, 0);
223 if (w == width && h == height) {
224 img_next_buffer = (double *)malloc(w*h*3*sizeof(double));
225 if (img_next_buffer) {
226 img2array_short(img, w, h, img_next_buffer, w, h);
227 rgb2yuv(img_next_buffer, img_next_buffer, width, height);
234 /* apply images to opencv image */
236 size.height = height;
237 image_preview = cvCreateImage(size, IPL_DEPTH_8U, 1);
239 flow_map_x_prev = (double *)malloc(sizeof(double)*width*height);
240 flow_map_y_prev = (double *)malloc(sizeof(double)*width*height);
241 flow_map_x_next = (double *)malloc(sizeof(double)*width*height);
242 flow_map_y_next = (double *)malloc(sizeof(double)*width*height);
245 image_preview = create_flow_maps(img_prev_buffer, img_next_buffer, img_buffer, width, height, win_size, steps, flow_map_x_prev, flow_map_y_prev, flow_map_x_next, flow_map_y_next, image_preview);
247 /* paint vectors from image_preview to img_buffer */
248 for (i = 0; i < height; i++) {
249 for (j = 0; j < width; j++) {
250 c = CV_IMAGE_ELEM(image_preview, uchar, i, j);
255 } else if (c > 160) {
260 if (!steps && uv_scale)
262 if (img_next_buffer && uv_scale) {
265 flow_map_x_next[width * i + j] / uv_scale,
266 flow_map_y_next[width * i + j] / uv_scale,
269 r = ((double)c) / 255.0;
270 g = ((double)c) / 255.0;
271 b = ((double)c) / 255.0;
274 _img_buffer[(i*width+j)*3 + 0] = r * 65535.0;
275 _img_buffer[(i*width+j)*3 + 1] = g * 65535.0;
276 _img_buffer[(i*width+j)*3 + 2] = b * 65535.0;
285 free(img_prev_buffer);
287 free(img_next_buffer);
289 free(flow_map_x_prev);
291 free(flow_map_y_prev);
293 free(flow_map_x_next);
295 free(flow_map_y_next);
297 cvReleaseImage(&image_preview);