/** Use kP given */ descriptor* makeDescriptor(imageIntegral* imgInt,keyPoint* pC) { float scale=pC->scale; descriptor* desc=new descriptor(); // Let's divide in a 4x4 zone the space around the interest point float cosA=cosf(pC->orientation); float sinA=sinf(pC->orientation); float norm=0; float u,v; float gauss,responseU,responseV,responseX,responseY; //We divide in 16 sectors for(int i=0;i<4;i++) { for(int j=0;j<4;j++) { (desc->list[4*i+j]).sumDx=0; (desc->list[4*i+j]).sumAbsDx=0; (desc->list[4*i+j]).sumDy=0; (desc->list[4*i+j]).sumAbsDy=0; // Then each 4x4 becomes a 5x5 zone for(int k=0;k<5;k++) { for(int l=0;l<5;l++) { u=(pC->x+scale*(cosA*((i-2)*5+k+0.5)-sinA*((j-2)*5+l+0.5)));//-0.5 is here to center pixel v=(pC->y+scale*(sinA*((i-2)*5+k+0.5)+cosA*((j-2)*5+l+0.5))); responseX=haarX(imgInt,u,v,fround(scale) ); responseY=haarY(imgInt,u,v,fround(scale)); //We use a gaussian to weight gauss=gaussian(((i-2)*5+k+0.5),((j-2)*5+l+0.5),3.3f); responseU = gauss*( -responseX*sinA + responseY*cosA); responseV = gauss*(responseX*cosA + responseY*sinA); (desc->list[4*i+j]).sumDx+=responseU; (desc->list[4*i+j]).sumAbsDx+=absval(responseU); (desc->list[4*i+j]).sumDy+=responseV; (desc->list[4*i+j]).sumAbsDy+=absval(responseV); } } //We compute the norm of the vector norm+=(desc->list[4*i+j]).sumAbsDx*(desc->list[4*i+j]).sumAbsDx+(desc->list[4*i+j]).sumAbsDy*(desc->list[4*i+j]).sumAbsDy+((desc->list[4*i+j]).sumDx*(desc->list[4*i+j]).sumDx+(desc->list[4*i+j]).sumDy*(desc->list[4*i+j]).sumDy); } } //Then we normalized it. norm=sqrtf(norm); if(norm!=0) for(int i=0;i<16;i++) { (desc->list[i]).sumDx/=norm; (desc->list[i]).sumAbsDx/=norm; (desc->list[i]).sumDy/=norm; (desc->list[i]).sumAbsDy/=norm; } desc->kP=new keyPoint(pC); return desc; }
//! Get the upright descriptor vector of the provided Ipoint void Surf::getUprightDescriptor() { int y, x, count=0; float scale, *desc, dx, dy, mdx, mdy; float gauss, rx, ry, len = 0.f; Ipoint *ipt = &ipts.at(index); scale = ipt->scale; y = fRound(ipt->y); x = fRound(ipt->x); desc = ipt->descriptor; // Calculate descriptor for this interest point for (int i = -10; i < 10; i+=5) { for (int j = -10; j < 10; j+=5) { dx=dy=mdx=mdy=0; for (int k = i; k < i + 5; ++k) { for (int l = j; l < j + 5; ++l) { // get Gaussian weighted x and y responses gauss = static_cast<float>(gauss33[abs(k)][abs(l)]); rx = gauss * haarX(fRound(k*scale+y), fRound(l*scale+x), 2*fRound(scale)); ry = gauss * haarY(fRound(k*scale+y), fRound(l*scale+x), 2*fRound(scale)); dx += rx; dy += ry; mdx += fabs(rx); mdy += fabs(ry); } } // add the values to the descriptor vector desc[count++] = dx; desc[count++] = dy; desc[count++] = mdx; desc[count++] = mdy; // store the current length^2 of the vector len += dx*dx + dy*dy + mdx*mdx + mdy*mdy; } } // convert to unit vector len = sqrt(len); for (int i = 0; i < 64; i++) desc[i] /= len; }
//! Assign the supplied Ipoint an orientation void Surf::getOrientation() { Ipoint *ipt = &ipts.at(index); float gauss, scale = ipt->scale; int s = fRound(scale), r = fRound(ipt->y), c = fRound(ipt->x); std::vector<float> resX, resY, Ang; // calculate haar responses for points within radius of 6*scale for (int i = -6; i <= 6; ++i) { for (int j = -6; j <= 6; ++j) { if (i*i + j*j < 36) { gauss = static_cast<float>(gauss25[abs(i)][abs(j)]); resX.push_back( gauss * haarX(r+j*s, c+i*s, 4*s) ); resY.push_back( gauss * haarY(r+j*s, c+i*s, 4*s) ); Ang.push_back(getAngle(resX.back(), resY.back())); } } } // calculate the dominant direction float sumX, sumY; float max=0, old_max = 0, orientation = 0, old_orientation = 0; float ang1, ang2, ang; // loop slides pi/3 window around feature point for (ang1 = 0; ang1 < 2*pi; ang1+=0.15f) { ang2 = ( ang1+pi/3.0f > 2*pi ? ang1-5.0f*pi/3.0f : ang1+pi/3.0f); sumX = sumY = 0; for (unsigned int k = 0; k < Ang.size(); k++) { // get angle from the x-axis of the sample point ang = Ang.at(k); // determine whether the point is within the window if (ang1 < ang2 && ang1 < ang && ang < ang2) { sumX+=resX.at(k); sumY+=resY.at(k); } else if (ang2 < ang1 && ((ang > 0 && ang < ang2) || (ang > ang1 && ang < 2*pi) )) { sumX+=resX.at(k); sumY+=resY.at(k); } } // if the vector produced from this window is longer than all // previous vectors then this forms the new dominant direction if (sumX*sumX + sumY*sumY > max) { // store largest orientation max = sumX*sumX + sumY*sumY; orientation = getAngle(sumX, sumY); } } // assign orientation of the dominant response vector ipt->orientation = orientation; }
//! Get the descriptor vector of the provided Ipoint void Surf::getDescriptor() { int y, x, sample_x, sample_y, count=0; float scale, *desc, dx, dy, mdx, mdy, co, si; float gauss, rx, ry, rrx, rry, len=0; Ipoint *ipt = &ipts.at(index); scale = ipt->scale; x = fRound(ipt->x); y = fRound(ipt->y); co = cos(ipt->orientation); si = sin(ipt->orientation); desc = ipt->descriptor; // Calculate descriptor for this interest point for (int i = -10; i < 10; i+=5) { for (int j = -10; j < 10; j+=5) { dx=dy=mdx=mdy=0; for (int k = i; k < i + 5; ++k) { for (int l = j; l < j + 5; ++l) { // Get coords of sample point on the rotated axis sample_x = fRound(x + (-l*scale*si + k*scale*co)); sample_y = fRound(y + ( l*scale*co + k*scale*si)); // Get the gaussian weighted x and y responses gauss = static_cast<float>(gauss33[abs(k)][abs(l)]); rx = gauss * haarX(sample_y, sample_x, 2*fRound(scale)); ry = gauss * haarY(sample_y, sample_x, 2*fRound(scale)); // Get the gaussian weighted x and y responses on rotated axis rrx = -rx*si + ry*co; rry = rx*co + ry*si; dx += rrx; dy += rry; mdx += fabs(rrx); mdy += fabs(rry); } } // add the values to the descriptor vector desc[count++] = dx; desc[count++] = dy; desc[count++] = mdx; desc[count++] = mdy; // store the current length^2 of the vector len += dx*dx + dy*dy + mdx*mdx + mdy*mdy; } } // convert to unit vector len = sqrt(len); for (int i = 0; i < 64; i++) desc[i] /= len; }
//! Get the modified descriptor. See Agrawal ECCV 08 //! Modified descriptor contributed by Pablo Fernandez static int getDescriptor( SurfSubIPointT *iPoint, int *image, int width, int height, int border ) { int y, x, sample_x, sample_y, count=0; int i = 0, ix = 0, j = 0, jx = 0, xs = 0, ys = 0; float scale, *desc, dx, dy, mdx, mdy, co, si; float gauss_s1 = 0.f, gauss_s2 = 0.f; float rx = 0.f, ry = 0.f, rrx = 0.f, rry = 0.f, len = 0.f; float cx = -0.5f, cy = 0.f; //Subregion centers for the 4x4 gaussian weighting scale = iPoint->scale; x = (int)(iPoint->x + 0.5); y = (int)(iPoint->y + 0.5); desc = iPoint->descriptor; co = cosf(iPoint->orientation); si = sinf(iPoint->orientation); i = -8; //Calculate descriptor for this interest point while(i < 12) { j = -8; i = i-4; cx += 1.f; cy = -0.5f; while(j < 12) { dx=dy=mdx=mdy=0.f; cy += 1.f; j = j - 4; ix = i + 5; jx = j + 5; xs = (int)lroundf(x + (-jx*scale*si + ix*scale*co)); ys = (int)lroundf(y + ( jx*scale*co + ix*scale*si)); 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)lroundf(x + (-l*scale*si + k*scale*co)); sample_y = (int)lroundf(y + ( l*scale*co + k*scale*si)); //Get the gaussian weighted x and y responses gauss_s1 = gaussian(xs-sample_x,ys-sample_y,2.5f*scale); rx = (float)haarX(image, width, height, border, sample_y, sample_x, 2*((int)(scale+0.5))); ry = (float)haarY(image, width, height, border, sample_y, sample_x, 2*((int)(scale+0.5))); //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); dx += rrx; dy += rry; mdx += fabsf(rrx); mdy += fabsf(rry); } } //Add the values to the descriptor vector gauss_s2 = gaussian(cx-2.0f,cy-2.0f,1.5f); desc[count++] = dx*gauss_s2; desc[count++] = dy*gauss_s2; desc[count++] = mdx*gauss_s2; desc[count++] = mdy*gauss_s2; len += (dx*dx + dy*dy + mdx*mdx + mdy*mdy) * gauss_s2*gauss_s2; j += 9; } i += 9; } //Convert to Unit Vector len = sqrtf(len); for(int i = 0; i < 64; ++i) { desc[i] /= len; } return 0; }
static int getOrientation( SurfSubIPointT *iPoint, int *image, int width, int height, int border ) { float resX[109], resY[109], Ang[109]; float gauss = 0.0f; float scale = iPoint->scale; int id[] = {6,5,4,3,2,1,0,1,2,3,4,5,6}; int c = (int)(iPoint->x + 0.5); int r = (int)(iPoint->y + 0.5); int s = (int)(scale + 0.5); // calculate haar responses for points within radius of 6*scale int idx = 0; for(int i = -6; i <= 6; i++) { for(int j = -6; j <= 6; j++) { if( i*i + j*j >= 36 ) continue; gauss = (float)gauss25[id[i+6]][id[j+6]]; // Or: gauss25[abs(i)][abs(j)] resX[idx] = gauss * haarX(image, width, height, border, r+j*s, c+i*s, 4*s); resY[idx] = gauss * haarY(image, width, height, border, r+j*s, c+i*s, 4*s); Ang[idx] = getAngle(resX[idx], resY[idx]); idx++; } } // calculate the dominant direction float sumX=0.f, sumY=0.f; float maxSumX=0.f, maxSumY=0.f; float max=0.f; float ang1=0.f, ang2=0.f; // loop slides pi/3 window around feature point for(ang1 = 0; ang1 < 2.0f*M_PI; ang1+=0.15f) { ang2 = ( ang1 + (float)M_PI/3.0f > 2.0f*(float)M_PI ? ang1 - 5.0f*(float)M_PI/3.0f : ang1 + (float)M_PI/3.0f); sumX = sumY = 0.f; for (int k = 0; k < idx; ++k) { // get angle from the x-axis of the sample point const float & ang = Ang[k]; // determine whether the point is within the window if (ang1 < ang2 && ang1 < ang && ang < ang2) { sumX+=resX[k]; sumY+=resY[k]; } else if (ang2 < ang1 && ((ang > 0 && ang < ang2) || (ang > ang1 && ang < 2*M_PI) )) { sumX+=resX[k]; sumY+=resY[k]; } } // if the vector produced from this window is longer than all // previous vectors then this forms the new dominant direction if (sumX*sumX + sumY*sumY > max) { // store largest orientation max = sumX*sumX + sumY*sumY; maxSumX = sumX; maxSumY = sumY; } } // assign orientation of the dominant response vector iPoint->orientation = getAngle(maxSumX, maxSumY); return 0; }
//! Assign the supplied Ipoint an orientation void Surf::getOrientation() { Ipoint *ipt = &ipts[index]; float gauss = 0.f, scale = ipt->scale; const int s = fRound(scale), r = fRound(ipt->y), c = fRound(ipt->x); std::vector<float> resX(109), resY(109), Ang(109); const int id[] = {6,5,4,3,2,1,0,1,2,3,4,5,6}; int idx = 0; // calculate haar responses for points within radius of 6*scale for(int i = -6; i <= 6; ++i) { for(int j = -6; j <= 6; ++j) { if(i*i + j*j < 36) { gauss = static_cast<float>(gauss25[id[i+6]][id[j+6]]); resX[idx] = gauss * haarX(r+j*s, c+i*s, 4*s); resY[idx] = gauss * haarY(r+j*s, c+i*s, 4*s); Ang[idx] = getAngle(resX[idx], resY[idx]); ++idx; } } } // calculate the dominant direction float sumX=0.f, sumY=0.f; float max=0.f, orientation = 0.f; float ang1=0.f, ang2=0.f; // loop slides pi/3 window around feature point for(ang1 = 0; ang1 < 2*pi; ang1+=0.15f) { ang2 = ( ang1+pi/3.0f > 2*pi ? ang1-5.0f*pi/3.0f : ang1+pi/3.0f); sumX = sumY = 0.f; for(unsigned int k = 0; k < Ang.size(); ++k) { // get angle from the x-axis of the sample point const float & ang = Ang[k]; // determine whether the point is within the window if (ang1 < ang2 && ang1 < ang && ang < ang2) { sumX+=resX[k]; sumY+=resY[k]; } else if (ang2 < ang1 && ((ang > 0 && ang < ang2) || (ang > ang1 && ang < 2*pi) )) { sumX+=resX[k]; sumY+=resY[k]; } } // if the vector produced from this window is longer than all // previous vectors then this forms the new dominant direction if (sumX*sumX + sumY*sumY > max) { // store largest orientation max = sumX*sumX + sumY*sumY; orientation = getAngle(sumX, sumY); } } // assign orientation of the dominant response vector ipt->orientation = orientation; }
//! Get the modified descriptor. See Agrawal ECCV 08 //! Modified descriptor contributed by Pablo Fernandez void Surf::getDescriptor(bool bUpright) { int y, x, sample_x, sample_y, count=0; int i = 0, ix = 0, j = 0, jx = 0, xs = 0, ys = 0; float scale, *desc, dx, dy, mdx, mdy, co, si; float gauss_s1 = 0.f, gauss_s2 = 0.f; float rx = 0.f, ry = 0.f, rrx = 0.f, rry = 0.f, len = 0.f; float cx = -0.5f, cy = 0.f; //Subregion centers for the 4x4 gaussian weighting Ipoint *ipt = &ipts[index]; scale = ipt->scale; x = fRound(ipt->x); y = fRound(ipt->y); desc = ipt->descriptor; if (bUpright) { co = 1; si = 0; } else { co = cos(ipt->orientation); si = sin(ipt->orientation); } i = -8; //Calculate descriptor for this interest point while(i < 12) { j = -8; i = i-4; cx += 1.f; cy = -0.5f; while(j < 12) { dx=dy=mdx=mdy=0.f; cy += 1.f; j = j - 4; ix = i + 5; jx = j + 5; xs = fRound(x + ( -jx*scale*si + ix*scale*co)); ys = fRound(y + ( jx*scale*co + ix*scale*si)); 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 = fRound(x + (-l*scale*si + k*scale*co)); sample_y = fRound(y + ( l*scale*co + k*scale*si)); //Get the gaussian weighted x and y responses gauss_s1 = gaussian(xs-sample_x,ys-sample_y,2.5f*scale); rx = haarX(sample_y, sample_x, 2*fRound(scale)); ry = haarY(sample_y, sample_x, 2*fRound(scale)); //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); dx += rrx; dy += rry; mdx += fabs(rrx); mdy += fabs(rry); } } //Add the values to the descriptor vector gauss_s2 = gaussian(cx-2.0f,cy-2.0f,1.5f); desc[count++] = dx*gauss_s2; desc[count++] = dy*gauss_s2; desc[count++] = mdx*gauss_s2; desc[count++] = mdy*gauss_s2; len += (dx*dx + dy*dy + mdx*mdx + mdy*mdy) * gauss_s2*gauss_s2; j += 9; } i += 9; } //Convert to Unit Vector len = sqrt(len); for(int i = 0; i < 64; ++i) desc[i] /= len; }
void SURF::eval(unsigned char *in, float *out, int xres, int yres,float scale,float orientation) { img = in; float co,si; this->xres = xres; this->yres = yres; co = cos(orientation); si = sin(orientation); #pragma omp parallel for for(int y = 0; y < yres; y ++) { int sample_x, sample_y, count; int i, ix, j, jx, xs, ys; #ifdef SURF_128 float dx1, dx2, dx3, dx4, dy1, dy2, dy3, dy4; #else float dx, dy, mdx, mdy; #endif float gauss_s1, gauss_s2; float rx, ry, rrx, rry, len; float cx,cy; //Subregion centers for the 4x4 gaussian weighting for(int x = 0; x < xres; x ++) { #ifdef SURF_128 float *desc = out+(x+y*xres)*128; #else float *desc = out+(x+y*xres)*64; #endif count = 0; len = 0; cx = -0.5f; i = -8; //Calculate descriptor while(i < 12) { j = -8; i = i-4; cx += 1.f; cy = -0.5f; while(j < 12) { #ifdef SURF_128 dx1 = dx2 = dx3 = dx4 = dy1 = dy2 = dy3 = dy4 = 0.f; #else dx=dy=mdx=mdy=0.f; #endif cy += 1.f; j = j - 4; ix = i + 5; jx = j + 5; xs = fRound(x + ( -jx*scale*si + ix*scale*co)); ys = fRound(y + ( jx*scale*co + ix*scale*si)); 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 = fRound(x + (-l*scale*si + k*scale*co)); sample_y = fRound(y + ( l*scale*co + k*scale*si)); //Get the gaussian weighted x and y responses gauss_s1 = gaussian(xs-sample_x,ys-sample_y,2.5f*scale); rx = haarX(sample_y, sample_x, 2*fRound(scale)); ry = haarY(sample_y, sample_x, 2*fRound(scale)); //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); #ifdef SURF_128 if(rry > 0) if(rrx > 0) { dx1 += rrx; dy1 += rry; } else { dx2 -= rrx; dy2 += rry; } else if(rrx < 0) { dx3 -= rrx; dy3 -= rry; } else { dx4 += rrx; dy4 -= rry; } #else dx += rrx; dy += rry; mdx += fabs(rrx); mdy += fabs(rry); #endif } } //Add the values to the descriptor vector gauss_s2 = gaussian(cx-2.0f,cy-2.0f,1.5f); #ifdef SURF_128 desc[count++] = dx1*gauss_s2; desc[count++] = dy1*gauss_s2; desc[count++] = dx2*gauss_s2; desc[count++] = dy2*gauss_s2; desc[count++] = dx3*gauss_s2; desc[count++] = dy3*gauss_s2; desc[count++] = dx4*gauss_s2; desc[count++] = dy4*gauss_s2; len += (dx1*dx1 + dy1*dy1 + dx2*dx2 + dy2*dy2 + dx3*dx3 + dy3*dy3 + dx4*dx4 + dy4*dy4 ) * gauss_s2*gauss_s2; #else desc[count++] = dx*gauss_s2; desc[count++] = dy*gauss_s2; desc[count++] = mdx*gauss_s2; desc[count++] = mdy*gauss_s2; len += (dx*dx + dy*dy + mdx*mdx + mdy*mdy) * gauss_s2*gauss_s2; #endif j += 9; } i += 9; } //Convert to Unit Vector len = sqrt(len); #ifdef SURF_128 for(int i = 0; i < 128; ++i) #else for(int i = 0; i < 64; ++i) #endif desc[i] /= len; } } }