/** \brief Checks if a patch at a specific image location is still within the reference image. * * @param img - Reference Image. * @param c - Coordinates of the patch in the reference image. * @param withBorder - Check, using either the patch-patchSize of Patch::patch_ (withBorder = false) or the patch-patchSize * of the expanded patch Patch::patchWithBorder_ (withBorder = true). * @return true, if the patch is completely located within the reference image. */ static bool isPatchInFrame(const cv::Mat& img,const FeatureCoordinates& c,const bool withBorder = false){ if(c.isInFront() && c.com_warp_c()){ const int halfpatch_size = patchSize/2+(int)withBorder; if(c.isNearIdentityWarping()){ if(c.get_c().x < halfpatch_size || c.get_c().y < halfpatch_size || c.get_c().x > img.cols-halfpatch_size || c.get_c().y > img.rows-halfpatch_size){ return false; } else { return true; } } else { for(int x = 0;x<2;x++){ for(int y = 0;y<2;y++){ const float dx = halfpatch_size*(2*x-1); const float dy = halfpatch_size*(2*y-1); const float wdx = c.get_warp_c()(0,0)*dx + c.get_warp_c()(0,1)*dy; const float wdy = c.get_warp_c()(1,0)*dx + c.get_warp_c()(1,1)*dy; const float c_x = c.get_c().x + wdx; const float c_y = c.get_c().y + wdy; if(c_x < 0 || c_y < 0 || c_x > img.cols || c_y > img.rows){ return false; } } } return true; } } else { return false; } }
/** \brief Extracts a patch from an image. * * @param img - Reference Image. * @param c - Coordinates of the patch in the reference image (subpixel coordinates possible). * @param withBorder - If false, the patch object is only initialized with the patch data of the general patch (Patch::patch_). * If true, the patch object is initialized with both, the patch data of the general patch (Patch::patch_) * and the patch data of the expanded patch (Patch::patchWithBorder_). */ void extractPatchFromImage(const cv::Mat& img,const FeatureCoordinates& c,const bool withBorder = false){ assert(isPatchInFrame(img,c,withBorder)); const int halfpatch_size = patchSize/2+(int)withBorder; const int refStep = img.step.p[0]; // Get Pointers uint8_t* img_ptr; float* patch_ptr; if(withBorder){ patch_ptr = patchWithBorder_; } else { patch_ptr = patch_; } if(c.isNearIdentityWarping()){ const int u_r = floor(c.get_c().x); const int v_r = floor(c.get_c().y); // compute interpolation weights const float subpix_x = c.get_c().x-u_r; const float subpix_y = c.get_c().y-v_r; const float wTL = (1.0-subpix_x)*(1.0-subpix_y); const float wTR = subpix_x * (1.0-subpix_y); const float wBL = (1.0-subpix_x)*subpix_y; const float wBR = subpix_x * subpix_y; for(int y=0; y<2*halfpatch_size; ++y){ img_ptr = (uint8_t*) img.data + (v_r+y-halfpatch_size)*refStep + u_r-halfpatch_size; for(int x=0; x<2*halfpatch_size; ++x, ++img_ptr, ++patch_ptr) { *patch_ptr = wTL*img_ptr[0]; if(subpix_x > 0) *patch_ptr += wTR*img_ptr[1]; if(subpix_y > 0) *patch_ptr += wBL*img_ptr[refStep]; if(subpix_x > 0 && subpix_y > 0) *patch_ptr += wBR*img_ptr[refStep+1]; } } } else { for(int y=0; y<2*halfpatch_size; ++y){ for(int x=0; x<2*halfpatch_size; ++x, ++patch_ptr){ const float dx = x - halfpatch_size + 0.5; const float dy = y - halfpatch_size + 0.5; const float wdx = c.get_warp_c()(0,0)*dx + c.get_warp_c()(0,1)*dy; const float wdy = c.get_warp_c()(1,0)*dx + c.get_warp_c()(1,1)*dy; const float u_pixel = c.get_c().x+wdx - 0.5; const float v_pixel = c.get_c().y+wdy - 0.5; const int u_r = floor(u_pixel); const int v_r = floor(v_pixel); const float subpix_x = u_pixel-u_r; const float subpix_y = v_pixel-v_r; const float wTL = (1.0-subpix_x) * (1.0-subpix_y); const float wTR = subpix_x * (1.0-subpix_y); const float wBL = (1.0-subpix_x) * subpix_y; const float wBR = subpix_x * subpix_y; img_ptr = (uint8_t*) img.data + v_r*refStep + u_r; *patch_ptr = wTL*img_ptr[0]; if(subpix_x > 0) *patch_ptr += wTR*img_ptr[1]; if(subpix_y > 0) *patch_ptr += wBL*img_ptr[refStep]; if(subpix_x > 0 && subpix_y > 0) *patch_ptr += wBR*img_ptr[refStep+1]; } } } if(withBorder){ extractPatchFromPatchWithBorder(); } validGradientParameters_ = false; }