Commit e2dfa357 authored by GilLevi's avatar GilLevi

added description of LATCH and fixed indentation

parent 292cee60
...@@ -152,6 +152,19 @@ public: ...@@ -152,6 +152,19 @@ public:
/** latch Class for computing the LATCH descriptor. /** latch Class for computing the LATCH descriptor.
If you find this code useful, please add a reference to the following paper in your work: If you find this code useful, please add a reference to the following paper in your work:
Gil Levi and Tal Hassner, "LATCH: Learned Arrangements of Three Patch Codes", arXiv preprint arXiv:1501.03719, 15 Jan. 2015 Gil Levi and Tal Hassner, "LATCH: Learned Arrangements of Three Patch Codes", arXiv preprint arXiv:1501.03719, 15 Jan. 2015
LATCH is a binary descriptor based on learned comparisons of triplets of image patches.
* bytes is the size of the descriptor - can be 64, 32, 16, 8, 4, 2 or 1
* rotationInvariance - whether or not the descriptor should compansate for orientation changes.
* half_ssd_size - the size of half of the mini-patches size. For example, if we would like to compare triplets of patches of size 7x7x
then the half_ssd_size should be (7-1)/2 = 3.
Note: the descriptor can be coupled with any keypoint extractor. The only demand is that if you use set rotationInvariance = True then
you will have to use an extractor which estimates the patch orientation (in degrees). Examples for such extractors are ORB and SIFT.
Note: a complete example can be found under /samples/cpp/tutorial_code/xfeatures2D/latch_match.cpp
*/ */
class CV_EXPORTS LATCHDescriptorExtractor : public DescriptorExtractor class CV_EXPORTS LATCHDescriptorExtractor : public DescriptorExtractor
{ {
......
...@@ -52,15 +52,15 @@ ...@@ -52,15 +52,15 @@
namespace cv namespace cv
{ {
namespace xfeatures2d namespace xfeatures2d
{ {
/* /*
* LATCH Descriptor * LATCH Descriptor
*/ */
class LATCHDescriptorExtractorImpl : public LATCHDescriptorExtractor class LATCHDescriptorExtractorImpl : public LATCHDescriptorExtractor
{ {
public: public:
enum { PATCH_SIZE = 48 }; enum { PATCH_SIZE = 48 };
LATCHDescriptorExtractorImpl(int bytes = 32, bool rotationInvariance = true, int half_ssd_size = 3); LATCHDescriptorExtractorImpl(int bytes = 32, bool rotationInvariance = true, int half_ssd_size = 3);
...@@ -74,7 +74,7 @@ public: ...@@ -74,7 +74,7 @@ public:
virtual void compute(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors); virtual void compute(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors);
protected: protected:
typedef void(*PixelTestFn)(const Mat& input_image, const std::vector<KeyPoint>& keypoints, OutputArray, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size); typedef void(*PixelTestFn)(const Mat& input_image, const std::vector<KeyPoint>& keypoints, OutputArray, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size);
int bytes_; int bytes_;
...@@ -84,17 +84,17 @@ protected: ...@@ -84,17 +84,17 @@ protected:
std::vector<int> sampling_points_ ; std::vector<int> sampling_points_ ;
}; };
Ptr<LATCHDescriptorExtractor> LATCHDescriptorExtractor::create(int bytes, bool rotationInvariance, int half_ssd_size) Ptr<LATCHDescriptorExtractor> LATCHDescriptorExtractor::create(int bytes, bool rotationInvariance, int half_ssd_size)
{ {
return makePtr<LATCHDescriptorExtractorImpl>(bytes, rotationInvariance, half_ssd_size); return makePtr<LATCHDescriptorExtractorImpl>(bytes, rotationInvariance, half_ssd_size);
} }
void CacluateSums(int count, const std::vector<int> &points, bool rotationInvariance, const Mat &grayImage, const KeyPoint &pt, int &suma, int &sumc, float cos_theta, float sin_theta, int half_ssd_size); void CalcuateSums(int count, const std::vector<int> &points, bool rotationInvariance, const Mat &grayImage, const KeyPoint &pt, int &suma, int &sumc, float cos_theta, float sin_theta, int half_ssd_size);
static void pixelTests1(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size) static void pixelTests1(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size)
{ {
Mat descriptors = _descriptors.getMat(); Mat descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i) for (int i = 0; i < (int)keypoints.size(); ++i)
{ {
...@@ -114,18 +114,18 @@ static void pixelTests1(const Mat& grayImage, const std::vector<KeyPoint>& keypo ...@@ -114,18 +114,18 @@ static void pixelTests1(const Mat& grayImage, const std::vector<KeyPoint>& keypo
int suma = 0; int suma = 0;
int sumc = 0; int sumc = 0;
CacluateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size); CalcuateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size);
desc[ix] += (uchar)((suma < sumc) << j); desc[ix] += (uchar)((suma < sumc) << j);
count += 6; count += 6;
} }
} }
} }
} }
static void pixelTests2(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size) static void pixelTests2(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size)
{ {
Mat descriptors = _descriptors.getMat(); Mat descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i) for (int i = 0; i < (int)keypoints.size(); ++i)
{ {
...@@ -145,18 +145,18 @@ static void pixelTests2(const Mat& grayImage, const std::vector<KeyPoint>& keypo ...@@ -145,18 +145,18 @@ static void pixelTests2(const Mat& grayImage, const std::vector<KeyPoint>& keypo
int suma = 0; int suma = 0;
int sumc = 0; int sumc = 0;
CacluateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size); CalcuateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size);
desc[ix] += (uchar)((suma < sumc) << j); desc[ix] += (uchar)((suma < sumc) << j);
count += 6; count += 6;
} }
} }
} }
} }
static void pixelTests4(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size) static void pixelTests4(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size)
{ {
Mat descriptors = _descriptors.getMat(); Mat descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i) for (int i = 0; i < (int)keypoints.size(); ++i)
{ {
...@@ -176,19 +176,19 @@ static void pixelTests4(const Mat& grayImage, const std::vector<KeyPoint>& keypo ...@@ -176,19 +176,19 @@ static void pixelTests4(const Mat& grayImage, const std::vector<KeyPoint>& keypo
int suma = 0; int suma = 0;
int sumc = 0; int sumc = 0;
CacluateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size); CalcuateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size);
desc[ix] += (uchar)((suma < sumc) << j); desc[ix] += (uchar)((suma < sumc) << j);
count += 6; count += 6;
} }
} }
} }
} }
static void pixelTests8(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size) static void pixelTests8(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size)
{ {
Mat descriptors = _descriptors.getMat(); Mat descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i) for (int i = 0; i < (int)keypoints.size(); ++i)
{ {
...@@ -208,18 +208,18 @@ static void pixelTests8(const Mat& grayImage, const std::vector<KeyPoint>& keypo ...@@ -208,18 +208,18 @@ static void pixelTests8(const Mat& grayImage, const std::vector<KeyPoint>& keypo
int suma = 0; int suma = 0;
int sumc = 0; int sumc = 0;
CacluateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size); CalcuateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size);
desc[ix] += (uchar)((suma < sumc) << j); desc[ix] += (uchar)((suma < sumc) << j);
count += 6; count += 6;
} }
} }
} }
} }
static void pixelTests16(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size) static void pixelTests16(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size)
{ {
Mat descriptors = _descriptors.getMat(); Mat descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i) for (int i = 0; i < (int)keypoints.size(); ++i)
{ {
...@@ -239,18 +239,18 @@ static void pixelTests16(const Mat& grayImage, const std::vector<KeyPoint>& keyp ...@@ -239,18 +239,18 @@ static void pixelTests16(const Mat& grayImage, const std::vector<KeyPoint>& keyp
int suma = 0; int suma = 0;
int sumc = 0; int sumc = 0;
CacluateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size); CalcuateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size);
desc[ix] += (uchar)((suma < sumc) << j); desc[ix] += (uchar)((suma < sumc) << j);
count += 6; count += 6;
} }
} }
} }
} }
static void pixelTests32(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size) static void pixelTests32(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size)
{ {
Mat descriptors = _descriptors.getMat(); Mat descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i) for (int i = 0; i < (int)keypoints.size(); ++i)
{ {
...@@ -269,18 +269,18 @@ static void pixelTests32(const Mat& grayImage, const std::vector<KeyPoint>& keyp ...@@ -269,18 +269,18 @@ static void pixelTests32(const Mat& grayImage, const std::vector<KeyPoint>& keyp
int suma = 0; int suma = 0;
int sumc = 0; int sumc = 0;
CacluateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size); CalcuateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size);
desc[ix] += (uchar)((suma < sumc) << j); desc[ix] += (uchar)((suma < sumc) << j);
count += 6; count += 6;
} }
} }
} }
} }
static void pixelTests64(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size) static void pixelTests64(const Mat& grayImage, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, const std::vector<int> &points, bool rotationInvariance, int half_ssd_size)
{ {
Mat descriptors = _descriptors.getMat(); Mat descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i) for (int i = 0; i < (int)keypoints.size(); ++i)
{ {
...@@ -300,18 +300,18 @@ static void pixelTests64(const Mat& grayImage, const std::vector<KeyPoint>& keyp ...@@ -300,18 +300,18 @@ static void pixelTests64(const Mat& grayImage, const std::vector<KeyPoint>& keyp
int suma = 0; int suma = 0;
int sumc = 0; int sumc = 0;
CacluateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size); CalcuateSums(count, points, rotationInvariance, grayImage, pt, suma, sumc, cos_theta, sin_theta, half_ssd_size);
desc[ix] += (uchar)((suma < sumc) << j); desc[ix] += (uchar)((suma < sumc) << j);
count += 6; count += 6;
} }
} }
} }
} }
void CacluateSums(int count, const std::vector<int> &points, bool rotationInvariance, const Mat &grayImage, const KeyPoint &pt, int &suma, int &sumc, float cos_theta, float sin_theta, int half_ssd_size) void CalcuateSums(int count, const std::vector<int> &points, bool rotationInvariance, const Mat &grayImage, const KeyPoint &pt, int &suma, int &sumc, float cos_theta, float sin_theta, int half_ssd_size)
{ {
int ax = points[count]; int ax = points[count];
int ay = points[count + 1]; int ay = points[count + 1];
...@@ -399,13 +399,13 @@ void CacluateSums(int count, const std::vector<int> &points, bool rotationInvari ...@@ -399,13 +399,13 @@ void CacluateSums(int count, const std::vector<int> &points, bool rotationInvari
} }
} }
} }
LATCHDescriptorExtractorImpl::LATCHDescriptorExtractorImpl(int bytes, bool rotationInvariance, int half_ssd_size) : LATCHDescriptorExtractorImpl::LATCHDescriptorExtractorImpl(int bytes, bool rotationInvariance, int half_ssd_size) :
bytes_(bytes), test_fn_(NULL), rotationInvariance_(rotationInvariance), half_ssd_size_(half_ssd_size) bytes_(bytes), test_fn_(NULL), rotationInvariance_(rotationInvariance), half_ssd_size_(half_ssd_size)
{ {
switch (bytes) switch (bytes)
{ {
case 1: case 1:
...@@ -946,25 +946,25 @@ bytes_(bytes), test_fn_(NULL), rotationInvariance_(rotationInvariance), half_ssd ...@@ -946,25 +946,25 @@ bytes_(bytes), test_fn_(NULL), rotationInvariance_(rotationInvariance), half_ssd
11, -12, 5, -21, -2, -13}; 11, -12, 5, -21, -2, -13};
sampling_points_.assign(&sampling_points_arr[0],&sampling_points_arr[0]+3072); sampling_points_.assign(&sampling_points_arr[0],&sampling_points_arr[0]+3072);
} }
int LATCHDescriptorExtractorImpl::descriptorSize() const int LATCHDescriptorExtractorImpl::descriptorSize() const
{ {
return bytes_; return bytes_;
} }
int LATCHDescriptorExtractorImpl::descriptorType() const int LATCHDescriptorExtractorImpl::descriptorType() const
{ {
return CV_8UC1; return CV_8UC1;
} }
int LATCHDescriptorExtractorImpl::defaultNorm() const int LATCHDescriptorExtractorImpl::defaultNorm() const
{ {
return NORM_HAMMING; return NORM_HAMMING;
} }
void LATCHDescriptorExtractorImpl::read(const FileNode& fn) void LATCHDescriptorExtractorImpl::read(const FileNode& fn)
{ {
int dSize = fn["descriptorSize"]; int dSize = fn["descriptorSize"];
switch (dSize) switch (dSize)
{ {
...@@ -993,17 +993,17 @@ void LATCHDescriptorExtractorImpl::read(const FileNode& fn) ...@@ -993,17 +993,17 @@ void LATCHDescriptorExtractorImpl::read(const FileNode& fn)
CV_Error(Error::StsBadArg, "descriptorSize must be 1,2, 4, 8, 16, 32, or 64"); CV_Error(Error::StsBadArg, "descriptorSize must be 1,2, 4, 8, 16, 32, or 64");
} }
bytes_ = dSize; bytes_ = dSize;
} }
void LATCHDescriptorExtractorImpl::write(FileStorage& fs) const void LATCHDescriptorExtractorImpl::write(FileStorage& fs) const
{ {
fs << "descriptorSize" << bytes_; fs << "descriptorSize" << bytes_;
} }
void LATCHDescriptorExtractorImpl::compute(InputArray image, void LATCHDescriptorExtractorImpl::compute(InputArray image,
std::vector<KeyPoint>& keypoints, std::vector<KeyPoint>& keypoints,
OutputArray descriptors) OutputArray descriptors)
{ {
Mat grayImage; Mat grayImage;
GaussianBlur(image, grayImage, cv::Size(3, 3), 2, 2); GaussianBlur(image, grayImage, cv::Size(3, 3), 2, 2);
...@@ -1019,8 +1019,8 @@ void LATCHDescriptorExtractorImpl::compute(InputArray image, ...@@ -1019,8 +1019,8 @@ void LATCHDescriptorExtractorImpl::compute(InputArray image,
descriptors.create((int)keypoints.size(), bytes_, CV_8U); descriptors.create((int)keypoints.size(), bytes_, CV_8U);
test_fn_(grayImage, keypoints, descriptors, sampling_points_, rotationInvariance_, half_ssd_size_); test_fn_(grayImage, keypoints, descriptors, sampling_points_, rotationInvariance_, half_ssd_size_);
} }
} }
} // namespace cv } // namespace cv
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment