Welcome to mirror list, hosted at ThFree Co, Russian Federation.

detect.patch « patches « libmv « extern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 36fea8427db314a855f0d73cc0c1cad38085044d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
diff --git a/src/libmv/simple_pipeline/detect.cc b/src/libmv/simple_pipeline/detect.cc
index 6fc0cdd..8ac42ab 100644
--- a/src/libmv/simple_pipeline/detect.cc
+++ b/src/libmv/simple_pipeline/detect.cc
@@ -23,15 +23,89 @@
 ****************************************************************************/
 
 #include "libmv/simple_pipeline/detect.h"
+#include <third_party/fast/fast.h>
 #include <stdlib.h>
-#include <string.h>
+#include <memory.h>
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
 
 namespace libmv {
 
 typedef unsigned int uint;
 
+int featurecmp(const void *a_v, const void *b_v)
+{
+  Feature *a = (Feature*)a_v;
+  Feature *b = (Feature*)b_v;
+
+  return b->score - a->score;
+}
+
+std::vector<Feature> DetectFAST(const unsigned char* data, int width, int height, int stride,
+                           int min_trackness, int min_distance) {
+  std::vector<Feature> features;
+  // TODO(MatthiasF): Support targetting a feature count (binary search trackness)
+  int num_features;
+  xy* all = fast9_detect(data, width, height,
+                         stride, min_trackness, &num_features);
+  if(num_features == 0) {
+    free(all);
+    return features;
+  }
+  int* scores = fast9_score(data, stride, all, num_features, min_trackness);
+  // TODO: merge with close feature suppression
+  xy* nonmax = nonmax_suppression(all, scores, num_features, &num_features);
+  free(all);
+  // Remove too close features
+  // TODO(MatthiasF): A resolution independent parameter would be better than distance
+  // e.g. a coefficient going from 0 (no minimal distance) to 1 (optimal circle packing)
+  // FIXME(MatthiasF): this method will not necessarily give all maximum markers
+  if(num_features) {
+    Feature *all_features = new Feature[num_features];
+
+    for(int i = 0; i < num_features; ++i) {
+      Feature a = { nonmax[i].x, nonmax[i].y, scores[i], 0 };
+      all_features[i] = a;
+    }
+
+    qsort((void *)all_features, num_features, sizeof(Feature), featurecmp);
+
+    features.reserve(num_features);
+
+    int prev_score = all_features[0].score;
+    for(int i = 0; i < num_features; ++i) {
+      bool ok = true;
+      Feature a = all_features[i];
+      if(a.score>prev_score)
+        abort();
+      prev_score = a.score;
+
+      // compare each feature against filtered set
+      for(int j = 0; j < features.size(); j++) {
+        Feature& b = features[j];
+        if ( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y) < min_distance*min_distance ) {
+          // already a nearby feature
+          ok = false;
+          break;
+        }
+      }
+
+      if(ok) {
+        // add the new feature
+        features.push_back(a);
+      }
+    }
+
+    delete [] all_features;
+  }
+  free(scores);
+  free(nonmax);
+  return features;
+}
+
 #ifdef __SSE2__
-#include <emmintrin.h>
 static uint SAD(const ubyte* imageA, const ubyte* imageB, int strideA, int strideB) {
   __m128i a = _mm_setzero_si128();
   for(int i = 0; i < 16; i++) {
@@ -52,7 +126,7 @@ static uint SAD(const ubyte* imageA, const ubyte* imageB, int strideA, int strid
 }
 #endif
 
-void Detect(ubyte* image, int stride, int width, int height, Feature* detected, int* count, int distance, ubyte* pattern) {
+void DetectMORAVEC(ubyte* image, int stride, int width, int height, Feature* detected, int* count, int distance, ubyte* pattern) {
   unsigned short histogram[256];
   memset(histogram,0,sizeof(histogram));
   ubyte* scores = new ubyte[width*height];
diff --git a/src/libmv/simple_pipeline/detect.h b/src/libmv/simple_pipeline/detect.h
index 23b239b..bbe7aed 100644
--- a/src/libmv/simple_pipeline/detect.h
+++ b/src/libmv/simple_pipeline/detect.h
@@ -25,27 +25,52 @@
 #ifndef LIBMV_SIMPLE_PIPELINE_DETECT_H_
 #define LIBMV_SIMPLE_PIPELINE_DETECT_H_
 
-#ifdef __cplusplus
+#include <vector>
+
 namespace libmv {
-#endif
 
 typedef unsigned char ubyte;
 
 /*!
-    \a Feature is the 2D location of a detected feature in an image.
+    A Feature is the 2D location of a detected feature in an image.
 
-    \a x, \a y is the position of the center in pixels (from image top-left).
-    \a score is an estimate of how well the pattern will be tracked.
-    \a size can be used as an initial size to track the pattern.
+    \a x, \a y is the position of the feature in pixels from the top left corner.
+    \a score is an estimate of how well the feature will be tracked.
+    \a size can be used as an initial pattern size to track the feature.
 
     \sa Detect
 */
 struct Feature {
+  /// Position in pixels (from top-left corner)
+  /// \note libmv might eventually support subpixel precision.
   float x, y;
+  /// Trackness of the feature
   float score;
+  /// Size of the feature in pixels
   float size;
 };
- //radius for non maximal suppression
+
+/*!
+    Detect features in an image.
+
+    You need to input a single channel 8-bit image using pointer to image \a data,
+    \a width, \a height and \a stride (i.e bytes per line).
+
+    You can tweak the count of detected features using \a min_trackness, which is
+    the minimum score to add a feature, and \a min_distance which is the minimal
+    distance accepted between two featuress.
+
+    \note You can binary search over \a min_trackness to get a given feature count.
+
+    \note a way to get an uniform distribution of a given feature count is:
+          \a min_distance = \a width * \a height / desired_feature_count ^ 2
+
+    \return All detected feartures matching given parameters
+*/
+std::vector<Feature> DetectFAST(const unsigned char* data, int width, int height,
+                           int stride, int min_trackness = 128,
+                           int min_distance = 120);
+
 /*!
     Detect features in an image.
 
@@ -63,10 +88,8 @@ struct Feature {
     \note \a You can crop the image (to avoid detecting markers near the borders) without copying:
              image += marginY*stride+marginX, width -= 2*marginX, height -= 2*marginY;
 */
-void Detect(ubyte* image, int stride, int width, int height, Feature* detected, int* count, int distance /*=32*/, ubyte* pattern /*=0*/);
+void DetectMORAVEC(ubyte* image, int stride, int width, int height, Feature* detected, int* count, int distance /*=32*/, ubyte* pattern /*=0*/);
 
-#ifdef __cplusplus
 }
-#endif
 
 #endif