features2d.diff

Delia Passalacqua, 2011-02-10 08:06 pm

Download (23.9 kB)

 
modules/features2d/include/opencv2/features2d/features2d.hpp (copia locale)
45 45

  
46 46
#include "opencv2/core/core.hpp"
47 47
#include "opencv2/flann/flann.hpp"
48
#include "opencv2/imgproc/gaussian_pyramid.hpp"
48 49

  
49 50
#ifdef __cplusplus
50 51
#include <limits>
......
398 399
        CV_OUT vector<vector<Point> >& msers, const Mat& mask ) const;
399 400
};
400 401

  
402
class CV_EXPORTS HarrisLaplace
403
{
404

  
405
public:
406
    HarrisLaplace();
407
    HarrisLaplace(int numOctaves, float corn_thresh, int DOG_thresh,int maxCorners=1500, int num_layers=4);
408
    void detect(const Mat& image, vector<KeyPoint>& keypoints) const;
409
    virtual ~HarrisLaplace();
410

  
411
    int numOctaves;
412
    float corn_thresh;
413
    int DOG_thresh;
414
    int maxCorners;
415
    int num_layers;
416

  
417
};
418

  
419

  
401 420
/*!
402 421
 The "Star" Detector.
403 422
 
......
1460 1479
    int levels;
1461 1480
};
1462 1481

  
1482
class CV_EXPORTS HarrisLaplaceFeatureDetector : public FeatureDetector
1483
{
1484
public:
1485
 class CV_EXPORTS Params
1486
    {
1487
    public:
1488
        Params( int numOctaves=4, float corn_thresh=0.01, int DOG_thresh=3, int maxCorners=1500, int num_layers=4 );
1489
        
1490

  
1491
        int numOctaves;
1492
        float corn_thresh;
1493
        int DOG_thresh;
1494
        int maxCorners;
1495
        int num_layers;
1496
       
1497
    };
1498
    HarrisLaplaceFeatureDetector( const HarrisLaplaceFeatureDetector::Params& params=HarrisLaplaceFeatureDetector::Params() );
1499
    HarrisLaplaceFeatureDetector( int numOctaves, float corn_thresh, int DOG_thresh, int maxCorners, int num_layers);
1500
    virtual void read( const FileNode& fn );
1501
    virtual void write( FileStorage& fs ) const;
1502

  
1503
protected:
1504
	virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
1505

  
1506
    HarrisLaplace harris;
1507
    Params params;
1508
};
1509

  
1510

  
1511
class CV_EXPORTS HarrisAffineFeatureDetector : public FeatureDetector
1512
{
1513
public:
1514
 class CV_EXPORTS Params
1515
    {
1516
    public:
1517
        Params( int numOctaves=4, float corn_thresh=0.01, int DOG_thresh=3, int maxCorners=100, int num_layers=4 );
1518
        
1519

  
1520
        int numOctaves;
1521
        float corn_thresh;
1522
        int DOG_thresh;
1523
        int maxCorners;
1524
        int num_layers;
1525
       
1526
    };
1527
    HarrisAffineFeatureDetector( const HarrisAffineFeatureDetector::Params& params=HarrisAffineFeatureDetector::Params() );
1528
    HarrisAffineFeatureDetector( int numOctaves, float corn_thresh, int DOG_thresh, int maxCorners, int num_layers);
1529
    virtual void read( const FileNode& fn );
1530
    virtual void write( FileStorage& fs ) const;
1531

  
1532
protected:
1533
	virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
1534

  
1535
    HarrisLaplace harris;
1536
    Params params;
1537
};
1538

  
1463 1539
/** \brief A feature detector parameter adjuster, this is used by the DynamicAdaptedFeatureDetector
1464 1540
 *  and is a wrapper for FeatureDetector that allow them to be adjusted after a detection
1465 1541
 */
......
2768 2844
    Ptr<DescriptorMatcher> dmatcher;
2769 2845
};
2770 2846

  
2847
/*
2848
 * Elliptic region around interest point 
2849
 */
2850
class CV_EXPORTS Elliptic_KeyPoint : public KeyPoint{
2851
public:
2852
	Point centre;
2853
	Size axes;
2854
	double phi;
2855
	float size;
2856
	float si;
2857
	Mat transf;
2858
	Elliptic_KeyPoint();
2859
	Elliptic_KeyPoint(Point centre, double phi, Size axes, float size, float si);
2860
	virtual ~Elliptic_KeyPoint();
2861
};
2862

  
2863
/*
2864
 * Functions to perform affine adaptation of circular keypoint 
2865
 */
2866
void calcAffineCovariantRegions(const Mat& image, const vector<KeyPoint>& keypoints, vector<Elliptic_KeyPoint>& affRegions, string detector_type);
2867
void calcAffineCovariantDescriptors( const Ptr<DescriptorExtractor>& dextractor, const Mat& img, vector<Elliptic_KeyPoint>& affRegions, Mat& descriptors );
2868

  
2869

  
2771 2870
} /* namespace cv */
2772 2871

  
2773 2872
#endif /* __cplusplus */
modules/features2d/src/detectors.cpp (copia locale)
151 151
        pos += string("Dynamic").size();
152 152
        fd = new DynamicAdaptedFeatureDetector( AdjusterAdapter::create(detectorType.substr(pos)) );
153 153
    }
154
    else if( !detectorType.compare( "HarrisLaplace" ) )
155
    {
156
        fd = new HarrisLaplaceFeatureDetector();
157
    }
158
    else if( !detectorType.compare( "HarrisAffine" ) )
159
    {
160
        fd = new HarrisAffineFeatureDetector();
161
    }
154 162

  
155 163
    return fd;
156 164
}
......
587 595
    }
588 596
}
589 597

  
598
/*
599
 *  HarrisLaplaceFeatureDetector
600
 */
601
HarrisLaplaceFeatureDetector::Params::Params(int _numOctaves, float _corn_thresh, int _DOG_thresh, int _maxCorners, int _num_layers) :
602
    numOctaves(_numOctaves), corn_thresh(_corn_thresh), DOG_thresh(_DOG_thresh), maxCorners(_maxCorners), num_layers(_num_layers)
603
{}
604
HarrisLaplaceFeatureDetector::HarrisLaplaceFeatureDetector( int numOctaves, float corn_thresh, int DOG_thresh, int maxCorners, int num_layers)
605
  : harris( numOctaves, corn_thresh, DOG_thresh, maxCorners, num_layers)
606
{}
607

  
608
HarrisLaplaceFeatureDetector::HarrisLaplaceFeatureDetector(  const Params& params  )
609
 : harris( params.numOctaves, params.corn_thresh, params.DOG_thresh, params.maxCorners, params.num_layers)
610
 
611
{}
612

  
613
void HarrisLaplaceFeatureDetector::read (const FileNode& fn)
614
{
615
	int numOctaves = fn["numOctaves"];
616
	float corn_thresh = fn["corn_thresh"];
617
	int DOG_thresh = fn["DOG_thresh"];
618
	int maxCorners = fn["maxCorners"];
619
	int num_layers = fn["num_layers"];
620
	
621
    harris = HarrisLaplace( numOctaves, corn_thresh, DOG_thresh, maxCorners,num_layers );
590 622
}
623

  
624
void HarrisLaplaceFeatureDetector::write (FileStorage& fs) const
625
{
626

  
627
    fs << "numOctaves" << harris.numOctaves;
628
    fs << "corn_thresh" << harris.corn_thresh;
629
    fs << "DOG_thresh" << harris.DOG_thresh;
630
    fs << "maxCorners" << harris.maxCorners;
631
    fs << "num_layers" << harris.num_layers;
632

  
633
    
634
}
635

  
636

  
637
void HarrisLaplaceFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
638
{
639
	harris.detect(image, keypoints);
640
}
641

  
642
/*
643
 *  HarrisAffineFeatureDetector
644
 */
645
HarrisAffineFeatureDetector::Params::Params(int _numOctaves, float _corn_thresh, int _DOG_thresh, int _maxCorners, int _num_layers) :
646
    numOctaves(_numOctaves), corn_thresh(_corn_thresh), DOG_thresh(_DOG_thresh), maxCorners(_maxCorners), num_layers(_num_layers)
647
{}
648
HarrisAffineFeatureDetector::HarrisAffineFeatureDetector( int numOctaves, float corn_thresh, int DOG_thresh, int maxCorners, int num_layers)
649
  : harris( numOctaves, corn_thresh, DOG_thresh, maxCorners, num_layers)
650
{}
651

  
652
HarrisAffineFeatureDetector::HarrisAffineFeatureDetector(  const Params& params  )
653
 : harris( params.numOctaves, params.corn_thresh, params.DOG_thresh, params.maxCorners, params.num_layers)
654
 
655
{}
656

  
657
void HarrisAffineFeatureDetector::read (const FileNode& fn)
658
{
659
	int numOctaves = fn["numOctaves"];
660
	float corn_thresh = fn["corn_thresh"];
661
	int DOG_thresh = fn["DOG_thresh"];
662
	int maxCorners = fn["maxCorners"];
663
	int num_layers = fn["num_layers"];
664
	
665
    harris = HarrisLaplace( numOctaves, corn_thresh, DOG_thresh, maxCorners,num_layers );
666
}
667

  
668
void HarrisAffineFeatureDetector::write (FileStorage& fs) const
669
{
670

  
671
    fs << "numOctaves" << harris.numOctaves;
672
    fs << "corn_thresh" << harris.corn_thresh;
673
    fs << "DOG_thresh" << harris.DOG_thresh;
674
    fs << "maxCorners" << harris.maxCorners;
675
    fs << "num_layers" << harris.num_layers;
676

  
677
    
678
}
679

  
680

  
681
void HarrisAffineFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
682
{
683
	harris.detect(image, keypoints);
684
	vector<Elliptic_KeyPoint> ekeypoints;
685
	Mat fimage;
686
    image.convertTo(fimage, CV_32F, 1.f / 255);
687
	calcAffineCovariantRegions(fimage, keypoints, ekeypoints, "HarrisLaplace");
688
	keypoints.clear();
689
	keypoints = vector<KeyPoint>(ekeypoints.begin(), ekeypoints.end());
690
}
691
}
modules/features2d/src/affineAdaptation.cpp (revisione 0)
1
/*
2
 * Functions to perform affine adaptation of keypoint and to calculate descriptors of elliptic regions
3
 */
4

  
5
#include "precomp.hpp"
6

  
7
namespace cv
8
{
9
void calcDerivatives(const Mat& image, Mat & dx2, Mat & dxy, Mat & dy2, float si, float sd);
10
void calcSecondMomentMatrix(const Mat & dx2, const Mat & dxy, const Mat & dy2, Point p, Mat& M);
11
bool calcAffineAdaptation(const Mat & image, Elliptic_KeyPoint& keypoint);
12
float selIntegrationScale(const Mat & image, float si, Point c);
13
float selDifferentiationScale(const Mat & image, Mat & Lxm2smooth, Mat & Lxmysmooth, Mat & Lym2smooth, float si, Point c);
14
float calcSecondMomentSqrt(const Mat & dx2, const Mat & dxy, const Mat & dy2, Point p, Mat& Mk);
15
float normMaxEval(Mat & U, Mat& uVal, Mat& uVect);
16

  
17
/*
18
 * Calculates derivatives according to integration scale and differentiation scale
19
 * si - integration scale
20
 * sd - differentiation scale
21
 * dx2, dxy and dy2 are per-element derivatives multiplication
22
 */
23
/*void calcDerivatives(const Mat & image, Mat & dx2, Mat & dxy, Mat & dy2, float si, float sd)
24
 {
25
 int gsize = ceil(sd * 3) * 2 + 1;
26
 Size ksize(gsize, gsize);
27
 Mat L, Lx, Ly;
28

  
29
 GaussianBlur(image, L, ksize, sd, sd);
30

  
31
 Sobel(L, Lx, L.depth(), 1, 0, 3);//TODO era 3 messo a 1 come in harris laplace?
32
 Lx = Lx * sd;
33

  
34
 Sobel(L, Ly, L.depth(), 0, 1, 3);
35
 Ly = Ly * sd;
36

  
37
 gsize = ceil(si * 3) * 2 + 1;
38
 ksize = Size(gsize, gsize);
39

  
40
 Mat Lxm2 = Lx.mul(Lx);
41
 GaussianBlur(Lxm2, dx2, ksize, si, si, BORDER_REPLICATE);
42

  
43
 Mat Lym2 = Ly.mul(Ly);
44
 GaussianBlur(Lym2, dy2, ksize, si, si, BORDER_REPLICATE);
45

  
46
 Mat Lxmy = Lx.mul(Ly);
47
 GaussianBlur(Lxmy, dxy, ksize, si, si, BORDER_REPLICATE);
48

  
49
 }*/
50

  
51
/*
52
 * Calculates second moments matrix in point p
53
 */
54
void calcSecondMomentMatrix(const Mat & dx2, const Mat & dxy, const Mat & dy2, Point p, Mat & M)
55
{
56
    int x = p.x;
57
    int y = p.y;
58

  
59
    M.create(2, 2, CV_32FC1);
60
    M.at<float> (0, 0) = dx2.at<float> (y, x);
61
    M.at<float> (0, 1) = M.at<float> (1, 0) = dxy.at<float> (y, x);
62
    M.at<float> (1, 1) = dy2.at<float> (y, x);
63
}
64

  
65
/*
66
 * Performs affine adaptation
67
 */
68
bool calcAffineAdaptation(const Mat & fimage, Elliptic_KeyPoint & keypoint)
69
{
70
    Mat_<float> transf(2, 3)/*Trasformation matrix*/,
71
            size(2, 1)/*Image size after transformation*/, c(2, 1)/*Transformed point*/, p(2, 1) /*Image point*/;
72
    Mat U = Mat::eye(2, 2, CV_32F) * 1;
73

  
74
    Mat warpedImg, Mk, Lxm2smooth, Lym2smooth, Lxmysmooth, img_roi;
75
    float Qinv = 1, q, si = keypoint.si, sd = 0.75 * si;
76
    bool divergence = false, convergence = false;
77
    int i = 0;
78

  
79
    //Coordinates in image
80
    int py = keypoint.centre.y;
81
    int px = keypoint.centre.x;
82

  
83
    //Roi coordinates
84
    int roix, roiy;
85

  
86
    //Coordinates in U-trasformation
87
    int cx = px;
88
    int cy = py;
89
    int cxPr = cx;
90
    int cyPr = cy;
91

  
92
    float radius = keypoint.size * 1.4;
93
    float half_width, half_height;
94

  
95
    Rect roi;
96

  
97
    //Affine adaptation
98
    while (i <= 10 && !divergence && !convergence)
99
    {
100
        //Transformation matrix creation
101
        transf.setTo(0);
102
        Mat col0 = transf.col(0);
103
        U.col(0).copyTo(col0);
104
        Mat col1 = transf.col(1);
105
        U.col(1).copyTo(col1);
106
        keypoint.transf = Mat(transf);
107

  
108
        //Create window around interest point
109
        half_width = min((float) min(fimage.cols - px, px), ceil(radius) + 10);
110
        half_height = min((float) min(fimage.rows - py, py), ceil(radius) + 10);
111
        roix = max(px - (int) half_width, 0);
112
        roiy = max(py - (int) half_height, 0);
113
        roi = Rect(roix, roiy, px - roix + half_width, py - roiy + half_height);
114
        img_roi = fimage(roi);
115

  
116
        //Point within the Roi
117
        p(0, 0) = px - roix;
118
        p(1, 0) = py - roiy;
119

  
120
        if (half_width <= 0 || half_height <= 0)
121
            return divergence;
122

  
123
        //Size of normalized window
124
        size(0, 0) = img_roi.cols;
125
        size(1, 0) = img_roi.rows;
126
        size = U * size;
127

  
128
        //Size of normalized window must be 2*si*3
129
        if (ceil(size(0, 0)) >= 2 * radius && ceil(size(1, 0)) >= 2 * radius)
130
        {
131
            //Transformation
132
            Mat warpedImgRoi;
133
            warpAffine(img_roi, warpedImgRoi, transf, Size(ceil(size(0, 0)), ceil(size(1, 0))),
134
                    INTER_AREA, BORDER_DEFAULT);
135

  
136
            //Point in U-Normalized coordinates
137
            c = U * p;
138
            cx = c(0, 0);
139
            cy = c(1, 0);
140

  
141
            //Cut around normalized patch
142
            roix = std::max(cx - si * 3 * 1.4, 0.0);
143
            roiy = std::max(cy - si * 3 * 1.4, 0.0);
144
            roi = Rect(roix, roiy, std::min(cx - roix + si * 3 * 1.4, (double) size(0, 0)),
145
                    std::min(cy - roiy + si * 3 * 1.4, (double) size(1, 0)));
146
            warpedImg = warpedImgRoi(roi);
147

  
148
            //Point's coordinates in cutted window
149
            cx = c(0, 0) - roix;
150
            cy = c(1, 0) - roiy;
151

  
152
            //Integration Scale selection
153
            si = selIntegrationScale(warpedImg, si, Point(cx, cy));
154

  
155
            //Differentation scale selection
156
            sd = selDifferentiationScale(warpedImg, Lxm2smooth, Lxmysmooth, Lym2smooth, si, Point(
157
                    cx, cy));
158

  
159
            //Spatial Localization
160
            cxPr = cx;
161
            cyPr = cy;
162

  
163
            float cornMax = 0;
164
            for (int j = 0; j < 3; j++)
165
            {
166
                for (int t = 0; t < 3; t++)
167
                {
168
                    float dx2 = Lxm2smooth.at<float> (cyPr - 1 + j, cxPr - 1 + t);
169
                    float dy2 = Lym2smooth.at<float> (cyPr - 1 + j, cxPr - 1 + t);
170
                    float dxy = Lxmysmooth.at<float> (cyPr - 1 + j, cxPr - 1 + t);
171
                    float det = dx2 * dy2 - dxy * dxy;
172
                    float tr = dx2 + dy2;
173
                    float cornerness = det - (0.04 * pow(tr, 2));
174
                    if (cornerness > cornMax)
175
                    {
176
                        cornMax = cornerness;
177
                        cx = cxPr - 1 + t;
178
                        cy = cyPr - 1 + j;
179
                    }
180
                }
181
            }
182

  
183
            //Transform point in image coordinates
184
            p(0, 0) = px;
185
            p(1, 0) = py;
186
            //Displacement vector
187
            c(0, 0) = cx - cxPr;
188
            c(1, 0) = cy - cyPr;
189
            //New interest point location in image
190
            p = p + U.inv() * c;
191
            px = p(0, 0);
192
            py = p(1, 0);
193

  
194
            q = calcSecondMomentSqrt(Lxm2smooth, Lxmysmooth, Lym2smooth, Point(cx, cy), Mk);
195

  
196
            float ratio = 1 - q;
197

  
198
            //if ratio == 1 means q == 0 and one axes equals to 0
199
            if (!isnan(ratio) && ratio != 1)
200
            {
201
                //Update U matrix
202
                U = U * Mk;
203

  
204
                Mat uVal, uV;
205
                eigen(U, uVal, uV);
206

  
207
                Qinv = normMaxEval(U, uVal, uV);
208
                //Keypoint doesn't converge
209
                if (Qinv >= 6)
210
                    divergence = true;
211
                //Keypoint converges
212
                else if (ratio <= 0.05)
213
                {
214
                    convergence = true;
215

  
216
                    //Set transformation matrix
217
                    transf.setTo(0);
218
                    Mat col0 = transf.col(0);
219
                    U.col(0).copyTo(col0);
220
                    Mat col1 = transf.col(1);
221
                    U.col(1).copyTo(col1);
222
                    keypoint.transf = Mat(transf);
223

  
224
                    float ax1 = 1. / std::abs(uVal.at<float> (0, 0)) * 3 * si;
225
                    float ax2 = 1. / std::abs(uVal.at<float> (1, 0)) * 3 * si;
226
                    double phi = atan(uV.at<float> (1, 0) / uV.at<float> (0, 0)) * (180) / CV_PI;
227
                    keypoint.axes = Size(ax1, ax2);
228
                    keypoint.phi = phi;
229
                    keypoint.centre = Point(px, py);
230
                    keypoint.si = si;
231
                    keypoint.size = 3 * si;
232
                } else
233
                    radius = 3 * si * 1.4;
234

  
235
            } else
236
                divergence = true;
237
        } else
238
            divergence = true;
239
        ++i;
240
    }
241

  
242
    return convergence;
243
}
244

  
245
/*
246
 * Selects the integration scale that maximize LoG in point c
247
 */
248
float selIntegrationScale(const Mat & image, float si, Point c)
249
{
250
    Mat Lap, L;
251
    int cx = c.x;
252
    int cy = c.y;
253
    float maxLap = 0;
254
    float maxsx = si;
255
    int gsize;
256
    float sigma, sigma_prev = 0;
257

  
258
    image.copyTo(L);
259
    /* Search best integration scale between previous and successive layer
260
     */
261
    for (float u = 0.7; u <= 1.41; u += 0.1)
262
    {
263
        float sik = u * si;
264
        sigma = sqrt(powf(sik, 2) - powf(sigma_prev, 2));
265

  
266
        gsize = ceil(sigma * 3) * 2 + 1;
267

  
268
        GaussianBlur(L, L, Size(gsize, gsize), sigma);
269
        sigma_prev = sik;
270

  
271
        Laplacian(L, Lap, CV_32F, 3);
272

  
273
        float lapVal = sik * sik * std::abs(Lap.at<float> (cy, cx));
274

  
275
        if (u == 0.7)
276
            maxLap = lapVal;
277

  
278
        if (lapVal >= maxLap)
279
        {
280
            maxLap = lapVal;
281
            maxsx = sik;
282

  
283
        }
284

  
285
    }
286
    return maxsx;
287
}
288

  
289
/*
290
 * Calculates second moments matrix square root
291
 */
292
float calcSecondMomentSqrt(const Mat & dx2, const Mat & dxy, const Mat & dy2, Point p, Mat & Mk)
293
{
294
    Mat M, V, eigVal, Vinv, D;
295

  
296
    calcSecondMomentMatrix(dx2, dxy, dy2, p, M);
297

  
298
    /* *
299
     * M = V * D * V.inv()
300
     * V has eigenvectors as columns
301
     * D is a diagonal Matrix with eigenvalues as elements
302
     * V.inv() is the inverse of V
303
     * */
304

  
305
    eigen(M, eigVal, V);
306
    V = V.t();
307
    Vinv = V.inv();
308

  
309
    float eval1 = eigVal.at<float> (0, 0) = sqrt(eigVal.at<float> (0, 0));
310
    float eval2 = eigVal.at<float> (1, 0) = sqrt(eigVal.at<float> (1, 0));
311

  
312
    D = Mat::diag(eigVal);
313

  
314
    //square root of M
315
    Mk = V * D * Vinv;
316
    //return q isotropic measure
317
    return min(eval1, eval2) / max(eval1, eval2);
318
}
319

  
320
float normMaxEval(Mat & U, Mat & uVal, Mat & uVec)
321
{
322
    /* *
323
     * Decomposition:
324
     * U = V * D * V.inv()
325
     * V has eigenvectors as columns
326
     * D is a diagonal Matrix with eigenvalues as elements
327
     * V.inv() is the inverse of V
328
     * */
329
    uVec = uVec.t();
330
    Mat uVinv = uVec.inv();
331

  
332
    //Normalize min eigenvalue to 1 to expand patch in the direction of min eigenvalue of U.inv()
333
    double uval1 = uVal.at<float> (0, 0);
334
    double uval2 = uVal.at<float> (1, 0);
335

  
336
    if (std::abs(uval1) < std::abs(uval2))
337
    {
338
        uVal.at<float> (0, 0) = 1;
339
        uVal.at<float> (1, 0) = uval2 / uval1;
340

  
341
    } else
342
    {
343
        uVal.at<float> (1, 0) = 1;
344
        uVal.at<float> (0, 0) = uval1 / uval2;
345

  
346
    }
347

  
348
    Mat D = Mat::diag(uVal);
349
    //U normalized
350
    U = uVec * D * uVinv;
351

  
352
    return max(std::abs(uVal.at<float> (0, 0)), std::abs(uVal.at<float> (1, 0))) / min(std::abs(
353
            uVal.at<float> (0, 0)), std::abs(uVal.at<float> (1, 0))); //define the direction of warping
354
}
355

  
356
/*
357
 * Selects diffrentiation scale
358
 */
359
float selDifferentiationScale(const Mat & img, Mat & Lxm2smooth, Mat & Lxmysmooth,
360
        Mat & Lym2smooth, float si, Point c)
361
{
362
    float s = 0.5;
363
    float sdk = s * si;
364
    float sigma_prev = 0, sigma;
365

  
366
    Mat L, dx2, dxy, dy2;
367

  
368
    double qMax = 0;
369

  
370
    //Gaussian kernel size
371
    int gsize;
372
    Size ksize;
373

  
374
    img.copyTo(L);
375

  
376
    while (s <= 0.751)
377
    {
378
        Mat M;
379
        float sd = s * si;
380

  
381
        //Smooth previous smoothed image L
382
        sigma = sqrt(powf(sd, 2) - powf(sigma_prev, 2));
383

  
384
        gsize = ceil(sigma * 3) * 2 + 1;
385
        GaussianBlur(L, L, Size(gsize, gsize), sigma);
386

  
387
        sigma_prev = sd;
388

  
389
        //X and Y derivatives
390
        Mat Lx, Ly;
391
        Sobel(L, Lx, L.depth(), 1, 0, 3);
392
        Lx = Lx * sd;
393
        Sobel(L, Ly, L.depth(), 0, 1, 3);
394
        Ly = Ly * sd;
395

  
396
        //Size of gaussian kernel
397
        gsize = ceil(si * 3) * 2 + 1;
398
        ksize = Size(gsize, gsize);
399

  
400
        Mat Lxm2 = Lx.mul(Lx);
401
        GaussianBlur(Lxm2, dx2, ksize, si, si, BORDER_REPLICATE);
402

  
403
        Mat Lym2 = Ly.mul(Ly);
404
        GaussianBlur(Lym2, dy2, ksize, si, si, BORDER_REPLICATE);
405

  
406
        Mat Lxmy = Lx.mul(Ly);
407
        GaussianBlur(Lxmy, dxy, ksize, si, si, BORDER_REPLICATE);
408

  
409
        calcSecondMomentMatrix(dx2, dxy, dy2, Point(c.x, c.y), M);
410

  
411
        //calc eigenvalues
412
        Mat eval;
413
        eigen(M, eval);
414
        double eval1 = std::abs(eval.at<float> (0, 0));
415
        double eval2 = std::abs(eval.at<float> (1, 0));
416
        double q = min(eval1, eval2) / max(eval1, eval2);
417

  
418
        if (q >= qMax)
419
        {
420
            qMax = q;
421
            sdk = sd;
422
            dx2.copyTo(Lxm2smooth);
423
            dxy.copyTo(Lxmysmooth);
424
            dy2.copyTo(Lym2smooth);
425

  
426
        }
427

  
428
        s += 0.05;
429
    }
430

  
431
    return sdk;
432
}
433

  
434
void calcAffineCovariantRegions(const Mat & image, const vector<KeyPoint> & keypoints, vector<
435
        Elliptic_KeyPoint> & affRegions, string detector_type)
436
{
437

  
438
    for (size_t i = 0; i < keypoints.size(); ++i)
439
    {
440
        KeyPoint kp = keypoints[i];
441
        Elliptic_KeyPoint ex(kp.pt, 0, Size(kp.size, kp.size), kp.size, kp.size / 3);
442

  
443
        if (calcAffineAdaptation(image, ex))
444
        {
445
            affRegions.push_back(ex);
446
        }
447
    }
448
}
449

  
450
void calcAffineCovariantDescriptors(const Ptr<DescriptorExtractor>& dextractor, const Mat& img,
451
        vector<Elliptic_KeyPoint>& affRegions, Mat& descriptors)
452
{
453

  
454
    assert(!affRegions.empty());
455
    int size = dextractor->descriptorSize();
456
    int type = dextractor->descriptorType();
457
    descriptors = Mat(Size(size, affRegions.size()), type);
458
    descriptors.setTo(0);
459

  
460
    int i = 0;
461

  
462
    for (vector<Elliptic_KeyPoint>::iterator it = affRegions.begin(); it < affRegions.end(); ++it)
463
    {
464
        Point p = it->centre;
465

  
466
        Mat_<float> size(2, 1);
467
        size(0, 0) = size(1, 0) = it->size;
468

  
469
        //U matrix
470
        Mat transf = it->transf;
471
        Mat_<float> U(2, 2);
472
        U.setTo(0);
473
        Mat col0 = U.col(0);
474
        transf.col(0).copyTo(col0);
475
        Mat col1 = U.col(1);
476
        transf.col(1).copyTo(col1);
477

  
478
        float radius = it->size;
479

  
480
        float half_width = min((float) min(img.cols - p.x, p.x), ceil(radius) + 10);
481
        float half_height = min((float) min(img.rows - p.y, p.y), ceil(radius) + 10);
482
        float roix = max(p.x - (int) half_width, 0);
483
        float roiy = max(p.y - (int) half_height, 0);
484
        Rect roi(roix, roiy, p.x - roix + half_width, p.y - roiy + half_height);
485
        Mat img_roi = img(roi);
486

  
487
        size(0, 0) = img_roi.cols;
488
        size(1, 0) = img_roi.rows;
489

  
490
        size = U * size;
491

  
492
        Mat transfImgRoi, transfImg;
493
        warpAffine(img_roi, transfImgRoi, transf, Size(ceil(size(0, 0)), ceil(size(1, 0))),
494
                INTER_AREA, BORDER_DEFAULT);
495

  
496
        //Trasformazione
497
        Mat_<float> c(2, 1); //Transformed point
498
        Mat_<float> pt(2, 1); //Image point
499
        //Point within the Roi
500
        pt(0, 0) = p.x - roix;
501
        pt(1, 0) = p.y - roiy;
502

  
503
        //Point in U-Normalized coordinates
504
        c = U * pt;
505
        float cx = c(0, 0);
506
        float cy = c(1, 0);
507

  
508
        //Cut around point to have patch of 2*keypoint->size
509

  
510
        roix = std::max(cx - radius, 0.f);
511
        roiy = std::max(cy - radius, 0.f);
512

  
513
        roi = Rect(roix, roiy, std::min(cx - roix + radius, size(0, 0)), std::min(cy - roiy
514
                + radius, size(1, 0)));
515
        transfImg = transfImgRoi(roi);
516

  
517
        cx = c(0, 0) - roix;
518
        cy = c(1, 0) - roiy;
519

  
520
        Mat tmpDesc;
521
        KeyPoint kp(Point(cx, cy), it->size);
522

  
523
        vector<KeyPoint> k(1, kp);
524

  
525
        transfImg.convertTo(transfImg, CV_8U);
526
        dextractor->compute(transfImg, k, tmpDesc);
527

  
528
        for (int j = 0; j < tmpDesc.cols; j++)
529
        {
530
            descriptors.at<float> (i, j) = tmpDesc.at<float> (0, j);
531
        }
532

  
533
        i++;
534

  
535
    }
536

  
537
}
538
}