// Catalano Imaging Library
// The Catalano Framework
//
// Copyright © Diego Catalano, 2012-2016
// diego.catalano at live.com
//
// Copyright © César Souza, 2009-2013
// cesarsouza at gmail.com
//
// Copyright (c) 2011-2012 LTS2, EPFL
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the CherryPy Team nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
package Catalano.Imaging.Corners.FREAK;
import Catalano.Math.Constants;
import java.util.ArrayList;
/**
* Fast Retina Keypoint (FREAK) pattern.
* @author Diego Catalano
*/
public class FastRetinaKeypointPattern {
/**
* Pattern scale resolution.
*/
public static final int Scales = 64;
/**
* Pattern orientation resulution.
*/
public static final int Orientations = 256;
/**
* Number of pattern points.
*/
public static final int Points = 43;
/**
* Smallest keypoint size.
*/
public static final int Size = 7;
private int octaves;
private float scale;
/**
* Look-up table for the pattern points (position + sigma of all points at all scales and orientation).
*/
public PatternPoint[] lookupTable;
/**
* Get the number of octaves.
* @return Octaves.
*/
public int getOctaves(){
return octaves;
}
/**
* Get the number of scale.
* @return Scale.
*/
public float getScale(){
return scale;
}
/**
* Step.
*/
public double step;
/**
* Pattern Sizes
*/
public int[] patternSizes = new int[Scales];
/**
* Point Values.
*/
public int[] pointsValues = new int[Points];
/**
* Description pairs.
*/
public DescriptionPair[] descriptionPairs = new DescriptionPair[512];
/**
* Orientation pairs.
*/
public OrientationPair[] orientationPairs = new OrientationPair[45];
/**
* Initializes a new instance of the FastRetinaKeypointPattern class.
* @param octaves Number of octaves.
* @param scales Scale.
*/
public FastRetinaKeypointPattern(int octaves, float scales) {
this.octaves = octaves;
this.scale = scales;
lookupTable = new PatternPoint[Scales * Orientations * Points];
double scaleStep = Math.pow(2.0, (double)(octaves) / Scales);
step = (float)(Scales / (Constants.Log2 * octaves));
// pattern definition, radius normalized to 1.0 (outer point position + sigma = 1.0)
// number of points on each concentric circle (from outer to inner)
int[] n = { 6, 6, 6, 6, 6, 6, 6, 1 };
double bigR = 2.0 / 3.0; // bigger radius
double smallR = 2.0 / 24.0; // smaller radius
double unitSpace = ((bigR - smallR) / 21.0); // define spaces between concentric circles (from center to outer: 1,2,3,4,5,6)
double[] radius =
{
bigR, bigR - 6 * unitSpace, // radii of the concentric cirles (from outer to inner)
bigR - 11 * unitSpace, bigR - 15 * unitSpace,
bigR - 18 * unitSpace, bigR - 20 * unitSpace,
smallR, 0.0
};
double[] sigma =
{
radius[0]/2.0, radius[1]/2.0,
radius[2]/2.0, radius[3]/2.0, // sigma of the pattern points (each group of 6
radius[4]/2.0, radius[5]/2.0, // points on a concentric cirle has same sigma)
radius[6]/2.0, radius[6]/2.0
};
// fill the lookup table
for (int scaleIdx = 0; scaleIdx < Scales; scaleIdx++)
{
patternSizes[scaleIdx] = 0;
double scalingFactor = Math.pow(scaleStep, scaleIdx);
for (int orientationIdx = 0; orientationIdx < Orientations; orientationIdx++)
{
// orientation of the pattern
double theta = orientationIdx * 2 * Math.PI / Orientations;
int pointIdx = 0;
for (int i = 0; i < 8; i++)
{
for (int k = 0; k < n[i]; k++)
{
// Compute orientation offset so that groups
// of points on each circles become staggered
//
double beta = Math.PI / n[i] * (i % 2);
double alpha = k * 2 * Math.PI / n[i] + beta + theta;
// Add the point to the pattern look-up table
PatternPoint point = new PatternPoint(
(float)(radius[i] * Math.cos(alpha) * scalingFactor * scale),
(float)(radius[i] * Math.sin(alpha) * scalingFactor * scale),
(float)(sigma[i] * scalingFactor * scale));
lookupTable[scaleIdx * Orientations * Points
+ orientationIdx * Points + pointIdx] = point;
// adapt the sizeList if necessary
int sizeMax = (int)Math.ceil((radius[i] + sigma[i]) * scalingFactor * scale) + 1;
if (patternSizes[scaleIdx] < sizeMax)
patternSizes[scaleIdx] = sizeMax;
pointIdx++;
}
}
}
}
for (int i = 0; i < 45; i++) {
orientationPairs[i] = new OrientationPair();
}
// build the list of orientation pairs
orientationPairs[0].i = 0; orientationPairs[0].j = 3; orientationPairs[1].i = 1; orientationPairs[1].j = 4; orientationPairs[2].i = 2; orientationPairs[2].j = 5;
orientationPairs[3].i = 0; orientationPairs[3].j = 2; orientationPairs[4].i = 1; orientationPairs[4].j = 3; orientationPairs[5].i = 2; orientationPairs[5].j = 4;
orientationPairs[6].i = 3; orientationPairs[6].j = 5; orientationPairs[7].i = 4; orientationPairs[7].j = 0; orientationPairs[8].i = 5; orientationPairs[8].j = 1;
orientationPairs[9].i = 6; orientationPairs[9].j = 9; orientationPairs[10].i = 7; orientationPairs[10].j = 10; orientationPairs[11].i = 8; orientationPairs[11].j = 11;
orientationPairs[12].i = 6; orientationPairs[12].j = 8; orientationPairs[13].i = 7; orientationPairs[13].j = 9; orientationPairs[14].i = 8; orientationPairs[14].j = 10;
orientationPairs[15].i = 9; orientationPairs[15].j = 11; orientationPairs[16].i = 10; orientationPairs[16].j = 6; orientationPairs[17].i = 11; orientationPairs[17].j = 7;
orientationPairs[18].i = 12; orientationPairs[18].j = 15; orientationPairs[19].i = 13; orientationPairs[19].j = 16; orientationPairs[20].i = 14; orientationPairs[20].j = 17;
orientationPairs[21].i = 12; orientationPairs[21].j = 14; orientationPairs[22].i = 13; orientationPairs[22].j = 15; orientationPairs[23].i = 14; orientationPairs[23].j = 16;
orientationPairs[24].i = 15; orientationPairs[24].j = 17; orientationPairs[25].i = 16; orientationPairs[25].j = 12; orientationPairs[26].i = 17; orientationPairs[26].j = 13;
orientationPairs[27].i = 18; orientationPairs[27].j = 21; orientationPairs[28].i = 19; orientationPairs[28].j = 22; orientationPairs[29].i = 20; orientationPairs[29].j = 23;
orientationPairs[30].i = 18; orientationPairs[30].j = 20; orientationPairs[31].i = 19; orientationPairs[31].j = 21; orientationPairs[32].i = 20; orientationPairs[32].j = 22;
orientationPairs[33].i = 21; orientationPairs[33].j = 23; orientationPairs[34].i = 22; orientationPairs[34].j = 18; orientationPairs[35].i = 23; orientationPairs[35].j = 19;
orientationPairs[36].i = 24; orientationPairs[36].j = 27; orientationPairs[37].i = 25; orientationPairs[37].j = 28; orientationPairs[38].i = 26; orientationPairs[38].j = 29;
orientationPairs[39].i = 30; orientationPairs[39].j = 33; orientationPairs[40].i = 31; orientationPairs[40].j = 34; orientationPairs[41].i = 32; orientationPairs[41].j = 35;
orientationPairs[42].i = 36; orientationPairs[42].j = 39; orientationPairs[43].i = 37; orientationPairs[43].j = 40; orientationPairs[44].i = 38; orientationPairs[44].j = 41;
for (int m = 0; m < orientationPairs.length; m++)
{
float dx = lookupTable[orientationPairs[m].i].x - lookupTable[orientationPairs[m].j].x;
float dy = lookupTable[orientationPairs[m].i].y - lookupTable[orientationPairs[m].j].y;
float norm_sq = (dx * dx + dy * dy);
orientationPairs[m].weight_dx = (int)((dx / (norm_sq)) * 4096.0 + 0.5);
orientationPairs[m].weight_dy = (int)((dy / (norm_sq)) * 4096.0 + 0.5);
}
// build the list of description pairs
ArrayList allPairs = new ArrayList();
for (int i = 1; i < Points; i++)
for (int j = 0; j < i; j++)
allPairs.add(new DescriptionPair(i, j));
for (int i = 0; i < 512; i++) {
descriptionPairs[i] = new DescriptionPair(0, 0);
}
// default selected pairs
for (int i = 0; i < descriptionPairs.length; i++)
descriptionPairs[i] = allPairs.get(CV_FREAK_DEF_PAIRS[i]);
}
class PatternPoint
{
public PatternPoint(float x, float y, float sigma)
{
this.x = x;
this.y = y;
this.sigma = sigma;
}
public float x;
public float y;
public float sigma;
};
class DescriptionPair
{
public int i; // index of the first point
public int j; // index of the second point
public DescriptionPair(int i, int j)
{
this.i = i;
this.j = j;
}
};
class OrientationPair
{
public OrientationPair() {
this.i = 0;
this.j = 0;
}
public int i; // index of the first point
public int j; // index of the second point
public int weight_dx; // dx/(norm_sq))*4096
public int weight_dy; // dy/(norm_sq))*4096
};
static int[] CV_FREAK_DEF_PAIRS = // default pairs
{
404,431,818,511,181,52,311,874,774,543,719,230,417,205,11,
560,149,265,39,306,165,857,250,8,61,15,55,717,44,412,
592,134,761,695,660,782,625,487,549,516,271,665,762,392,178,
796,773,31,672,845,548,794,677,654,241,831,225,238,849,83,
691,484,826,707,122,517,583,731,328,339,571,475,394,472,580,
381,137,93,380,327,619,729,808,218,213,459,141,806,341,95,
382,568,124,750,193,749,706,843,79,199,317,329,768,198,100,
466,613,78,562,783,689,136,838,94,142,164,679,219,419,366,
418,423,77,89,523,259,683,312,555,20,470,684,123,458,453,833,
72,113,253,108,313,25,153,648,411,607,618,128,305,232,301,84,
56,264,371,46,407,360,38,99,176,710,114,578,66,372,653,
129,359,424,159,821,10,323,393,5,340,891,9,790,47,0,175,346,
236,26,172,147,574,561,32,294,429,724,755,398,787,288,299,
769,565,767,722,757,224,465,723,498,467,235,127,802,446,233,
544,482,800,318,16,532,801,441,554,173,60,530,713,469,30,
212,630,899,170,266,799,88,49,512,399,23,500,107,524,90,
194,143,135,192,206,345,148,71,119,101,563,870,158,254,214,
276,464,332,725,188,385,24,476,40,231,620,171,258,67,109,
844,244,187,388,701,690,50,7,850,479,48,522,22,154,12,659,
736,655,577,737,830,811,174,21,237,335,353,234,53,270,62,
182,45,177,245,812,673,355,556,612,166,204,54,248,365,226,
242,452,700,685,573,14,842,481,468,781,564,416,179,405,35,
819,608,624,367,98,643,448,2,460,676,440,240,130,146,184,
185,430,65,807,377,82,121,708,239,310,138,596,730,575,477,
851,797,247,27,85,586,307,779,326,494,856,324,827,96,748,
13,397,125,688,702,92,293,716,277,140,112,4,80,855,839,1,
413,347,584,493,289,696,19,751,379,76,73,115,6,590,183,734,
197,483,217,344,330,400,186,243,587,220,780,200,793,246,824,
41,735,579,81,703,322,760,720,139,480,490,91,814,813,163,
152,488,763,263,425,410,576,120,319,668,150,160,302,491,515,
260,145,428,97,251,395,272,252,18,106,358,854,485,144,550,
131,133,378,68,102,104,58,361,275,209,697,582,338,742,589,
325,408,229,28,304,191,189,110,126,486,211,547,533,70,215,
670,249,36,581,389,605,331,518,442,822
};
}
Ads help maintain this website.