Split tracking.c into several files
[blender.git] / source / blender / blenkernel / intern / tracking_detect.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation,
22  *                 Sergey Sharybin
23  *                 Keir Mierle
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/tracking_detect.c
29  *  \ingroup bke
30  *
31  * This file contains blender-side implementation of feature detection.
32  */
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_gpencil_types.h"
37 #include "DNA_movieclip_types.h"
38 #include "DNA_object_types.h"   /* SELECT */
39
40 #include "BLI_utildefines.h"
41
42 #include "BKE_tracking.h"
43
44 #include "IMB_imbuf_types.h"
45 #include "IMB_imbuf.h"
46
47 #include "libmv-capi.h"
48
49 /* Check whether point is inside grease pencil stroke. */
50 static bool check_point_in_stroke(bGPDstroke *stroke, float x, float y)
51 {
52         int i, prev;
53         int count = 0;
54         bGPDspoint *points = stroke->points;
55
56         /* Count intersections of horizontal ray coming from the point.
57          * Point will be inside layer if and only if number of intersection
58          * is uneven.
59          *
60          * Well, if layer has got self-intersections, this logic wouldn't
61          * work, but such situation is crappy anyway.
62          */
63
64         prev = stroke->totpoints - 1;
65
66         for (i = 0; i < stroke->totpoints; i++) {
67                 if ((points[i].y < y && points[prev].y >= y) || (points[prev].y < y && points[i].y >= y)) {
68                         float fac = (y - points[i].y) / (points[prev].y - points[i].y);
69
70                         if (points[i].x + fac * (points[prev].x - points[i].x) < x)
71                                 count++;
72                 }
73
74                 prev = i;
75         }
76
77         return (count % 2) ? true : false;
78 }
79
80 /* Check whether point is inside any stroke of grease pencil layer. */
81 static bool check_point_in_layer(bGPDlayer *layer, float x, float y)
82 {
83         bGPDframe *frame = layer->frames.first;
84
85         while (frame) {
86                 bGPDstroke *stroke = frame->strokes.first;
87
88                 while (stroke) {
89                         if (check_point_in_stroke(stroke, x, y))
90                                 return true;
91
92                         stroke = stroke->next;
93                 }
94                 frame = frame->next;
95         }
96
97         return false;
98 }
99
100 /* Get features detected by libmv and create tracks on the clip for them. */
101 static void detect_retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase,
102                                            struct libmv_Features *features, int framenr, int width, int height,
103                                            bGPDlayer *layer, bool place_outside_layer)
104 {
105         int a;
106
107         a = libmv_countFeatures(features);
108         while (a--) {
109                 MovieTrackingTrack *track;
110                 double x, y, size, score;
111                 bool ok = true;
112                 float xu, yu;
113
114                 libmv_getFeature(features, a, &x, &y, &score, &size);
115
116                 xu = x / width;
117                 yu = y / height;
118
119                 if (layer)
120                         ok = check_point_in_layer(layer, xu, yu) != place_outside_layer;
121
122                 if (ok) {
123                         track = BKE_tracking_track_add(tracking, tracksbase, xu, yu, framenr, width, height);
124                         track->flag |= SELECT;
125                         track->pat_flag |= SELECT;
126                         track->search_flag |= SELECT;
127                 }
128         }
129 }
130
131 /* Get a gray-scale unsigned char buffer from given image buffer
132  * wich will be used for feature detection.
133  */
134 static unsigned char *detect_get_frame_ucharbuf(ImBuf *ibuf)
135 {
136         int x, y;
137         unsigned char *pixels, *cp;
138
139         cp = pixels = MEM_callocN(ibuf->x * ibuf->y * sizeof(unsigned char), "tracking ucharBuf");
140         for (y = 0; y < ibuf->y; y++) {
141                 for (x = 0; x < ibuf->x; x++) {
142                         int pixel = ibuf->x * y + x;
143
144                         if (ibuf->rect_float) {
145                                 const float *rrgbf = ibuf->rect_float + pixel * 4;
146                                 const float gray_f = 0.2126f * rrgbf[0] + 0.7152f * rrgbf[1] + 0.0722f * rrgbf[2];
147
148                                 *cp = FTOCHAR(gray_f);
149                         }
150                         else {
151                                 const unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
152
153                                 *cp = 0.2126f * rrgb[0] + 0.7152f * rrgb[1] + 0.0722f * rrgb[2];
154                         }
155
156                         cp++;
157                 }
158         }
159
160         return pixels;
161 }
162
163 /* Detect features using FAST detector */
164 void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf,
165                               int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer,
166                               bool place_outside_layer)
167 {
168         struct libmv_Features *features;
169         unsigned char *pixels = detect_get_frame_ucharbuf(ibuf);
170
171         features = libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x,
172                                             margin, min_trackness, min_distance);
173
174         MEM_freeN(pixels);
175
176         detect_retrieve_libmv_features(tracking, tracksbase, features,
177                                        framenr, ibuf->x, ibuf->y, layer,
178                                        place_outside_layer);
179
180         libmv_featuresDestroy(features);
181 }