bool QuickHarrisDetector::quickConvolutionWithBestPoint( const image::ConvexRoi & roi, int pixMax[2], float & scoreMax) { int shift_derv = 1; int shift_derv_conv = shift_derv + shift_conv; // bounds int riMin = shift_derv_conv; int riMax = roi.h() - shift_derv_conv; int rjMin = shift_derv_conv; int rjMax = roi.w() - shift_derv_conv; // data structure pointers HQuickData* int_center; #if GAUSSIAN_MASK_APPROX #else HQuickData* int_upLeft; HQuickData* int_upRight; HQuickData* int_downLeft; HQuickData* int_downRight; #endif float im_low_curv_max = 0.; // maximum smallest eigenvalue float im_high_curv_max = 0.; int sm, df; // sum and difference float sr, corner_ratio; int ri, rj; // roi coordinates for (ri = riMin; ri < riMax; ri++) { int_center = m_quickData + (ri * roi.w()) + rjMin; #if GAUSSIAN_MASK_APPROX for(int i = 0; i < nConvCoeffs; ++i) { int_upLeft[i] = int_center - (shift_convs[i] * (roi.w()+1)); int_upRight[i] = int_center - (shift_convs[i] * (roi.w()-1)); int_downLeft[i] = int_center + (shift_convs[i] * (roi.w()-1)); int_downRight[i] = int_center + (shift_convs[i] * (roi.w()+1)); } #else int_upLeft = int_center - (shift_conv * roi.w()) - shift_conv; int_upRight = int_center - (shift_conv * roi.w()) + shift_conv; int_downLeft = int_center + (shift_conv * roi.w()) - shift_conv; int_downRight = int_center + (shift_conv * roi.w()) + shift_conv; #endif for (rj = rjMin; rj < rjMax; rj++) { #if GAUSSIAN_MASK_APPROX int_center->im_conv_xx = int_center->im_conv_xy = int_center->im_conv_yy = 0.; for(int i = 0; i < nConvCoeffs; ++i) { int_center->im_conv_xx += convCoeffs[i]*( int_downRight[i]->int_xx - int_upRight[i]->int_xx - int_downLeft[i]->int_xx + int_upLeft[i]->int_xx); int_center->im_conv_xy += convCoeffs[i]*( int_downRight[i]->int_xy - int_upRight[i]->int_xy - int_downLeft[i]->int_xy + int_upLeft[i]->int_xy); int_center->im_conv_yy += convCoeffs[i]*( int_downRight[i]->int_yy - int_upRight[i]->int_yy - int_downLeft[i]->int_yy + int_upLeft[i]->int_yy); } if (nConvCoeffsCenter) { int_center->im_conv_xx += convCoeffs[nConvCoeffs]*int_center->im_xx; int_center->im_conv_xy += convCoeffs[nConvCoeffs]*int_center->im_xy; int_center->im_conv_yy += convCoeffs[nConvCoeffs]*int_center->im_yy; } #else int_center->im_conv_xx = int_downRight->int_xx - int_upRight->int_xx - int_downLeft->int_xx + int_upLeft->int_xx; int_center->im_conv_xy = int_downRight->int_xy - int_upRight->int_xy - int_downLeft->int_xy + int_upLeft->int_xy; int_center->im_conv_yy = int_downRight->int_yy - int_upRight->int_yy - int_downLeft->int_yy + int_upLeft->int_yy; #endif // get eigenvalues: EIG/eig = I_xx + I_yy +/- sqrt((Ixx - I_yy)^2 + 4*I_xy^2) sm = int_center->im_conv_xx + int_center->im_conv_yy; df = int_center->im_conv_xx - int_center->im_conv_yy; sr = sqrt((double) ((double) df * (double) df + 4 * ((double) int_center->im_conv_xy) * ((double) int_center->im_conv_xy))); int_center->im_high_curv = (double) sm + sr; // Smallest eigenvalue. int_center->im_low_curv = (double) sm - sr; // Largest eigenvalue. // detect and write pixel corresponding to strongest corner, with score. #ifndef JFR_NDEBUG if (int_center->im_low_curv == 0.0) corner_ratio = 1e10; else #endif corner_ratio = int_center->im_high_curv / int_center->im_low_curv; // CAUTION should be high/low if (corner_ratio < m_edge) { if (int_center->im_low_curv > im_low_curv_max) { im_low_curv_max = int_center->im_low_curv; im_high_curv_max = int_center->im_high_curv; pixMax[0] = roi.x() + rj; pixMax[1] = roi.y() + ri; } } int_center++; #if GAUSSIAN_MASK_APPROX for(int i = 0; i < nConvCoeffs; ++i) { int_upLeft[i]++; int_upRight[i]++; int_downLeft[i]++; int_downRight[i]++; } #else int_upLeft++; int_upRight++; int_downLeft++; int_downRight++; #endif } } // normalized score: over the size of the derivative and convolution windows scoreMax = sqrt(im_low_curv_max / normCoeff); //std::cout << "- at " << pixMax[0] << "," << pixMax[1] << " : high " << im_high_curv_max << " low " << im_low_curv_max << " ; ratio " << im_high_curv_max/im_low_curv_max << " score " << scoreMax << std::endl; #if FILTER_VIRTUAL_POINTS /* accept: _|_ (4) |_ _/ _ (2) _ _ _ (1 or 2) | \ \ / reject: |_ (3) . (0) | */ int_center = m_quickData + ((pixMax[1]-roi.y()) * roi.w()) + (pixMax[0]-roi.x()); int indexes[8][2] = {{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1}}; int radius = m_convolutionSize/2; for(int i = 0; i < 8; ++i) for(int j = 0; j < 2; ++j) indexes[i][j] *= radius; double thres = im_low_curv_max * 0.75; int npeaks = 0; bool lastpeaked = false; bool firstpeaked = false; for(int i = 0; i < 8; ++i) { int_upLeft = int_center + indexes[i][1] * roi.w() + indexes[i][0]; if (int_upLeft->im_high_curv > thres) { if (i == 0) firstpeaked = true; else if (i == 7) lastpeaked = lastpeaked || firstpeaked; if (!lastpeaked) npeaks++; lastpeaked = true; } else lastpeaked = false; std::cout << " high " << int_upLeft->im_high_curv << " " << " low " << int_upLeft->im_low_curv << std::endl; } bool ok = (npeaks == 1 || npeaks == 2 || npeaks == 4); std::cout << " high " << int_center->im_high_curv << " low " << int_center->im_low_curv << " npeaks " << npeaks << " ok " << ok << std::endl; #endif return (scoreMax > m_threshold); }
void ActiveSearchGrid::setFailed(const image::ConvexRoi & roi) { vec2 p; p(0) = roi.x()+roi.w()/2; p(1) = roi.y()+roi.h()/2; veci2 cell = pix2cell(p); projectionsCount(cell(0), cell(1)) = -1; }
void QuickHarrisDetector::quickDerivatives( const jafar::image::Image & image, image::ConvexRoi & roi) { const uchar* pix_center; const uchar* pix_right; const uchar* pix_left; const uchar* pix_down; const uchar* pix_up; HQuickData* int_center; HQuickData* int_up; HQuickData* int_upLeft; HQuickData* int_left; // dead zone due to derivative mask [-1 0 1] int shift_derv = 1; // = (3-1)/2 // i: vert; j: horz image coordinates int iMin = roi.y() + shift_derv; int iMax = roi.y() + roi.h() - shift_derv; // FIXME take into account possible convex part of roi x(i) and w(i) by moving this into the loop int jMin = roi.x() + shift_derv; int jMax = roi.x() + roi.w() - shift_derv; int i, j; // i, j: image coordinates int ri; // ri: vertical roi coordinate for (i = iMin; i < iMax; i++) { ri = i - roi.y(); pix_center = image.data() + (i * image.step()) + jMin; pix_right = pix_center + 1; pix_left = pix_center - 1; pix_down = pix_center + image.step(); pix_up = pix_center - image.step(); int_center = m_quickData + (ri * roi.w()) + shift_derv; int_up = int_center - roi.w(); int_upLeft = int_up - 1; int_left = int_center - 1; for (j = jMin; j < jMax; j++) { // Build x and y derivatives, and their products: xx, xy and yy. int_center->im_x = *pix_right - *pix_left; int_center->im_y = *pix_down - *pix_up; int_center->im_xx = int_center->im_x * int_center->im_x; int_center->im_xy = int_center->im_x * int_center->im_y; int_center->im_yy = int_center->im_y * int_center->im_y; // build integral images of the 3 derivative products, xx, xy and yy: if (i == iMin && j == jMin) { int_center->int_xx = int_center->im_xx; int_center->int_xy = int_center->im_xy; int_center->int_yy = int_center->im_yy; } else if (i == iMin) { int_center->int_xx = int_center->im_xx + int_left->int_xx; int_center->int_xy = int_center->im_xy + int_left->int_xy; int_center->int_yy = int_center->im_yy + int_left->int_yy; } else if (j == jMin) { int_center->int_xx = int_center->im_xx + int_up->int_xx; int_center->int_xy = int_center->im_xy + int_up->int_xy; int_center->int_yy = int_center->im_yy + int_up->int_yy; } else { int_center->int_xx = int_center->im_xx + int_up->int_xx + int_left->int_xx - int_upLeft->int_xx; int_center->int_xy = int_center->im_xy + int_up->int_xy + int_left->int_xy - int_upLeft->int_xy; int_center->int_yy = int_center->im_yy + int_up->int_yy + int_left->int_yy - int_upLeft->int_yy; } // Advance all pointers pix_center++; pix_right++; pix_left++; pix_up++; pix_down++; int_center++; int_up++; int_left++; int_upLeft++; } } }