```// Copyright (C) 2009  Davis E. King (davis@dlib.net)
#undef DLIB_SURf_ABSTRACT_H_
#ifdef DLIB_SURf_ABSTRACT_H_

#include "hessian_pyramid_abstract.h"
#include "../geometry/vector_abstract.h"
#include "../matrix/matrix_abstract.h"
#include "../image_processing/generic_image.h"

namespace dlib
{
/*
The functions in this file implement the components of the SURF algorithm
for extracting scale invariant feature descriptors from images.

For the full story on what this algorithm does and how it works
you should refer to the following papers.

This is the original paper which introduced the algorithm:
SURF: Speeded Up Robust Features
By Herbert Bay, Tinne Tuytelaars, and Luc Van Gool

This paper provides a nice detailed overview of how the algorithm works:
Notes on the OpenSURF Library by Christopher Evans
*/

// ----------------------------------------------------------------------------------------

double gaussian (
double x,
double y,
double sig
);
/*!
requires
- sig > 0
ensures
- computes and returns the value of a 2D Gaussian function with mean 0
and standard deviation sig at the given (x,y) point.
!*/

// ----------------------------------------------------------------------------------------

template <typename integral_image_type, typename T>
double compute_dominant_angle (
const integral_image_type& img,
const dlib::vector<T,2>& center,
const double& scale
);
/*!
requires
- integral_image_type == an object such as dlib::integral_image or another
type that implements the interface defined in image_transforms/integral_image_abstract.h
- scale > 0
- get_rect(img).contains(centered_rect(center, 17*scale, 17*scale)) == true
(i.e. center can't be within 17*scale pixels of the edge of the image)
ensures
- computes and returns the dominant angle (i.e. the angle of the dominant gradient)
at the given center point and scale in img.
- The returned angle is in radians.  Specifically, if the angle is described by
a vector vect then the angle is exactly the value of std::atan2(vect.y(), vect.x())
!*/

// ----------------------------------------------------------------------------------------

template <typename integral_image_type, typename T, typename MM, typename L>
void compute_surf_descriptor (
const integral_image_type& img,
const dlib::vector<T,2>& center,
const double scale,
const double angle,
matrix<double,64,1,MM,L>& des
)
/*!
requires
- integral_image_type == an object such as dlib::integral_image or another
type that implements the interface defined in image_transforms/integral_image_abstract.h
- scale > 0
- get_rect(img).contains(centered_rect(center, 32*scale, 32*scale)) == true
(i.e. center can't be within 32*scale pixels of the edge of the image)
ensures
- computes the 64 dimensional SURF descriptor vector of a box centered
at the given center point, tilted at an angle determined by the given
angle, and sized according to the given scale.
- #des == the computed SURF descriptor vector extracted from the img object.
- The angle is measured in radians and measures the degree of counter-clockwise
rotation around the center point.  This is the same kind of rotation as is
performed by the dlib::rotate_point() function.
!*/

// ----------------------------------------------------------------------------------------

struct surf_point
{
/*!
WHAT THIS OBJECT REPRESENTS
This object represents a detected SURF point.  The meanings of
its fields are defined below in the get_surf_points() function.
!*/

interest_point p;
matrix<double,64,1> des;
double angle;
};

// ----------------------------------------------------------------------------------------

void serialize (
const surf_point& item,
std::ostream& out
);
/*!
provides serialization support
!*/

void deserialize (
surf_point& item,
std::istream& in
);
/*!
provides serialization support
!*/

// ----------------------------------------------------------------------------------------

template <typename image_type>
const std::vector<surf_point> get_surf_points (
const image_type& img,
long max_points = 10000,
double detection_threshold = 30.0
);
/*!
requires
- max_points > 0
- detection_threshold >= 0
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- Let P denote the type of pixel in img, then we require:
- pixel_traits<P>::has_alpha == false
ensures
- This function runs the complete SURF algorithm on the given input image and
returns the points it found.
- returns a vector V such that:
- V.size() <= max_points
- for all valid i:
- V[i] == a SURF point found in the given input image img
- V[i].p == the interest_point extracted from the hessian pyramid for this
SURF point.
- V[i].des == the SURF descriptor for this point (calculated using
compute_surf_descriptor())
- V[i].angle == the angle of the SURF box at this point (calculated using
compute_dominant_angle())
- V[i].p.score >= detection_threshold
!*/

// ----------------------------------------------------------------------------------------

}

#endif // DLIB_SURf_ABSTRACT_H_

```