1 | initial version |
Here a parts of the code that use the scale and image size
void FREAK::buildPattern() { if( patternScale == patternScale0 && nOctaves == nOctaves0 && !patternLookup.empty() ) return;
nOctaves0 = nOctaves;
patternScale0 = **patternScale**;
patternLookup.resize(FREAK_NB_SCALES*FREAK_NB_ORIENTATION*FREAK_NB_POINTS);
double scaleStep = pow(2.0, (double)(nOctaves)/FREAK_NB_SCALES ); // 2 ^ ( (nOctaves-1) /nbScales)
double scalingFactor, alpha, beta, theta = 0;
// pattern definition, radius normalized to 1.0 (outer point position+sigma=1.0)
const int n[8] = {6,6,6,6,6,6,6,1}; // number of points on each concentric circle (from outer to inner)
const double bigR(2.0/3.0); // bigger radius
const double smallR(2.0/24.0); // smaller radius
const double unitSpace( (bigR-smallR)/21.0 ); // define spaces between concentric circles (from center to outer: 1,2,3,4,5,6)
// radii of the concentric cirles (from outer to inner)
const double radius[8] = {bigR, bigR-6*unitSpace, bigR-11*unitSpace, bigR-15*unitSpace, bigR-18*unitSpace, bigR-20*unitSpace, smallR, 0.0};
// sigma of pattern points (each group of 6 points on a concentric cirle has the same sigma)
const double sigma[8] = {radius[0]/2.0, radius[1]/2.0, radius[2]/2.0,
radius[3]/2.0, radius[4]/2.0, radius[5]/2.0,
radius[6]/2.0, radius[6]/2.0
};
// fill the lookup table
for( int scaleIdx=0; scaleIdx < FREAK_NB_SCALES; ++scaleIdx ) {
patternSizes[scaleIdx] = 0; // proper initialization
scalingFactor = pow(scaleStep,scaleIdx); //scale of the pattern, scaleStep ^ scaleIdx
for( int orientationIdx = 0; orientationIdx < FREAK_NB_ORIENTATION; ++orientationIdx ) {
theta = double(orientationIdx)* 2*CV_PI/double(FREAK_NB_ORIENTATION); // orientation of the pattern
int pointIdx = 0;
PatternPoint* patternLookupPtr = &patternLookup[0];
for( size_t i = 0; i < 8; ++i ) {
for( int k = 0 ; k < n[i]; ++k ) {
beta = CV_PI/n[i] * (i%2); // orientation offset so that groups of points on each circles are staggered
alpha = double(k)* 2*CV_PI/double(n[i])+beta+theta;
// add the point to the look-up table
PatternPoint& point = patternLookupPtr[ scaleIdx*FREAK_NB_ORIENTATION*FREAK_NB_POINTS+orientationIdx*FREAK_NB_POINTS+pointIdx ];
point.x = static_cast<float>(radius[i] * cos(alpha) * scalingFactor * **patternScale**);
point.y = static_cast<float>(radius[i] * sin(alpha) * scalingFactor * **patternScale**);
point.sigma = static_cast<float>(sigma[i] * scalingFactor * **patternScale**);
// adapt the sizeList if necessary
const int sizeMax = static_cast<int>(ceil((radius[i]+sigma[i])*scalingFactor* **patternScale**)) + 1;
if( patternSizes[scaleIdx] < sizeMax )
**patternSizes**[scaleIdx] = sizeMax;
++pointIdx;
}
}
}
}
Affter build the pattern a call off function is done to extra the descriptor
void FREAK::computeImpl( const Mat& image, std::vector<keypoint>& keypoints, Mat& descriptors )
According to the parameters setup in the constructor
if( scaleNormalized ) { for( size_t k = keypoints.size(); k--; ) { //Is k non-zero? If so, decrement it and continue" kpScaleIdx[k] = max( (int)(log(keypoints[k].size/FREAK_SMALLEST_KP_SIZE)*sizeCst+0.5) ,0); if( kpScaleIdx[k] >= FREAK_NB_SCALES ) kpScaleIdx[k] = FREAK_NB_SCALES-1;
if( keypoints[k].pt.x <= patternSizes[kpScaleIdx[k]] || //check if the description at this specific position and scale fits inside the image
keypoints[k].pt.y <= patternSizes[kpScaleIdx[k]] ||
keypoints[k].pt.x >= **image.cols-patternSizes**[kpScaleIdx[k]] ||
keypoints[k].pt.y >= **image.rows-patternSizes**[kpScaleIdx[k]]
) {
keypoints.erase(kpBegin+k);
kpScaleIdx.erase(ScaleIdxBegin+k);
}
}
}
else {
const int scIdx = max( (int)(1.0986122886681*sizeCst+0.5) ,0);
for( size_t k = keypoints.size(); k--; ) {
kpScaleIdx[k] = scIdx; **// equivalent to the formule when the scale is normalized with a constant size of keypoints[k].size=3*SMALLEST_KP_SIZE**
if( kpScaleIdx[k] >= FREAK_NB_SCALES ) {
kpScaleIdx[k] = FREAK_NB_SCALES-1;
}
if( keypoints[k].pt.x <= patternSizes[kpScaleIdx[k]] ||
keypoints[k].pt.y <= patternSizes[kpScaleIdx[k]] ||
keypoints[k].pt.x >= **image.cols-patternSizes**[kpScaleIdx[k]] ||
keypoints[k].pt.y >= **image.rows-patternSizes**[kpScaleIdx[k]]
) {
keypoints.erase(kpBegin+k);
kpScaleIdx.erase(ScaleIdxBegin+k);
}
}
}
for( size_t k = keypoints.size(); k--; ) {
// estimate orientation (gradient)
if( !orientationNormalized ) {
thetaIdx = 0; // assign 0° to all keypoints
keypoints[k].angle = 0.0;
}
else {
// get the points intensity value in the un-rotated pattern
for( int i = FREAK_NB_POINTS; i--; ) {
pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], 0, i);
}
direction0 = 0;
direction1 = 0;
for( int m = 45; m--; ) {
//iterate through the orientation pairs
const int delta = (pointsValue[ orientationPairs[m].i ]-pointsValue[ orientationPairs[m].j ]);
direction0 += delta*(orientationPairs[m].weight_dx)/2048;
direction1 += delta*(orientationPairs[m].weight_dy)/2048;
}
keypoints[k].angle = static_cast<float>(atan2((float)direction1,(float)direction0)*(180.0/CV_PI));//estimate orientation
thetaIdx = int(FREAK_NB_ORIENTATION*keypoints[k].angle*(1/360.0)+0.5);
if( thetaIdx < 0 )
thetaIdx += FREAK_NB_ORIENTATION;
if( thetaIdx >= FREAK_NB_ORIENTATION )
thetaIdx -= FREAK_NB_ORIENTATION;
}
// extract descriptor at the computed orientation
for( int i = FREAK_NB_POINTS; i--; ) {
pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], thetaIdx, i);
}
I hope this helps
2 | No.2 Revision |
Here a parts of the code that use the scale and image sizesize
Note the use off the " patternScale "
void FREAK::buildPattern() { if( patternScale == patternScale0 && nOctaves == nOctaves0 && !patternLookup.empty() ) return;
nOctaves0 = nOctaves;
patternScale0 = **patternScale**;
"***patternScale***";
patternLookup.resize(FREAK_NB_SCALES*FREAK_NB_ORIENTATION*FREAK_NB_POINTS);
double scaleStep = pow(2.0, (double)(nOctaves)/FREAK_NB_SCALES ); // 2 ^ ( (nOctaves-1) /nbScales)
double scalingFactor, alpha, beta, theta = 0;
// pattern definition, radius normalized to 1.0 (outer point position+sigma=1.0)
const int n[8] = {6,6,6,6,6,6,6,1}; // number of points on each concentric circle (from outer to inner)
const double bigR(2.0/3.0); // bigger radius
const double smallR(2.0/24.0); // smaller radius
const double unitSpace( (bigR-smallR)/21.0 ); // define spaces between concentric circles (from center to outer: 1,2,3,4,5,6)
// radii of the concentric cirles (from outer to inner)
const double radius[8] = {bigR, bigR-6*unitSpace, bigR-11*unitSpace, bigR-15*unitSpace, bigR-18*unitSpace, bigR-20*unitSpace, smallR, 0.0};
// sigma of pattern points (each group of 6 points on a concentric cirle has the same sigma)
const double sigma[8] = {radius[0]/2.0, radius[1]/2.0, radius[2]/2.0,
radius[3]/2.0, radius[4]/2.0, radius[5]/2.0,
radius[6]/2.0, radius[6]/2.0
};
// fill the lookup table
for( int scaleIdx=0; scaleIdx < FREAK_NB_SCALES; ++scaleIdx ) {
patternSizes[scaleIdx] = 0; // proper initialization
scalingFactor = pow(scaleStep,scaleIdx); //scale of the pattern, scaleStep ^ scaleIdx
for( int orientationIdx = 0; orientationIdx < FREAK_NB_ORIENTATION; ++orientationIdx ) {
theta = double(orientationIdx)* 2*CV_PI/double(FREAK_NB_ORIENTATION); // orientation of the pattern
int pointIdx = 0;
PatternPoint* patternLookupPtr = &patternLookup[0];
for( size_t i = 0; i < 8; ++i ) {
for( int k = 0 ; k < n[i]; ++k ) {
beta = CV_PI/n[i] * (i%2); // orientation offset so that groups of points on each circles are staggered
alpha = double(k)* 2*CV_PI/double(n[i])+beta+theta;
// add the point to the look-up table
PatternPoint& point = patternLookupPtr[ scaleIdx*FREAK_NB_ORIENTATION*FREAK_NB_POINTS+orientationIdx*FREAK_NB_POINTS+pointIdx ];
point.x = static_cast<float>(radius[i] * cos(alpha) * scalingFactor * **patternScale**);
***patternScale***);
point.y = static_cast<float>(radius[i] * sin(alpha) * scalingFactor * **patternScale**);
***patternScale***);
point.sigma = static_cast<float>(sigma[i] * scalingFactor * **patternScale**);
***patternScale***);
// adapt the sizeList if necessary
const int sizeMax = static_cast<int>(ceil((radius[i]+sigma[i])*scalingFactor* **patternScale**)) ***patternScale***)) + 1;
if( patternSizes[scaleIdx] < sizeMax )
**patternSizes**[scaleIdx] = sizeMax;
++pointIdx;
}
}
}
}
Affter build the pattern a call off function computeImpl() is done to extra extract the descriptor
void FREAK::computeImpl( const Mat& image, std::vector<keypoint>& keypoints, Mat& descriptors ) {......
According "According to the parameters setup in the constructorconstructor"
if( scaleNormalized ) { for( size_t k = keypoints.size(); k--; ) { //Is k non-zero? If so, decrement it and continue" kpScaleIdx[k] = max( (int)(log(keypoints[k].size/FREAK_SMALLEST_KP_SIZE)*sizeCst+0.5) ,0); if( kpScaleIdx[k] >= FREAK_NB_SCALES ) kpScaleIdx[k] = FREAK_NB_SCALES-1;
if( keypoints[k].pt.x <= patternSizes[kpScaleIdx[k]] || ||
" //check if the description at this specific position and scale fits inside the image
image "
keypoints[k].pt.y <= patternSizes[kpScaleIdx[k]] ||
keypoints[k].pt.x >= **image.cols-patternSizes**[kpScaleIdx[k]] image.cols-patternSizes[kpScaleIdx[k]] ||
keypoints[k].pt.y >= **image.rows-patternSizes**[kpScaleIdx[k]]
image.rows-patternSizes[kpScaleIdx[k]]
) {
keypoints.erase(kpBegin+k);
kpScaleIdx.erase(ScaleIdxBegin+k);
}
}
}
else {
const int scIdx = max( (int)(1.0986122886681*sizeCst+0.5) (int)(1.0986122886681sizeCst+0.5) ,0);
for( size_t k = keypoints.size(); k--; ) {
kpScaleIdx[k] = scIdx; **// equivalent "//equivalent to the formule when the scale is normalized with a constant size of keypoints[k].size=3*SMALLEST_KP_SIZE**
// keypoints[k].size=3SMALLEST_KP_SIZE**
kpScaleIdx[k] = scIdx;
if( kpScaleIdx[k] >= FREAK_NB_SCALES ) {
kpScaleIdx[k] = FREAK_NB_SCALES-1;
}
if( keypoints[k].pt.x <= patternSizes[kpScaleIdx[k]] ||
keypoints[k].pt.y <= patternSizes[kpScaleIdx[k]] ||
keypoints[k].pt.x >= **image.cols-patternSizes**[kpScaleIdx[k]] ||
" **image.cols-patternSizes** [kpScaleIdx[k]] ||"
keypoints[k].pt.y >= **image.rows-patternSizes**[kpScaleIdx[k]]
" **image.rows-patternSizes**[kpScaleIdx[k]]"
) {
keypoints.erase(kpBegin+k);
kpScaleIdx.erase(ScaleIdxBegin+k);
}
}
}
for( size_t k = keypoints.size(); k--; ) {
// estimate orientation (gradient)
if( !orientationNormalized ) {
thetaIdx = 0; // assign 0° to all keypoints
keypoints[k].angle = 0.0;
}
else {
// get the points intensity value in the un-rotated pattern
for( int i = FREAK_NB_POINTS; i--; ) {
pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], 0, i);
}
direction0 = 0;
direction1 = 0;
for( int m = 45; m--; ) {
//iterate through the orientation pairs
const int delta = (pointsValue[ orientationPairs[m].i ]-pointsValue[ orientationPairs[m].j ]);
direction0 += delta*(orientationPairs[m].weight_dx)/2048;
direction1 += delta*(orientationPairs[m].weight_dy)/2048;
}
keypoints[k].angle = static_cast<float>(atan2((float)direction1,(float)direction0)*(180.0/CV_PI));//estimate orientation
thetaIdx = int(FREAK_NB_ORIENTATION*keypoints[k].angle*(1/360.0)+0.5);
if( thetaIdx < 0 )
thetaIdx += FREAK_NB_ORIENTATION;
if( thetaIdx >= FREAK_NB_ORIENTATION )
thetaIdx -= FREAK_NB_ORIENTATION;
}
// extract descriptor at the computed orientation
for( int i = FREAK_NB_POINTS; i--; ) {
pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], thetaIdx, i);
}
I hope this helps
3 | No.3 Revision |
Here a parts of the code that use the scale and image size Note the use off the " patternScale "
void FREAK::buildPattern() { if( patternScale == patternScale0 && nOctaves == nOctaves0 && !patternLookup.empty() ) return;
nOctaves0 = nOctaves;
patternScale0 = "***patternScale***";
patternLookup.resize(FREAK_NB_SCALES*FREAK_NB_ORIENTATION*FREAK_NB_POINTS);
double scaleStep = pow(2.0, (double)(nOctaves)/FREAK_NB_SCALES ); // 2 ^ ( (nOctaves-1) /nbScales)
double scalingFactor, alpha, beta, theta = 0;
// pattern definition, radius normalized to 1.0 (outer point position+sigma=1.0)
const int n[8] = {6,6,6,6,6,6,6,1}; // number of points on each concentric circle (from outer to inner)
const double bigR(2.0/3.0); // bigger radius
const double smallR(2.0/24.0); // smaller radius
const double unitSpace( (bigR-smallR)/21.0 ); // define spaces between concentric circles (from center to outer: 1,2,3,4,5,6)
// radii of the concentric cirles (from outer to inner)
const double radius[8] = {bigR, bigR-6*unitSpace, bigR-11*unitSpace, bigR-15*unitSpace, bigR-18*unitSpace, bigR-20*unitSpace, smallR, 0.0};
// sigma of pattern points (each group of 6 points on a concentric cirle has the same sigma)
const double sigma[8] = {radius[0]/2.0, radius[1]/2.0, radius[2]/2.0,
radius[3]/2.0, radius[4]/2.0, radius[5]/2.0,
radius[6]/2.0, radius[6]/2.0
};
// fill the lookup table
for( int scaleIdx=0; scaleIdx < FREAK_NB_SCALES; ++scaleIdx ) {
patternSizes[scaleIdx] = 0; // proper initialization
scalingFactor = pow(scaleStep,scaleIdx); //scale of the pattern, scaleStep ^ scaleIdx
for( int orientationIdx = 0; orientationIdx < FREAK_NB_ORIENTATION; ++orientationIdx ) {
theta = double(orientationIdx)* 2*CV_PI/double(FREAK_NB_ORIENTATION); // orientation of the pattern
int pointIdx = 0;
PatternPoint* patternLookupPtr = &patternLookup[0];
for( size_t i = 0; i < 8; ++i ) {
for( int k = 0 ; k < n[i]; ++k ) {
beta = CV_PI/n[i] * (i%2); // orientation offset so that groups of points on each circles are staggered
alpha = double(k)* 2*CV_PI/double(n[i])+beta+theta;
// add the point to the look-up table
PatternPoint& point = patternLookupPtr[ scaleIdx*FREAK_NB_ORIENTATION*FREAK_NB_POINTS+orientationIdx*FREAK_NB_POINTS+pointIdx ];
point.x = static_cast<float>(radius[i] * cos(alpha) * scalingFactor * ***patternScale***);
"***patternScale***");
point.y = static_cast<float>(radius[i] * sin(alpha) * scalingFactor * ***patternScale***);
"***patternScale***");
point.sigma = static_cast<float>(sigma[i] * scalingFactor * ***patternScale***);
"***patternScale***");
// adapt the sizeList if necessary
const int sizeMax = static_cast<int>(ceil((radius[i]+sigma[i])*scalingFactor* ***patternScale***)) "***patternScale***")) + 1;
if( patternSizes[scaleIdx] < sizeMax )
**patternSizes**[scaleIdx] = sizeMax;
++pointIdx;
}
}
}
}
Affter build the pattern a call off function computeImpl() is done to extract the descriptor
void FREAK::computeImpl( const Mat& image, std::vector<keypoint>& keypoints, Mat& descriptors ) {......
"According to the parameters setup in the constructor"
if( scaleNormalized ) { for( size_t k = keypoints.size(); k--; ) { //Is k non-zero? If so, decrement it and continue" kpScaleIdx[k] = max( (int)(log(keypoints[k].size/FREAK_SMALLEST_KP_SIZE)*sizeCst+0.5) ,0); if( kpScaleIdx[k] >= FREAK_NB_SCALES ) kpScaleIdx[k] = FREAK_NB_SCALES-1;
if( keypoints[k].pt.x <= patternSizes[kpScaleIdx[k]] ||
" //check if the description at this specific position and scale fits inside the image "
keypoints[k].pt.y <= patternSizes[kpScaleIdx[k]] ||
keypoints[k].pt.x >= "image.cols-patternSizes[kpScaleIdx[k]] [kpScaleIdx[k]]" ||
keypoints[k].pt.y >= "image.rows-patternSizes[kpScaleIdx[k]]
[kpScaleIdx[k]]"
) {
keypoints.erase(kpBegin+k);
kpScaleIdx.erase(ScaleIdxBegin+k);
}
}
}
else {
const int scIdx = max( (int)(1.0986122886681sizeCst+0.5) ,0);
for( size_t k = keypoints.size(); k--; ) {
"//equivalent to the formule when the scale is normalized with a constant size of
// keypoints[k].size=3SMALLEST_KP_SIZE**
kpScaleIdx[k] = scIdx;
if( kpScaleIdx[k] >= FREAK_NB_SCALES ) {
kpScaleIdx[k] = FREAK_NB_SCALES-1;
}
if( keypoints[k].pt.x <= patternSizes[kpScaleIdx[k]] ||
keypoints[k].pt.y <= patternSizes[kpScaleIdx[k]] ||
keypoints[k].pt.x >= " **image.cols-patternSizes** [kpScaleIdx[k]] ||"
" ||
keypoints[k].pt.y >= " **image.rows-patternSizes**[kpScaleIdx[k]]"
) {
keypoints.erase(kpBegin+k);
kpScaleIdx.erase(ScaleIdxBegin+k);
}
}
}
for( size_t k = keypoints.size(); k--; ) {
// estimate orientation (gradient)
if( !orientationNormalized ) {
thetaIdx = 0; // assign 0° to all keypoints
keypoints[k].angle = 0.0;
}
else {
// get the points intensity value in the un-rotated pattern
for( int i = FREAK_NB_POINTS; i--; ) {
pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], 0, i);
}
direction0 = 0;
direction1 = 0;
for( int m = 45; m--; ) {
//iterate through the orientation pairs
const int delta = (pointsValue[ orientationPairs[m].i ]-pointsValue[ orientationPairs[m].j ]);
direction0 += delta*(orientationPairs[m].weight_dx)/2048;
direction1 += delta*(orientationPairs[m].weight_dy)/2048;
}
keypoints[k].angle = static_cast<float>(atan2((float)direction1,(float)direction0)*(180.0/CV_PI));//estimate orientation
thetaIdx = int(FREAK_NB_ORIENTATION*keypoints[k].angle*(1/360.0)+0.5);
if( thetaIdx < 0 )
thetaIdx += FREAK_NB_ORIENTATION;
if( thetaIdx >= FREAK_NB_ORIENTATION )
thetaIdx -= FREAK_NB_ORIENTATION;
}
// extract descriptor at the computed orientation
for( int i = FREAK_NB_POINTS; i--; ) {
pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], thetaIdx, i);
}
I hope this helps