|
|
|
@@ -500,10 +500,10 @@ void KAZEFeatures::Do_Subpixel_Refinement(std::vector<cv::KeyPoint> &kpts) {
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
class MSURF_Descriptor_Invoker : public cv::ParallelLoopBody
|
|
|
|
|
class KAZE_Descriptor_Invoker : public cv::ParallelLoopBody
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
MSURF_Descriptor_Invoker(std::vector<cv::KeyPoint> &kpts, cv::Mat &desc, std::vector<TEvolution>& evolution, const KAZEOptions& _options)
|
|
|
|
|
KAZE_Descriptor_Invoker(std::vector<cv::KeyPoint> &kpts, cv::Mat &desc, std::vector<TEvolution>& evolution, const KAZEOptions& _options)
|
|
|
|
|
: _kpts(&kpts)
|
|
|
|
|
, _desc(&desc)
|
|
|
|
|
, _evolution(&evolution)
|
|
|
|
@@ -511,7 +511,7 @@ public:
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ~MSURF_Descriptor_Invoker()
|
|
|
|
|
virtual ~KAZE_Descriptor_Invoker()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -528,82 +528,26 @@ public:
|
|
|
|
|
{
|
|
|
|
|
kpts[i].angle = 0.0;
|
|
|
|
|
if (options.extended)
|
|
|
|
|
Get_MSURF_Upright_Descriptor_128(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
Get_KAZE_Upright_Descriptor_128(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
else
|
|
|
|
|
Get_MSURF_Upright_Descriptor_64(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
Get_KAZE_Upright_Descriptor_64(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
KAZEFeatures::Compute_Main_Orientation(kpts[i], evolution, options);
|
|
|
|
|
|
|
|
|
|
if (options.extended)
|
|
|
|
|
Get_MSURF_Descriptor_128(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
Get_KAZE_Descriptor_128(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
else
|
|
|
|
|
Get_MSURF_Descriptor_64(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
Get_KAZE_Descriptor_64(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
void Get_MSURF_Upright_Descriptor_64(const cv::KeyPoint& kpt, float* desc) const;
|
|
|
|
|
void Get_MSURF_Descriptor_64(const cv::KeyPoint& kpt, float* desc) const;
|
|
|
|
|
void Get_MSURF_Upright_Descriptor_128(const cv::KeyPoint& kpt, float* desc) const;
|
|
|
|
|
void Get_MSURF_Descriptor_128(const cv::KeyPoint& kpt, float *desc) const;
|
|
|
|
|
|
|
|
|
|
std::vector<cv::KeyPoint> * _kpts;
|
|
|
|
|
cv::Mat * _desc;
|
|
|
|
|
std::vector<TEvolution> * _evolution;
|
|
|
|
|
KAZEOptions options;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class GSURF_Descriptor_Invoker : public cv::ParallelLoopBody
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
GSURF_Descriptor_Invoker(std::vector<cv::KeyPoint> &kpts, cv::Mat &desc, std::vector<TEvolution>& evolution, const KAZEOptions& _options)
|
|
|
|
|
: _kpts(&kpts)
|
|
|
|
|
, _desc(&desc)
|
|
|
|
|
, _evolution(&evolution)
|
|
|
|
|
, options(_options)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ~GSURF_Descriptor_Invoker()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void operator() (const cv::Range& range) const
|
|
|
|
|
{
|
|
|
|
|
std::vector<cv::KeyPoint> &kpts = *_kpts;
|
|
|
|
|
cv::Mat &desc = *_desc;
|
|
|
|
|
std::vector<TEvolution> &evolution = *_evolution;
|
|
|
|
|
|
|
|
|
|
for (int i = range.start; i < range.end; i++)
|
|
|
|
|
{
|
|
|
|
|
kpts[i].angle = 0.0;
|
|
|
|
|
if (options.upright)
|
|
|
|
|
{
|
|
|
|
|
kpts[i].angle = 0.0;
|
|
|
|
|
if (options.extended)
|
|
|
|
|
Get_GSURF_Upright_Descriptor_128(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
else
|
|
|
|
|
Get_GSURF_Upright_Descriptor_64(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
KAZEFeatures::Compute_Main_Orientation(kpts[i], evolution, options);
|
|
|
|
|
|
|
|
|
|
if (options.extended)
|
|
|
|
|
Get_GSURF_Descriptor_128(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
else
|
|
|
|
|
Get_GSURF_Descriptor_64(kpts[i], desc.ptr<float>((int)i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void Get_GSURF_Upright_Descriptor_64(const cv::KeyPoint& kpt, float* desc) const;
|
|
|
|
|
void Get_GSURF_Descriptor_64(const cv::KeyPoint& kpt, float *desc) const;
|
|
|
|
|
void Get_GSURF_Upright_Descriptor_128(const cv::KeyPoint& kpt, float* desc) const;
|
|
|
|
|
void Get_GSURF_Descriptor_128(const cv::KeyPoint& kpt, float* desc) const;
|
|
|
|
|
void Get_KAZE_Upright_Descriptor_64(const cv::KeyPoint& kpt, float* desc) const;
|
|
|
|
|
void Get_KAZE_Descriptor_64(const cv::KeyPoint& kpt, float* desc) const;
|
|
|
|
|
void Get_KAZE_Upright_Descriptor_128(const cv::KeyPoint& kpt, float* desc) const;
|
|
|
|
|
void Get_KAZE_Descriptor_128(const cv::KeyPoint& kpt, float *desc) const;
|
|
|
|
|
|
|
|
|
|
std::vector<cv::KeyPoint> * _kpts;
|
|
|
|
|
cv::Mat * _desc;
|
|
|
|
@@ -626,16 +570,7 @@ void KAZEFeatures::Feature_Description(std::vector<cv::KeyPoint> &kpts, cv::Mat
|
|
|
|
|
desc = Mat::zeros((int)kpts.size(), 64, CV_32FC1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (options.descriptor)
|
|
|
|
|
{
|
|
|
|
|
case cv::KAZE::DESCRIPTOR_MSURF:
|
|
|
|
|
cv::parallel_for_(cv::Range(0, (int)kpts.size()), MSURF_Descriptor_Invoker(kpts, desc, evolution_, options));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case cv::KAZE::DESCRIPTOR_GSURF:
|
|
|
|
|
cv::parallel_for_(cv::Range(0, (int)kpts.size()), GSURF_Descriptor_Invoker(kpts, desc, evolution_, options));
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
cv::parallel_for_(cv::Range(0, (int)kpts.size()), KAZE_Descriptor_Invoker(kpts, desc, evolution_, options));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
@@ -728,7 +663,7 @@ void KAZEFeatures::Compute_Main_Orientation(cv::KeyPoint &kpt, const std::vector
|
|
|
|
|
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
|
|
|
|
* ECCV 2008
|
|
|
|
|
*/
|
|
|
|
|
void MSURF_Descriptor_Invoker::Get_MSURF_Upright_Descriptor_64(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
void KAZE_Descriptor_Invoker::Get_KAZE_Upright_Descriptor_64(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
{
|
|
|
|
|
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0, gauss_s1 = 0.0, gauss_s2 = 0.0;
|
|
|
|
|
float rx = 0.0, ry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
|
|
|
@@ -862,7 +797,7 @@ void MSURF_Descriptor_Invoker::Get_MSURF_Upright_Descriptor_64(const cv::KeyPoin
|
|
|
|
|
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
|
|
|
|
* ECCV 2008
|
|
|
|
|
*/
|
|
|
|
|
void MSURF_Descriptor_Invoker::Get_MSURF_Descriptor_64(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
void KAZE_Descriptor_Invoker::Get_KAZE_Descriptor_64(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
{
|
|
|
|
|
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0, gauss_s1 = 0.0, gauss_s2 = 0.0;
|
|
|
|
|
float rx = 0.0, ry = 0.0, rrx = 0.0, rry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
|
|
|
@@ -988,284 +923,6 @@ void MSURF_Descriptor_Invoker::Get_MSURF_Descriptor_64(const cv::KeyPoint &kpt,
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief This method computes the upright G-SURF descriptor of the provided keypoint
|
|
|
|
|
* given the main orientation
|
|
|
|
|
* @param kpt Input keypoint
|
|
|
|
|
* @param desc Descriptor vector
|
|
|
|
|
* @note Rectangular grid of 20 s x 20 s. Descriptor Length 64. No additional
|
|
|
|
|
* G-SURF descriptor as described in Pablo F. Alcantarilla, Luis M. Bergasa and
|
|
|
|
|
* Andrew J. Davison, Gauge-SURF Descriptors, Image and Vision Computing 31(1), 2013
|
|
|
|
|
*/
|
|
|
|
|
void GSURF_Descriptor_Invoker::Get_GSURF_Upright_Descriptor_64(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
{
|
|
|
|
|
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0;
|
|
|
|
|
float rx = 0.0, ry = 0.0, rxx = 0.0, rxy = 0.0, ryy = 0.0, len = 0.0, xf = 0.0, yf = 0.0;
|
|
|
|
|
float sample_x = 0.0, sample_y = 0.0;
|
|
|
|
|
float fx = 0.0, fy = 0.0, res1 = 0.0, res2 = 0.0, res3 = 0.0, res4 = 0.0;
|
|
|
|
|
float lvv = 0.0, lww = 0.0, modg = 0.0;
|
|
|
|
|
int x1 = 0, y1 = 0, x2 = 0, y2 = 0, sample_step = 0, pattern_size = 0, dcount = 0;
|
|
|
|
|
int dsize = 0, scale = 0, level = 0;
|
|
|
|
|
|
|
|
|
|
std::vector<TEvolution>& evolution_ = *_evolution;
|
|
|
|
|
|
|
|
|
|
// Set the descriptor size and the sample and pattern sizes
|
|
|
|
|
dsize = 64;
|
|
|
|
|
sample_step = 5;
|
|
|
|
|
pattern_size = 10;
|
|
|
|
|
|
|
|
|
|
// Get the information from the keypoint
|
|
|
|
|
yf = kpt.pt.y;
|
|
|
|
|
xf = kpt.pt.x;
|
|
|
|
|
scale = fRound(kpt.size / 2.0f);
|
|
|
|
|
level = kpt.class_id;
|
|
|
|
|
|
|
|
|
|
// Calculate descriptor for this interest point
|
|
|
|
|
for (int i = -pattern_size; i < pattern_size; i += sample_step) {
|
|
|
|
|
for (int j = -pattern_size; j < pattern_size; j += sample_step) {
|
|
|
|
|
|
|
|
|
|
dx = dy = mdx = mdy = 0.0;
|
|
|
|
|
|
|
|
|
|
for (int k = i; k < i + sample_step; k++) {
|
|
|
|
|
for (int l = j; l < j + sample_step; l++) {
|
|
|
|
|
|
|
|
|
|
// Get the coordinates of the sample point on the rotated axis
|
|
|
|
|
sample_y = yf + l*scale;
|
|
|
|
|
sample_x = xf + k*scale;
|
|
|
|
|
|
|
|
|
|
y1 = (int)(sample_y - 0.5f);
|
|
|
|
|
x1 = (int)(sample_x - 0.5f);
|
|
|
|
|
|
|
|
|
|
checkDescriptorLimits(x1, y1, options.img_width, options.img_height);
|
|
|
|
|
|
|
|
|
|
y2 = (int)(sample_y + 0.5f);
|
|
|
|
|
x2 = (int)(sample_x + 0.5f);
|
|
|
|
|
|
|
|
|
|
checkDescriptorLimits(x2, y2, options.img_width, options.img_height);
|
|
|
|
|
|
|
|
|
|
fx = sample_x - x1;
|
|
|
|
|
fy = sample_y - y1;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lx.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lx.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lx.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lx.ptr<float>(y2)+x2);
|
|
|
|
|
rx = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Ly.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Ly.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Ly.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Ly.ptr<float>(y2)+x2);
|
|
|
|
|
ry = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
modg = pow(rx, 2) + pow(ry, 2);
|
|
|
|
|
|
|
|
|
|
if (modg != 0.0) {
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lxx.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lxx.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lxx.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lxx.ptr<float>(y2)+x2);
|
|
|
|
|
rxx = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lxy.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lxy.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lxy.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lxy.ptr<float>(y2)+x2);
|
|
|
|
|
rxy = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lyy.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lyy.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lyy.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lyy.ptr<float>(y2)+x2);
|
|
|
|
|
ryy = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
// Lww = (Lx^2 * Lxx + 2*Lx*Lxy*Ly + Ly^2*Lyy) / (Lx^2 + Ly^2)
|
|
|
|
|
lww = (pow(rx, 2)*rxx + 2.0f*rx*rxy*ry + pow(ry, 2)*ryy) / (modg);
|
|
|
|
|
|
|
|
|
|
// Lvv = (-2*Lx*Lxy*Ly + Lxx*Ly^2 + Lx^2*Lyy) / (Lx^2 + Ly^2)
|
|
|
|
|
lvv = (-2.0f*rx*rxy*ry + rxx*pow(ry, 2) + pow(rx, 2)*ryy) / (modg);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
lww = 0.0;
|
|
|
|
|
lvv = 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sum the derivatives to the cumulative descriptor
|
|
|
|
|
dx += lww;
|
|
|
|
|
dy += lvv;
|
|
|
|
|
mdx += fabs(lww);
|
|
|
|
|
mdy += fabs(lvv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add the values to the descriptor vector
|
|
|
|
|
desc[dcount++] = dx;
|
|
|
|
|
desc[dcount++] = dy;
|
|
|
|
|
desc[dcount++] = mdx;
|
|
|
|
|
desc[dcount++] = mdy;
|
|
|
|
|
|
|
|
|
|
// Store the current length^2 of the vector
|
|
|
|
|
len += dx*dx + dy*dy + mdx*mdx + mdy*mdy;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// convert to unit vector
|
|
|
|
|
len = sqrt(len);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < dsize; i++) {
|
|
|
|
|
desc[i] /= len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.use_clipping_normalilzation) {
|
|
|
|
|
clippingDescriptor(desc, dsize, options.clipping_normalization_niter, options.clipping_normalization_ratio);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief This method computes the G-SURF descriptor of the provided keypoint given the
|
|
|
|
|
* main orientation
|
|
|
|
|
* @param kpt Input keypoint
|
|
|
|
|
* @param desc Descriptor vector
|
|
|
|
|
* @note Rectangular grid of 20 s x 20 s. Descriptor Length 64. No additional
|
|
|
|
|
* G-SURF descriptor as described in Pablo F. Alcantarilla, Luis M. Bergasa and
|
|
|
|
|
* Andrew J. Davison, Gauge-SURF Descriptors, Image and Vision Computing 31(1), 2013
|
|
|
|
|
*/
|
|
|
|
|
void GSURF_Descriptor_Invoker::Get_GSURF_Descriptor_64(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
{
|
|
|
|
|
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0;
|
|
|
|
|
float rx = 0.0, ry = 0.0, rxx = 0.0, rxy = 0.0, ryy = 0.0, len = 0.0, xf = 0.0, yf = 0.0;
|
|
|
|
|
float sample_x = 0.0, sample_y = 0.0, co = 0.0, si = 0.0, angle = 0.0;
|
|
|
|
|
float fx = 0.0, fy = 0.0, res1 = 0.0, res2 = 0.0, res3 = 0.0, res4 = 0.0;
|
|
|
|
|
float lvv = 0.0, lww = 0.0, modg = 0.0;
|
|
|
|
|
int x1 = 0, y1 = 0, x2 = 0, y2 = 0, sample_step = 0, pattern_size = 0, dcount = 0;
|
|
|
|
|
int dsize = 0, scale = 0, level = 0;
|
|
|
|
|
|
|
|
|
|
std::vector<TEvolution>& evolution_ = *_evolution;
|
|
|
|
|
|
|
|
|
|
// Set the descriptor size and the sample and pattern sizes
|
|
|
|
|
dsize = 64;
|
|
|
|
|
sample_step = 5;
|
|
|
|
|
pattern_size = 10;
|
|
|
|
|
|
|
|
|
|
// Get the information from the keypoint
|
|
|
|
|
yf = kpt.pt.y;
|
|
|
|
|
xf = kpt.pt.x;
|
|
|
|
|
scale = fRound(kpt.size / 2.0f);
|
|
|
|
|
angle = kpt.angle;
|
|
|
|
|
level = kpt.class_id;
|
|
|
|
|
co = cos(angle);
|
|
|
|
|
si = sin(angle);
|
|
|
|
|
|
|
|
|
|
// Calculate descriptor for this interest point
|
|
|
|
|
for (int i = -pattern_size; i < pattern_size; i += sample_step) {
|
|
|
|
|
for (int j = -pattern_size; j < pattern_size; j += sample_step) {
|
|
|
|
|
|
|
|
|
|
dx = dy = mdx = mdy = 0.0;
|
|
|
|
|
|
|
|
|
|
for (int k = i; k < i + sample_step; k++) {
|
|
|
|
|
for (int l = j; l < j + sample_step; l++) {
|
|
|
|
|
|
|
|
|
|
// Get the coordinates of the sample point on the rotated axis
|
|
|
|
|
sample_y = yf + (l*scale*co + k*scale*si);
|
|
|
|
|
sample_x = xf + (-l*scale*si + k*scale*co);
|
|
|
|
|
|
|
|
|
|
y1 = (int)(sample_y - 0.5f);
|
|
|
|
|
x1 = (int)(sample_x - 0.5f);
|
|
|
|
|
|
|
|
|
|
checkDescriptorLimits(x1, y1, options.img_width, options.img_height);
|
|
|
|
|
|
|
|
|
|
y2 = (int)(sample_y + 0.5f);
|
|
|
|
|
x2 = (int)(sample_x + 0.5f);
|
|
|
|
|
|
|
|
|
|
checkDescriptorLimits(x2, y2, options.img_width, options.img_height);
|
|
|
|
|
|
|
|
|
|
fx = sample_x - x1;
|
|
|
|
|
fy = sample_y - y1;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lx.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lx.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lx.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lx.ptr<float>(y2)+x2);
|
|
|
|
|
rx = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Ly.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Ly.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Ly.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Ly.ptr<float>(y2)+x2);
|
|
|
|
|
ry = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
modg = pow(rx, 2) + pow(ry, 2);
|
|
|
|
|
|
|
|
|
|
if (modg != 0.0) {
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lxx.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lxx.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lxx.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lxx.ptr<float>(y2)+x2);
|
|
|
|
|
rxx = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lxy.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lxy.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lxy.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lxy.ptr<float>(y2)+x2);
|
|
|
|
|
rxy = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lyy.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lyy.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lyy.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lyy.ptr<float>(y2)+x2);
|
|
|
|
|
ryy = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
// Lww = (Lx^2 * Lxx + 2*Lx*Lxy*Ly + Ly^2*Lyy) / (Lx^2 + Ly^2)
|
|
|
|
|
lww = (pow(rx, 2)*rxx + 2.0f*rx*rxy*ry + pow(ry, 2)*ryy) / (modg);
|
|
|
|
|
|
|
|
|
|
// Lvv = (-2*Lx*Lxy*Ly + Lxx*Ly^2 + Lx^2*Lyy) / (Lx^2 + Ly^2)
|
|
|
|
|
lvv = (-2.0f*rx*rxy*ry + rxx*pow(ry, 2) + pow(rx, 2)*ryy) / (modg);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
lww = 0.0;
|
|
|
|
|
lvv = 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sum the derivatives to the cumulative descriptor
|
|
|
|
|
dx += lww;
|
|
|
|
|
dy += lvv;
|
|
|
|
|
mdx += fabs(lww);
|
|
|
|
|
mdy += fabs(lvv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add the values to the descriptor vector
|
|
|
|
|
desc[dcount++] = dx;
|
|
|
|
|
desc[dcount++] = dy;
|
|
|
|
|
desc[dcount++] = mdx;
|
|
|
|
|
desc[dcount++] = mdy;
|
|
|
|
|
|
|
|
|
|
// Store the current length^2 of the vector
|
|
|
|
|
len += dx*dx + dy*dy + mdx*mdx + mdy*mdy;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// convert to unit vector
|
|
|
|
|
len = sqrt(len);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < dsize; i++) {
|
|
|
|
|
desc[i] /= len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.use_clipping_normalilzation) {
|
|
|
|
|
clippingDescriptor(desc, dsize, options.clipping_normalization_niter, options.clipping_normalization_ratio);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief This method computes the extended upright descriptor (not rotation invariant) of
|
|
|
|
|
* the provided keypoint
|
|
|
|
@@ -1275,7 +932,7 @@ void GSURF_Descriptor_Invoker::Get_GSURF_Descriptor_64(const cv::KeyPoint &kpt,
|
|
|
|
|
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
|
|
|
|
* ECCV 2008
|
|
|
|
|
*/
|
|
|
|
|
void MSURF_Descriptor_Invoker::Get_MSURF_Upright_Descriptor_128(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
void KAZE_Descriptor_Invoker::Get_KAZE_Upright_Descriptor_128(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
{
|
|
|
|
|
float gauss_s1 = 0.0, gauss_s2 = 0.0;
|
|
|
|
|
float rx = 0.0, ry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
|
|
|
@@ -1433,7 +1090,7 @@ void MSURF_Descriptor_Invoker::Get_MSURF_Upright_Descriptor_128(const cv::KeyPoi
|
|
|
|
|
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
|
|
|
|
* ECCV 2008
|
|
|
|
|
*/
|
|
|
|
|
void MSURF_Descriptor_Invoker::Get_MSURF_Descriptor_128(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
void KAZE_Descriptor_Invoker::Get_KAZE_Descriptor_128(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
{
|
|
|
|
|
float gauss_s1 = 0.0, gauss_s2 = 0.0;
|
|
|
|
|
float rx = 0.0, ry = 0.0, rrx = 0.0, rry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
|
|
|
@@ -1587,322 +1244,6 @@ void MSURF_Descriptor_Invoker::Get_MSURF_Descriptor_128(const cv::KeyPoint &kpt,
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief This method computes the G-SURF upright extended descriptor
|
|
|
|
|
* (no rotation invariant) of the provided keypoint
|
|
|
|
|
* @param kpt Input keypoint
|
|
|
|
|
* @param desc Descriptor vector
|
|
|
|
|
* @note Rectangular grid of 20 s x 20 s. Descriptor Length 128. No additional
|
|
|
|
|
* G-SURF descriptor as described in Pablo F. Alcantarilla, Luis M. Bergasa and
|
|
|
|
|
* Andrew J. Davison, Gauge-SURF Descriptors, Image and Vision Computing 31(1), 2013
|
|
|
|
|
*/
|
|
|
|
|
void GSURF_Descriptor_Invoker::Get_GSURF_Upright_Descriptor_128(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
{
|
|
|
|
|
float len = 0.0, xf = 0.0, yf = 0.0, sample_x = 0.0, sample_y = 0.0;
|
|
|
|
|
float rx = 0.0, ry = 0.0, rxx = 0.0, rxy = 0.0, ryy = 0.0, modg = 0.0;
|
|
|
|
|
float fx = 0.0, fy = 0.0, res1 = 0.0, res2 = 0.0, res3 = 0.0, res4 = 0.0;
|
|
|
|
|
float dxp = 0.0, dyp = 0.0, mdxp = 0.0, mdyp = 0.0;
|
|
|
|
|
float dxn = 0.0, dyn = 0.0, mdxn = 0.0, mdyn = 0.0, lvv = 0.0, lww = 0.0;
|
|
|
|
|
int x1 = 0, y1 = 0, x2 = 0, y2 = 0, sample_step = 0, pattern_size = 0, dcount = 0;
|
|
|
|
|
int dsize = 0, scale = 0, level = 0;
|
|
|
|
|
|
|
|
|
|
std::vector<TEvolution>& evolution_ = *_evolution;
|
|
|
|
|
|
|
|
|
|
// Set the descriptor size and the sample and pattern sizes
|
|
|
|
|
dsize = 128;
|
|
|
|
|
sample_step = 5;
|
|
|
|
|
pattern_size = 10;
|
|
|
|
|
|
|
|
|
|
// Get the information from the keypoint
|
|
|
|
|
yf = kpt.pt.y;
|
|
|
|
|
xf = kpt.pt.x;
|
|
|
|
|
scale = fRound(kpt.size / 2.0f);
|
|
|
|
|
level = kpt.class_id;
|
|
|
|
|
|
|
|
|
|
// Calculate descriptor for this interest point
|
|
|
|
|
for (int i = -pattern_size; i < pattern_size; i += sample_step) {
|
|
|
|
|
for (int j = -pattern_size; j < pattern_size; j += sample_step) {
|
|
|
|
|
|
|
|
|
|
dxp = dxn = mdxp = mdxn = 0.0;
|
|
|
|
|
dyp = dyn = mdyp = mdyn = 0.0;
|
|
|
|
|
|
|
|
|
|
for (int k = i; k < i + sample_step; k++) {
|
|
|
|
|
for (int l = j; l < j + sample_step; l++) {
|
|
|
|
|
|
|
|
|
|
sample_y = k*scale + yf;
|
|
|
|
|
sample_x = l*scale + xf;
|
|
|
|
|
|
|
|
|
|
y1 = (int)(sample_y - 0.5f);
|
|
|
|
|
x1 = (int)(sample_x - 0.5f);
|
|
|
|
|
|
|
|
|
|
checkDescriptorLimits(x1, y1, options.img_width, options.img_height);
|
|
|
|
|
|
|
|
|
|
y2 = (int)(sample_y + 0.5f);
|
|
|
|
|
x2 = (int)(sample_x + 0.5f);
|
|
|
|
|
|
|
|
|
|
checkDescriptorLimits(x2, y2, options.img_width, options.img_height);
|
|
|
|
|
|
|
|
|
|
fx = sample_x - x1;
|
|
|
|
|
fy = sample_y - y1;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lx.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lx.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lx.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lx.ptr<float>(y2)+x2);
|
|
|
|
|
rx = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Ly.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Ly.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Ly.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Ly.ptr<float>(y2)+x2);
|
|
|
|
|
ry = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
modg = pow(rx, 2) + pow(ry, 2);
|
|
|
|
|
|
|
|
|
|
if (modg != 0.0) {
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lxx.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lxx.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lxx.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lxx.ptr<float>(y2)+x2);
|
|
|
|
|
rxx = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lxy.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lxy.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lxy.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lxy.ptr<float>(y2)+x2);
|
|
|
|
|
rxy = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lyy.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lyy.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lyy.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lyy.ptr<float>(y2)+x2);
|
|
|
|
|
ryy = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
// Lww = (Lx^2 * Lxx + 2*Lx*Lxy*Ly + Ly^2*Lyy) / (Lx^2 + Ly^2)
|
|
|
|
|
lww = (pow(rx, 2)*rxx + 2.0f*rx*rxy*ry + pow(ry, 2)*ryy) / (modg);
|
|
|
|
|
|
|
|
|
|
// Lvv = (-2*Lx*Lxy*Ly + Lxx*Ly^2 + Lx^2*Lyy) / (Lx^2 + Ly^2)
|
|
|
|
|
lvv = (-2.0f*rx*rxy*ry + rxx*pow(ry, 2) + pow(rx, 2)*ryy) / (modg);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
lww = 0.0;
|
|
|
|
|
lvv = 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sum the derivatives to the cumulative descriptor
|
|
|
|
|
if (lww >= 0.0) {
|
|
|
|
|
dxp += lvv;
|
|
|
|
|
mdxp += fabs(lvv);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
dxn += lvv;
|
|
|
|
|
mdxn += fabs(lvv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lvv >= 0.0) {
|
|
|
|
|
dyp += lww;
|
|
|
|
|
mdyp += fabs(lww);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
dyn += lww;
|
|
|
|
|
mdyn += fabs(lww);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add the values to the descriptor vector
|
|
|
|
|
desc[dcount++] = dxp;
|
|
|
|
|
desc[dcount++] = dxn;
|
|
|
|
|
desc[dcount++] = mdxp;
|
|
|
|
|
desc[dcount++] = mdxn;
|
|
|
|
|
desc[dcount++] = dyp;
|
|
|
|
|
desc[dcount++] = dyn;
|
|
|
|
|
desc[dcount++] = mdyp;
|
|
|
|
|
desc[dcount++] = mdyn;
|
|
|
|
|
|
|
|
|
|
// Store the current length^2 of the vector
|
|
|
|
|
len += dxp*dxp + dxn*dxn + mdxp*mdxp + mdxn*mdxn +
|
|
|
|
|
dyp*dyp + dyn*dyn + mdyp*mdyp + mdyn*mdyn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// convert to unit vector
|
|
|
|
|
len = sqrt(len);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < dsize; i++) {
|
|
|
|
|
desc[i] /= len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.use_clipping_normalilzation) {
|
|
|
|
|
clippingDescriptor(desc, dsize, options.clipping_normalization_niter, options.clipping_normalization_ratio);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief This method computes the extended descriptor of the provided keypoint given the
|
|
|
|
|
* main orientation
|
|
|
|
|
* @param kpt Input keypoint
|
|
|
|
|
* @param desc Descriptor vector
|
|
|
|
|
* @note Rectangular grid of 20 s x 20 s. Descriptor Length 128. No additional
|
|
|
|
|
* G-SURF descriptor as described in Pablo F. Alcantarilla, Luis M. Bergasa and
|
|
|
|
|
* Andrew J. Davison, Gauge-SURF Descriptors, Image and Vision Computing 31(1), 2013
|
|
|
|
|
*/
|
|
|
|
|
void GSURF_Descriptor_Invoker::Get_GSURF_Descriptor_128(const cv::KeyPoint &kpt, float *desc) const
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
float len = 0.0, xf = 0.0, yf = 0.0;
|
|
|
|
|
float rx = 0.0, ry = 0.0, rxx = 0.0, rxy = 0.0, ryy = 0.0;
|
|
|
|
|
float sample_x = 0.0, sample_y = 0.0, co = 0.0, si = 0.0, angle = 0.0;
|
|
|
|
|
float fx = 0.0, fy = 0.0, res1 = 0.0, res2 = 0.0, res3 = 0.0, res4 = 0.0;
|
|
|
|
|
float dxp = 0.0, dyp = 0.0, mdxp = 0.0, mdyp = 0.0;
|
|
|
|
|
float dxn = 0.0, dyn = 0.0, mdxn = 0.0, mdyn = 0.0;
|
|
|
|
|
float lvv = 0.0, lww = 0.0, modg = 0.0;
|
|
|
|
|
int x1 = 0, y1 = 0, x2 = 0, y2 = 0, sample_step = 0, pattern_size = 0, dcount = 0;
|
|
|
|
|
int dsize = 0, scale = 0, level = 0;
|
|
|
|
|
|
|
|
|
|
std::vector<TEvolution>& evolution_ = *_evolution;
|
|
|
|
|
|
|
|
|
|
// Set the descriptor size and the sample and pattern sizes
|
|
|
|
|
dsize = 128;
|
|
|
|
|
sample_step = 5;
|
|
|
|
|
pattern_size = 10;
|
|
|
|
|
|
|
|
|
|
// Get the information from the keypoint
|
|
|
|
|
yf = kpt.pt.y;
|
|
|
|
|
xf = kpt.pt.x;
|
|
|
|
|
scale = fRound(kpt.size / 2.0f);
|
|
|
|
|
angle = kpt.angle;
|
|
|
|
|
level = kpt.class_id;
|
|
|
|
|
co = cos(angle);
|
|
|
|
|
si = sin(angle);
|
|
|
|
|
|
|
|
|
|
// Calculate descriptor for this interest point
|
|
|
|
|
for (int i = -pattern_size; i < pattern_size; i += sample_step) {
|
|
|
|
|
for (int j = -pattern_size; j < pattern_size; j += sample_step) {
|
|
|
|
|
|
|
|
|
|
dxp = dxn = mdxp = mdxn = 0.0;
|
|
|
|
|
dyp = dyn = mdyp = mdyn = 0.0;
|
|
|
|
|
|
|
|
|
|
for (int k = i; k < i + sample_step; k++) {
|
|
|
|
|
for (int l = j; l < j + sample_step; l++) {
|
|
|
|
|
|
|
|
|
|
// Get the coordinates of the sample point on the rotated axis
|
|
|
|
|
sample_y = yf + (l*scale*co + k*scale*si);
|
|
|
|
|
sample_x = xf + (-l*scale*si + k*scale*co);
|
|
|
|
|
|
|
|
|
|
y1 = (int)(sample_y - 0.5f);
|
|
|
|
|
x1 = (int)(sample_x - 0.5f);
|
|
|
|
|
|
|
|
|
|
checkDescriptorLimits(x1, y1, options.img_width, options.img_height);
|
|
|
|
|
|
|
|
|
|
y2 = (int)(sample_y + 0.5f);
|
|
|
|
|
x2 = (int)(sample_x + 0.5f);
|
|
|
|
|
|
|
|
|
|
checkDescriptorLimits(x2, y2, options.img_width, options.img_height);
|
|
|
|
|
|
|
|
|
|
fx = sample_x - x1;
|
|
|
|
|
fy = sample_y - y1;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lx.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lx.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lx.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lx.ptr<float>(y2)+x2);
|
|
|
|
|
rx = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Ly.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Ly.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Ly.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Ly.ptr<float>(y2)+x2);
|
|
|
|
|
ry = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
modg = pow(rx, 2) + pow(ry, 2);
|
|
|
|
|
|
|
|
|
|
if (modg != 0.0) {
|
|
|
|
|
res1 = *(evolution_[level].Lxx.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lxx.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lxx.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lxx.ptr<float>(y2)+x2);
|
|
|
|
|
rxx = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lxy.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lxy.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lxy.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lxy.ptr<float>(y2)+x2);
|
|
|
|
|
rxy = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
res1 = *(evolution_[level].Lyy.ptr<float>(y1)+x1);
|
|
|
|
|
res2 = *(evolution_[level].Lyy.ptr<float>(y1)+x2);
|
|
|
|
|
res3 = *(evolution_[level].Lyy.ptr<float>(y2)+x1);
|
|
|
|
|
res4 = *(evolution_[level].Lyy.ptr<float>(y2)+x2);
|
|
|
|
|
ryy = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
|
|
|
|
|
|
|
|
|
|
// Lww = (Lx^2 * Lxx + 2*Lx*Lxy*Ly + Ly^2*Lyy) / (Lx^2 + Ly^2)
|
|
|
|
|
lww = (pow(rx, 2)*rxx + 2.0f*rx*rxy*ry + pow(ry, 2)*ryy) / (modg);
|
|
|
|
|
|
|
|
|
|
// Lvv = (-2*Lx*Lxy*Ly + Lxx*Ly^2 + Lx^2*Lyy) / (Lx^2 + Ly^2)
|
|
|
|
|
lvv = (-2.0f*rx*rxy*ry + rxx*pow(ry, 2) + pow(rx, 2)*ryy) / (modg);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
lww = 0.0;
|
|
|
|
|
lvv = 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sum the derivatives to the cumulative descriptor
|
|
|
|
|
if (lww >= 0.0) {
|
|
|
|
|
dxp += lvv;
|
|
|
|
|
mdxp += fabs(lvv);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
dxn += lvv;
|
|
|
|
|
mdxn += fabs(lvv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lvv >= 0.0) {
|
|
|
|
|
dyp += lww;
|
|
|
|
|
mdyp += fabs(lww);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
dyn += lww;
|
|
|
|
|
mdyn += fabs(lww);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add the values to the descriptor vector
|
|
|
|
|
desc[dcount++] = dxp;
|
|
|
|
|
desc[dcount++] = dxn;
|
|
|
|
|
desc[dcount++] = mdxp;
|
|
|
|
|
desc[dcount++] = mdxn;
|
|
|
|
|
desc[dcount++] = dyp;
|
|
|
|
|
desc[dcount++] = dyn;
|
|
|
|
|
desc[dcount++] = mdyp;
|
|
|
|
|
desc[dcount++] = mdyn;
|
|
|
|
|
|
|
|
|
|
// Store the current length^2 of the vector
|
|
|
|
|
len += dxp*dxp + dxn*dxn + mdxp*mdxp + mdxn*mdxn +
|
|
|
|
|
dyp*dyp + dyn*dyn + mdyp*mdyp + mdyn*mdyn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// convert to unit vector
|
|
|
|
|
len = sqrt(len);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < dsize; i++) {
|
|
|
|
|
desc[i] /= len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.use_clipping_normalilzation) {
|
|
|
|
|
clippingDescriptor(desc, dsize, options.clipping_normalization_niter, options.clipping_normalization_ratio);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief This method performs a scalar non-linear diffusion step using AOS schemes
|
|
|
|
|
* @param Ld Image at a given evolution step
|
|
|
|
@@ -1911,7 +1252,7 @@ void GSURF_Descriptor_Invoker::Get_GSURF_Descriptor_128(const cv::KeyPoint &kpt,
|
|
|
|
|
* @param stepsize Stepsize for the nonlinear diffusion evolution
|
|
|
|
|
* @note If c is constant, the diffusion will be linear
|
|
|
|
|
* If c is a matrix of the same size as Ld, the diffusion will be nonlinear
|
|
|
|
|
* The stepsize can be arbitrarilly large
|
|
|
|
|
* The stepsize can be arbitrarily large
|
|
|
|
|
*/
|
|
|
|
|
void KAZEFeatures::AOS_Step_Scalar(cv::Mat &Ld, const cv::Mat &Ldprev, const cv::Mat &c, const float& stepsize) {
|
|
|
|
|
|
|
|
|
|