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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/extern
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2011-08-17 21:12:10 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2011-08-17 21:12:10 +0400
commit18f5322f7c2145b772ab4d47a9d4cf890222b080 (patch)
tree9698aa1672a7799e540788ebce528caa57a1072a /extern
parent8b4c115a58869577457123b380ab279059b54a0e (diff)
Camera tracking integration
=========================== - Bundling new libmv, issues with undefined uint and C99 functions should gone. - Changes to Detect operator to match new API.
Diffstat (limited to 'extern')
-rw-r--r--extern/libmv/ChangeLog46
-rw-r--r--extern/libmv/libmv-capi.cpp51
-rw-r--r--extern/libmv/libmv-capi.h12
-rw-r--r--extern/libmv/libmv/numeric/function_derivative.h3
-rw-r--r--extern/libmv/libmv/numeric/levenberg_marquardt.h51
-rw-r--r--extern/libmv/libmv/simple_pipeline/detect.cc109
-rw-r--r--extern/libmv/libmv/simple_pipeline/detect.h49
-rw-r--r--extern/libmv/libmv/tracking/sad.cc19
-rw-r--r--extern/libmv/libmv/tracking/sad.h6
9 files changed, 216 insertions, 130 deletions
diff --git a/extern/libmv/ChangeLog b/extern/libmv/ChangeLog
index 5db3c420ea5..936ec9d5d8d 100644
--- a/extern/libmv/ChangeLog
+++ b/extern/libmv/ChangeLog
@@ -1,3 +1,49 @@
+commit d22720e618456329388d2c107422c3b371657cba
+Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
+Date: Wed Aug 17 14:14:45 2011 +0200
+
+ Improve Detect and SAD Tracker API and documentation.
+
+commit 5d6cd4ad365b061901bad40695b51d568487a0cf
+Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
+Date: Wed Aug 17 11:57:29 2011 +0200
+
+ MSVC support fixes.
+
+commit 50f0323173c6deebd6aaf9c126f0b51b2a79c3c1
+Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
+Date: Tue Aug 16 23:21:37 2011 +0200
+
+ Detector can detect features similar to a given pattern.
+
+commit 5734cc27bbf84c2b6edcfcc1ea736798e12d5820
+Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
+Date: Tue Aug 16 22:53:54 2011 +0200
+
+ Ensure SAD Tracker is C compatible.
+ Update Detect API documentation.
+
+commit 701c42842574064fea992f8822e3899cb9066108
+Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
+Date: Tue Aug 16 21:56:42 2011 +0200
+
+ Remove FAST detector.
+ Add Moravec detector.
+ This detector is more suited to tracking since it try to choose patterns which are unlikely to drift by computing SAD with neighbouring patches.
+ It could be improved to better avoid edges.
+
+commit 9bdf93e13fc880c78b6f34397da673388c16040e
+Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
+Date: Tue Aug 16 21:55:08 2011 +0200
+
+ Fix Qt Tracker GL to work with AMD drivers.
+
+commit 81613ee0cc94b315f333c9632b18b95d426aad05
+Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
+Date: Tue Aug 16 21:54:12 2011 +0200
+
+ Make CameraIntrinsics (and thus Qt tracker) compilable without linking libmv.
+
commit a1d9a8fa8b01ef7cf2a79b3b891633fc333fc9cf
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Tue Aug 16 21:24:51 2011 +0200
diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp
index 70985f545b9..c3a0d717d12 100644
--- a/extern/libmv/libmv-capi.cpp
+++ b/extern/libmv/libmv-capi.cpp
@@ -77,6 +77,11 @@ typedef struct libmv_Reconstruction {
double error;
} libmv_Reconstruction;
+typedef struct libmv_Features {
+ int count, margin;
+ libmv::Feature *features;
+} libmv_Features;
+
/* ************ Logging ************ */
void libmv_initLogging(const char *argv0)
@@ -324,12 +329,12 @@ int libmv_SADTrackerTrack(unsigned char *pattern, unsigned char *image, int stri
{
float x2, y2;
- int result = libmv::Track(pattern, image, stride, width, height, &x2, &y2);
+ libmv::Track(pattern, image, stride, width, height, &x2, &y2);
*x= x2;
*y= y2;
- return result;
+ return 1;
}
/* ************ Tracks ************ */
@@ -495,37 +500,45 @@ void libmv_destroyReconstruction(libmv_Reconstruction *libmv_reconstruction)
/* ************ feature detector ************ */
-struct libmv_Corners *libmv_detectCorners(unsigned char *data, int width, int height, int stride,
- int margin, int min_trackness, int min_distance)
+struct libmv_Features *libmv_detectFeatures(unsigned char *data, int width, int height, int stride,
+ int margin, int count, int min_distance)
{
- std::vector<libmv::Corner> detect;
- std::vector<libmv::Corner> *libmv_corners= new std::vector<libmv::Corner>();
+ libmv::Feature *features = new libmv::Feature[count];
+ libmv_Features *libmv_features = new libmv_Features;
+
+ if(margin) {
+ data += margin*stride+margin;
+ width -= 2*margin;
+ height -= 2*margin;
+ }
- detect= libmv::Detect(data, width, height, stride, margin, min_trackness, min_distance);
+ libmv::Detect(data, stride, width, height, features, &count, min_distance, NULL);
- libmv_corners->insert(libmv_corners->begin(), detect.begin(), detect.end());
+ libmv_features->count= count;
+ libmv_features->margin= margin;
+ libmv_features->features= features;
- return (libmv_Corners *)libmv_corners;
+ return libmv_features ;
}
-int libmv_countCorners(struct libmv_Corners *libmv_corners)
+int libmv_countFeatures(struct libmv_Features *libmv_features)
{
- return ((std::vector<libmv::Corner> *)libmv_corners)->size();
+ return libmv_features->count;
}
-void libmv_getCorner(struct libmv_Corners *libmv_corners, int number, double *x, double *y, double *score, double *size)
+void libmv_getFeature(struct libmv_Features *libmv_features, int number, double *x, double *y, double *score, double *size)
{
- libmv::Corner corner = ((std::vector<libmv::Corner> *)libmv_corners)->at(number);
+ libmv::Feature feature = libmv_features->features[number];
- *x = corner.x;
- *y = corner.y;
- *score = corner.score;
- *size = corner.size;
+ *x = feature.x + libmv_features->margin;
+ *y = feature.y + libmv_features->margin;
+ *score = feature.score;
+ *size = feature.size;
}
-void libmv_destroyCorners(struct libmv_Corners *libmv_corners)
+void libmv_destroyFeatures(struct libmv_Features *libmv_features)
{
- delete (std::vector<libmv::Corner> *)libmv_corners;
+ delete (libmv::Feature *)libmv_features;
}
/* ************ distortion ************ */
diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h
index 0a7dd0beadf..d50632f3d4f 100644
--- a/extern/libmv/libmv-capi.h
+++ b/extern/libmv/libmv-capi.h
@@ -36,7 +36,7 @@ extern "C" {
struct libmv_RegionTracker;
struct libmv_Tracks;
struct libmv_Reconstruction;
-struct libmv_Corners;
+struct libmv_Features;
/* Logging */
void libmv_initLogging(const char *argv0);
@@ -71,11 +71,11 @@ double libmv_reprojectionError(struct libmv_Reconstruction *libmv_reconstruction
void libmv_destroyReconstruction(struct libmv_Reconstruction *libmv_reconstruction);
/* feature detector */
-struct libmv_Corners *libmv_detectCorners(unsigned char *data, int width, int height, int stride,
- int margin, int min_trackness, int min_distance);
-int libmv_countCorners(struct libmv_Corners *libmv_corners);
-void libmv_getCorner(struct libmv_Corners *libmv_corners, int number, double *x, double *y, double *score, double *size);
-void libmv_destroyCorners(struct libmv_Corners *libmv_corners);
+struct libmv_Features *libmv_detectFeatures(unsigned char *data, int width, int height, int stride,
+ int margin, int count, int min_distance);
+int libmv_countFeatures(struct libmv_Features *libmv_features);
+void libmv_getFeature(struct libmv_Features *libmv_features, int number, double *x, double *y, double *score, double *size);
+void libmv_destroyFeatures(struct libmv_Features *libmv_features);
/* dsitortion */
void libmv_undistortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
diff --git a/extern/libmv/libmv/numeric/function_derivative.h b/extern/libmv/libmv/numeric/function_derivative.h
index d7bc437b2e0..0075d23ac56 100644
--- a/extern/libmv/libmv/numeric/function_derivative.h
+++ b/extern/libmv/libmv/numeric/function_derivative.h
@@ -24,7 +24,6 @@
#include <cmath>
#include "libmv/numeric/numeric.h"
-#include "libmv/logging/logging.h"
namespace libmv {
@@ -98,7 +97,7 @@ bool CheckJacobian(const Function &f, const typename Function::XMatrixType &x) {
typename NumericJacobian<Function>::JMatrixType J_numeric = j_numeric(x);
typename NumericJacobian<Function>::JMatrixType J_analytic = j_analytic(x);
- LG << J_numeric - J_analytic;
+ //LG << J_numeric - J_analytic;
return true;
}
diff --git a/extern/libmv/libmv/numeric/levenberg_marquardt.h b/extern/libmv/libmv/numeric/levenberg_marquardt.h
index 4473b72f156..6a54f660d31 100644
--- a/extern/libmv/libmv/numeric/levenberg_marquardt.h
+++ b/extern/libmv/libmv/numeric/levenberg_marquardt.h
@@ -33,7 +33,6 @@
#include "libmv/numeric/numeric.h"
#include "libmv/numeric/function_derivative.h"
-#include "libmv/logging/logging.h"
namespace libmv {
@@ -124,40 +123,26 @@ class LevenbergMarquardt {
Parameters dx, x_new;
int i;
for (i = 0; results.status == RUNNING && i < params.max_iterations; ++i) {
- VLOG(1) << "iteration: " << i;
- VLOG(1) << "||f(x)||: " << f_(x).norm();
- VLOG(1) << "max(g): " << g.array().abs().maxCoeff();
- VLOG(1) << "u: " << u;
- VLOG(1) << "v: " << v;
-
- AMatrixType A_augmented = A + u*AMatrixType::Identity(J.cols(), J.cols());
- Solver solver(A_augmented);
- dx = solver.solve(g);
- bool solved = (A_augmented * dx).isApprox(g);
- if (!solved) {
- LOG(ERROR) << "Failed to solve";
- }
- if (solved && dx.norm() <= params.relative_step_threshold * x.norm()) {
+ if (dx.norm() <= params.relative_step_threshold * x.norm()) {
results.status = RELATIVE_STEP_SIZE_TOO_SMALL;
break;
- }
- if (solved) {
- x_new = x + dx;
- // Rho is the ratio of the actual reduction in error to the reduction
- // in error that would be obtained if the problem was linear.
- // See [1] for details.
- Scalar rho((error.squaredNorm() - f_(x_new).squaredNorm())
- / dx.dot(u*dx + g));
- if (rho > 0) {
- // Accept the Gauss-Newton step because the linear model fits well.
- x = x_new;
- results.status = Update(x, params, &J, &A, &error, &g);
- Scalar tmp = Scalar(2*rho-1);
- u = u*std::max(1/3., 1 - (tmp*tmp*tmp));
- v = 2;
- continue;
- }
- }
+ }
+ x_new = x + dx;
+ // Rho is the ratio of the actual reduction in error to the reduction
+ // in error that would be obtained if the problem was linear.
+ // See [1] for details.
+ Scalar rho((error.squaredNorm() - f_(x_new).squaredNorm())
+ / dx.dot(u*dx + g));
+ if (rho > 0) {
+ // Accept the Gauss-Newton step because the linear model fits well.
+ x = x_new;
+ results.status = Update(x, params, &J, &A, &error, &g);
+ Scalar tmp = Scalar(2*rho-1);
+ u = u*std::max(1/3., 1 - (tmp*tmp*tmp));
+ v = 2;
+ continue;
+ }
+
// Reject the update because either the normal equations failed to solve
// or the local linear model was not good (rho < 0). Instead, increase u
// to move closer to gradient descent.
diff --git a/extern/libmv/libmv/simple_pipeline/detect.cc b/extern/libmv/libmv/simple_pipeline/detect.cc
index c3f54fffa18..28cd01fa73f 100644
--- a/extern/libmv/libmv/simple_pipeline/detect.cc
+++ b/extern/libmv/libmv/simple_pipeline/detect.cc
@@ -23,49 +23,84 @@
****************************************************************************/
#include "libmv/simple_pipeline/detect.h"
-#include <third_party/fast/fast.h>
-#include <stdlib.h>
+#include <string.h>
namespace libmv {
-std::vector<Corner> Detect(const unsigned char* data, int width, int height, int stride,
- int margin, int min_trackness, int min_distance) {
- std::vector<Corner> corners;
- data += margin*width + margin;
- // TODO(MatthiasF): Support targetting a feature count (binary search trackness)
- int num_corners;
- xy* all = fast9_detect(data, width-2*margin, height-2*margin,
- stride, min_trackness, &num_corners);
- if(num_corners == 0) {
- free(all);
- return corners;
+#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++) {
+ a = _mm_adds_epu16(a, _mm_sad_epu8( _mm_loadu_si128((__m128i*)(imageA+i*strideA)),
+ _mm_loadu_si128((__m128i*)(imageB+i*strideB))));
}
- int* scores = fast9_score(data, stride, all, num_corners, min_trackness);
- // TODO: merge with close feature suppression
- xy* nonmax = nonmax_suppression(all, scores, num_corners, &num_corners);
- 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_corners) corners.reserve(num_corners);
- for(int i = 0; i < num_corners; ++i) {
- xy xy = nonmax[i];
- Corner a = { xy.x+margin, xy.y+margin, scores[i], 7 };
- // compare each feature against filtered set
- for(int j = 0; j < corners.size(); j++) {
- Corner& b = corners[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
- goto skip;
+ return _mm_extract_epi16(a,0) + _mm_extract_epi16(a,4);
+}
+#else
+static uint SAD(const ubyte* imageA, const ubyte* imageB, int strideA, int strideB) {
+ uint sad=0;
+ for(int i = 0; i < 16; i++) {
+ for(int j = 0; j < 16; j++) {
+ sad += abs((int)imageA[i*strideA+j] - imageB[i*strideB+j]);
+ }
+ }
+ return sad;
+}
+#endif
+
+void Detect(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[width*height];
+ memset(scores,0,sizeof(scores));
+ const int r = 1; //radius for self similarity comparison
+ for(int y=distance; y<height-distance; y++) {
+ for(int x=distance; x<width-distance; x++) {
+ ubyte* s = &image[y*stride+x];
+ int score = // low self-similarity with overlapping patterns //OPTI: load pattern once
+ SAD(s, s-r*stride-r, stride, stride)+SAD(s, s-r*stride, stride, stride)+SAD(s, s-r*stride+r, stride, stride)+
+ SAD(s, s -r, stride, stride)+ SAD(s, s +r, stride, stride)+
+ SAD(s, s+r*stride-r, stride, stride)+SAD(s, s+r*stride, stride, stride)+SAD(s, s+r*stride+r, stride, stride);
+ score /= 256; // normalize
+ if(pattern) score -= SAD(s, pattern, stride, 16); // find only features similar to pattern
+ if(score<=16) continue; // filter very self-similar features
+ score -= 16; // translate to score/histogram values
+ if(score>255) score=255; // clip
+ ubyte* c = &scores[y*width+x];
+ for(int i=-distance; i<0; i++) {
+ for(int j=-distance; j<distance; j++) {
+ int s = c[i*width+j];
+ if(s == 0) continue;
+ if(s >= score) goto nonmax;
+ c[i*width+j]=0, histogram[s]--;
+ }
}
+ for(int i=0, j=-distance; j<0; j++) {
+ int s = c[i*width+j];
+ if(s == 0) continue;
+ if(s >= score) goto nonmax;
+ c[i*width+j]=0, histogram[s]--;
+ }
+ c[0] = score, histogram[score]++;
+ nonmax:;
}
- // otherwise add the new feature
- corners.push_back(a);
- skip: ;
}
- free(scores);
- free(nonmax);
- return corners;
+ int min=255, total=0;
+ for(; min>0; min--) {
+ int h = histogram[min];
+ if(total+h > *count) break;
+ total += h;
+ }
+ int i=0;
+ for(int y=16; y<height-16; y++) {
+ for(int x=16; x<width-16; x++) {
+ int s = scores[y*width+x];
+ Feature f = { x+8, y+8, s, 16 };
+ if(s>min) detected[i++] = f;
+ }
+ }
+ *count = i;
}
+
}
diff --git a/extern/libmv/libmv/simple_pipeline/detect.h b/extern/libmv/libmv/simple_pipeline/detect.h
index 5e947fe8f5b..23b239b81d6 100644
--- a/extern/libmv/libmv/simple_pipeline/detect.h
+++ b/extern/libmv/libmv/simple_pipeline/detect.h
@@ -25,53 +25,48 @@
#ifndef LIBMV_SIMPLE_PIPELINE_DETECT_H_
#define LIBMV_SIMPLE_PIPELINE_DETECT_H_
-#include <vector>
-
+#ifdef __cplusplus
namespace libmv {
+#endif
+
+typedef unsigned char ubyte;
/*!
- A Corner 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 corner 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.
+ \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.
\sa Detect
*/
-struct Corner {
- /// Position in pixels (from top-left corner)
- /// \note libmv might eventually support subpixel precision.
+struct Feature {
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).
-
- To avoid detecting tracks which will quickly go out of frame, only corners
- further than \a margin pixels from the image edges are considered.
+ \a image is a single channel 8-bit image of size \a width x \a height
- You can tweak the count of detected corners using \a min_trackness, which is
- the minimum score to add a corner, and \a min_distance which is the minimal
- distance accepted between two corners.
+ \a detected is an array with space to hold \a *count features.
+ \a *count is the maximum count to detect on input and the actual
+ detected count on output.
- \note You can binary search over \a min_trackness to get a given corner count.
+ \a distance is the minimal distance between detected features.
- \note a way to get an uniform distribution of a given corner count is:
- \a min_distance = \a width * \a height / desired_corner_count ^ 2
+ if \a pattern is null all good features will be found.
+ if \a pattern is not null only features similar to \a pattern will be found.
- \return All detected corners matching given parameters
+ \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;
*/
-std::vector<Corner> Detect(const unsigned char* data, int width, int height,
- int stride, int margin = 16, int min_trackness = 16,
- int min_distance = 120);
+void Detect(ubyte* image, int stride, int width, int height, Feature* detected, int* count, int distance /*=32*/, ubyte* pattern /*=0*/);
+#ifdef __cplusplus
}
+#endif
#endif
diff --git a/extern/libmv/libmv/tracking/sad.cc b/extern/libmv/libmv/tracking/sad.cc
index 0bcf3cbec3f..4f17bc9e39c 100644
--- a/extern/libmv/libmv/tracking/sad.cc
+++ b/extern/libmv/libmv/tracking/sad.cc
@@ -28,6 +28,8 @@
namespace libmv {
+typedef unsigned int uint;
+
struct vec2 {
float x,y;
inline vec2(float x, float y):x(x),y(y){}
@@ -44,11 +46,20 @@ template <int k> inline int sample(const ubyte* image,int stride, int x, int y,
+ (s[stride] * (k-u) + s[stride+1] * u) * ( v) ) / (k*k);
}
-void SamplePattern(const ubyte* image, int stride, mat3 warp, ubyte* pattern) {
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+void SamplePattern(ubyte* image, int stride, mat3 warp, ubyte* pattern) {
const int k = 256;
for (int i = 0; i < 16; i++) for (int j = 0; j < 16; j++) {
vec2 p = warp*vec2(j-8,i-8);
+#ifdef __SSE__
+ //MSVC apparently doesn't support any float rounding.
+ int fx = _mm_cvtss_si32(_mm_set_ss(p.x*k));
+ int fy = _mm_cvtss_si32(_mm_set_ss(p.y*k));
+#else
int fx = lround(p.x*k), fy = lround(p.y*k);
+#endif
int ix = fx/k, iy = fy/k;
int u = fx%k, v = fy%k;
pattern[i*16+j] = sample<k>(image,stride,ix,iy,u,v);
@@ -78,14 +89,14 @@ static uint SAD(const ubyte* pattern, const ubyte* image, int stride) {
#endif
//float sq( float x ) { return x*x; }
-bool Track(const ubyte* pattern, const ubyte* image, int stride, int w, int h, float* px, float* py) {
+int Track(ubyte* pattern, ubyte* image, int stride, int w, int h, float* px, float* py) {
int ix = *px-8, iy = *py-8;
uint min=-1;
// integer pixel
for(int y = 0; y < h-16; y++) {
for(int x = 0; x < w-16; x++) {
uint d = SAD(pattern,&image[y*stride+x],stride); //image L1 distance
- //d += sq(x-w/2-8)+sq(y-h/2-8); //spatial L2 distance
+ //d += sq(x-w/2-8)+sq(y-h/2-8); //spatial L2 distance (need feature prediction first)
if(d < min) {
min = d;
ix = x, iy = y;
@@ -123,7 +134,7 @@ bool Track(const ubyte* pattern, const ubyte* image, int stride, int w, int h, f
*px = float((ix*kScale)+fx)/kScale+8;
*py = float((iy*kScale)+fy)/kScale+8;
- return true;
+ return min;
}
} // namespace libmv
diff --git a/extern/libmv/libmv/tracking/sad.h b/extern/libmv/libmv/tracking/sad.h
index 4b82d6cb646..92307c9580f 100644
--- a/extern/libmv/libmv/tracking/sad.h
+++ b/extern/libmv/libmv/tracking/sad.h
@@ -40,7 +40,7 @@ typedef float mat3[9];
\note \a warp might be used by higher level tracking methods (e.g planar)
*/
-void SamplePattern(const ubyte* image, int stride, mat3 warp, ubyte* pattern);
+void SamplePattern(ubyte* image, int stride, mat3 warp, ubyte* pattern);
/*!
Track \a pattern in \a image.
@@ -59,8 +59,10 @@ void SamplePattern(const ubyte* image, int stride, mat3 warp, ubyte* pattern);
\note For a 16x speedup, compile this tracker with SSE2 support.
\note \a stride allow you to reference your search region instead of copying.
+
+ \return Sum of absolute difference between reference and matched pattern.
*/
-bool Track(const ubyte* pattern, const ubyte* image, int stride, int width, int height, float* x, float* y);
+int Track(ubyte* pattern, ubyte* image, int stride, int width, int height, float* x, float* y);
#ifdef __cplusplus
} // namespace libmv