/* Alternate approach to return an orientation for a keypoint, as described in the PhD thesis of Krystian Mikolajczyk. This is done by creating a Gaussian weighted average of the gradient directions in the region. The result is in the range of -PII to PII. This was found not to work as well, but is included so that comparisons can continue to be done. */ KKeypoint AssignOriAvg(Image grad, Image ori, float octSize, float octScale, float octRow, float octCol, KKeypoint keys) { int r, c, irow, icol, rows, cols, radius; float gval, sigma, distsq, weight, angle, xvec = 0.0, yvec = 0.0; rows = grad->rows; cols = grad->cols; irow = (int) (octRow+0.5); icol = (int) (octCol+0.5); /* Look at pixels within 3 sigma around the point and put their Gaussian weighted vector values in (xvec, yvec). */ sigma = OriSigma * octScale; radius = (int) (3.0 * sigma); for (r = irow - radius; r <= irow + radius; r++) for (c = icol - radius; c <= icol + radius; c++) if (r >= 0 && c >= 0 && r < rows && c < cols) { gval = grad->pixels[r][c]; distsq = (r - octRow) * (r - octRow) + (c - octCol) * (c - octCol); if (distsq <= radius * radius) { weight = exp(- distsq / (2.0 * sigma * sigma)); /* Angle is in range of -PII to PII. */ angle = ori->pixels[r][c]; xvec += gval * cos(angle); yvec += gval * sin(angle); } } /* atan2 returns angle in range [-PII,PII]. */ angle = atan2(yvec, xvec); return MakeKeypoint(grad, ori, octSize, octScale, octRow, octCol, angle, keys); }
/* Assign an orientation to this keypoint. This is done by creating a Gaussian weighted histogram of the gradient directions in the region. The histogram is smoothed and the largest peak selected. The results are in the range of -PI to PI. */ void AssignOriHist( const flimage& grad, float octSize, float octScale, float octRow, float octCol,keypointslist& keys,siftPar &par) { int bin, prev, next; float* hist = new float[par.OriBins]; float distsq, dif, weight, angle, interp; float radius2, sigma2; int row = (int) (octRow+0.5), col = (int) (octCol+0.5), rows = grad.h, cols = grad.w; for (int i = 0; i < par.OriBins; i++) hist[i] = 0.0; /* Look at pixels within 3 sigma around the point and sum their Gaussian weighted gradient magnitudes into the histogram. */ float sigma = par.OriSigma * octScale; int radius = (int) (sigma * 3.0); int rmin = std::max(0,row-radius); int cmin = std::max(0,col-radius); int rmax = std::min(row+radius,rows-2); int cmax = std::min(col+radius,cols-2); radius2 = (float)(radius * radius); sigma2 = 2.0f*sigma*sigma; for (int r = rmin; r <= rmax; r++) { for (int c = cmin; c <= cmax; c++) { dif = (r - octRow); distsq = dif*dif; dif = (c - octCol); distsq += dif*dif; const float* g=grad.pixel(c,r); if (g[0] > 0.0 && distsq < radius2 + 0.5) { weight = exp(- distsq / sigma2); /* Ori is in range of -PI to PI. */ bin = (int) (par.OriBins * (g[1] + M_PI + 0.001) / (2.0 * M_PI)); assert(bin >= 0 && bin <= par.OriBins); bin = std::min(bin, par.OriBins - 1); hist[bin] += weight * g[0]; } } } /* Apply smoothing 6 times for accurate Gaussian approximation. */ for (int i = 0; i < 6; i++) SmoothHistogram(hist, par.OriBins); /* Find maximum value in histogram. */ float maxval = 0.0; for (int i = 0; i < par.OriBins; i++) if (hist[i] > maxval) maxval = hist[i]; /* Look for each local peak in histogram. If value is within par.OriHistThresh of maximum value, then generate a keypoint. */ for (int i = 0; i < par.OriBins; i++) { prev = (i == 0 ? par.OriBins - 1 : i - 1); next = (i == par.OriBins - 1 ? 0 : i + 1); if ( hist[i] > hist[prev] && hist[i] > hist[next] && hist[i] >= par.OriHistThresh * maxval ) { /* Use parabolic fit to interpolate peak location from 3 samples. Set angle in range -PI to PI. */ interp = InterpPeak(hist[prev], hist[i], hist[next]); angle = 2.0f * M_PI * (i + 0.5f + interp) / (float)par.OriBins - M_PI; assert(angle >= -M_PI && angle <= M_PI); if (DEBUG) printf("angle selected: %f \t location: (%f,%f)\n", angle, octRow, octCol); /* Create a keypoint with this orientation. */ MakeKeypoint( grad, octSize, octScale, octRow, octCol, angle, keys,par); } } delete [] hist; }
/* Assign an orientation to this keypoint. This is done by creating a Gaussian weighted histogram of the gradient directions in the region. The histogram is smoothed and the largest peak selected. The results are in the range of -PII to PII. */ KKeypoint AssignOriHist(Image grad, Image ori, float octSize, float octScale, float octRow, float octCol, KKeypoint keys) { int i, r, c, row, col, rows, cols, radius, bin, prev, next; float hist[OriBins], distsq, gval, weight, angle, sigma, interp, maxval = 0.0; row = (int) (octRow+0.5); col = (int) (octCol+0.5); rows = grad->rows; cols = grad->cols; for (i = 0; i < OriBins; i++) hist[i] = 0.0; /* Look at pixels within 3 sigma around the point and sum their Gaussian weighted gradient magnitudes into the histogram. */ sigma = OriSigma * octScale; radius = (int) (sigma * 3.0); for (r = row - radius; r <= row + radius; r++) for (c = col - radius; c <= col + radius; c++) /* Do not use last row or column, which are not valid. */ if (r >= 0 && c >= 0 && r < rows - 2 && c < cols - 2) { gval = grad->pixels[r][c]; distsq = (r - octRow) * (r - octRow) + (c - octCol) * (c - octCol); if (gval > 0.0 && distsq < radius * radius + 0.5) { weight = exp(- distsq / (2.0 * sigma * sigma)); /* Ori is in range of -PII to PII. */ angle = ori->pixels[r][c]; bin = (int) (OriBins * (angle + PII + 0.001) / (2.0 * PII)); assert(bin >= 0 && bin <= OriBins); bin = MIN_(bin, OriBins - 1); hist[bin] += weight * gval; } } /* Apply circular smoothing 6 times for accurate Gaussian approximation. */ for (i = 0; i < 6; i++) SmoothHistogram(hist, OriBins); /* Find maximum value in histogram. */ for (i = 0; i < OriBins; i++) if (hist[i] > maxval) maxval = hist[i]; /* Look for each local peak in histogram. If value is within OriHistThresh of maximum value, then generate a keypoint. */ for (i = 0; i < OriBins; i++) { prev = (i == 0 ? OriBins - 1 : i - 1); next = (i == OriBins - 1 ? 0 : i + 1); if (hist[i] > hist[prev] && hist[i] > hist[next] && hist[i] >= OriHistThresh * maxval) { /* Use parabolic fit to interpolate peak location from 3 samples. Set angle in range -PII to PII. */ interp = InterpPeak(hist[prev], hist[i], hist[next]); angle = 2.0 * PII * (i + 0.5 + interp) / OriBins - PII; assert(angle >= -PII && angle <= PII); /* Create a keypoint with this orientation. */ keys = MakeKeypoint(grad, ori, octSize, octScale, octRow, octCol, angle, keys); } } return keys; }