// Construct descriptor vector for this interest point void SurfDescriptor::GetDescriptor(IPoint &ip, bool bUpright, bool bExtended) { int sample_x, sample_y, count = 0; int i = 0, ix = 0, j = 0, jx = 0, xs = 0, ys = 0; float dx, dy, mdx, mdy, co, si; float dx_yn, mdx_yn, dy_xn, mdy_xn; float gauss_s1 = (float)0, gauss_s2 = (float)0; float rx = (float)0, ry = (float)0, rrx = (float)0, rry = (float)0, len = (float)0; float cx = (float)-0.5, cy = (float)0; //Subregion centers for the 4x4 gaussian weighting // Get rounded InterestPoint data int X = (int)floor(ip.x + (float)0.5); int Y = (int)floor(ip.y + (float)0.5); int S = (int)floor(ip.scale + (float)0.5); // Allocate descriptor memory ip.SetDescriptorLength(64); if (bUpright) { co = 1; si = 0; } else { co = (float)cos(ip.orientation); si = (float)sin(ip.orientation); } //Calculate descriptor for this interest point i = -8; while (i < 12) { j = -8; i = i - 4; cx += (float)1; cy = (float)-0.5; while (j < 12) { cy += (float)1; j = j - 4; ix = i + 5; jx = j + 5; dx = dy = mdx = mdy = (float)0; dx_yn = mdx_yn = dy_xn = mdy_xn = (float)0; xs = (int)floor(X + (-jx * S * si + ix * S * co) + (float)0.5); ys = (int)floor(Y + (jx * S * co + ix * S * si) + (float)0.5); // zero the responses dx = dy = mdx = mdy = (float)0; dx_yn = mdx_yn = dy_xn = mdy_xn = (float)0; for (int k = i; k < i + 9; ++k) { for (int l = j; l < j + 9; ++l) { //Get coords of sample point on the rotated axis sample_x = (int)floor(X + (-l * S * si + k * S * co) + (float)0.5); sample_y = (int)floor(Y + (l * S * co + k * S * si) + (float)0.5); //Get the gaussian weighted x and y responses gauss_s1 = Gaussian(xs - sample_x, ys - sample_y, (float)2.5 * S); rx = (float)img->HaarX(sample_y, sample_x, 2 * S); ry = (float)img->HaarY(sample_y, sample_x, 2 * S); //Get the gaussian weighted x and y responses on rotated axis rrx = gauss_s1 * (-rx * si + ry * co); rry = gauss_s1 * (rx * co + ry * si); if (bExtended) { // split x responses for different signs of y if (rry >= 0) { dx += rrx; mdx += fabs(rrx); } else { dx_yn += rrx; mdx_yn += fabs(rrx); } // split y responses for different signs of x if (rrx >= 0) { dy += rry; mdy += fabs(rry); } else { dy_xn += rry; mdy_xn += fabs(rry); } } else { dx += rrx; dy += rry; mdx += fabs(rrx); mdy += fabs(rry); } } } //Add the values to the descriptor vector gauss_s2 = Gaussian(cx - (float)2, cy - (float)2, (float)1.5); ip.descriptor[count++] = dx * gauss_s2; ip.descriptor[count++] = dy * gauss_s2; ip.descriptor[count++] = mdx * gauss_s2; ip.descriptor[count++] = mdy * gauss_s2; // add the extended components if (bExtended) { ip.descriptor[count++] = dx_yn * gauss_s2; ip.descriptor[count++] = dy_xn * gauss_s2; ip.descriptor[count++] = mdx_yn * gauss_s2; ip.descriptor[count++] = mdy_xn * gauss_s2; } len += (dx * dx + dy * dy + mdx * mdx + mdy * mdy + dx_yn + dy_xn + mdx_yn + mdy_xn) * gauss_s2 * gauss_s2; j += 9; } i += 9; } //Convert to Unit Vector len = (float)sqrt((double)len); if (len > 0) { for (int d = 0; d < ip.descriptorLength; ++d) { ip.descriptor[d] /= len; } } }