1.这个函数做什么的
将提取的ORB特征点分配到图像网格中方便特征点匹配的时候用到
2.Frame::AssignFeaturesToGrid函数代码解析
void Frame::AssignFeaturesToGrid() { // Step 1 给存储特征点的网格数组 Frame::mGrid 预分配空间 // ? 这里0.5 是为什么?节省空间? // FRAME_GRID_COLS = 64,FRAME_GRID_ROWS=48 int nReserve = 0.5f*N/(FRAME_GRID_COLS*FRAME_GRID_ROWS); //开始对mGrid这个二维数组中的每一个vector元素遍历并预分配空间 for(unsigned int i=0; i<FRAME_GRID_COLS;i++) for (unsigned int j=0; j<FRAME_GRID_ROWS;j++) mGrid[i][j].reserve(nReserve); // Step 2 遍历每个特征点,将每个特征点在mvKeysUn中的索引值放到对应的网格mGrid中 for(int i=0;i<N;i++) { //从类的成员变量中获取已经去畸变后的特征点 const cv::KeyPoint &kp = mvKeysUn[i]; //存储某个特征点所在网格的网格坐标,nGridPosX范围:[0,FRAME_GRID_COLS], nGridPosY范围:[0,FRAME_GRID_ROWS] int nGridPosX, nGridPosY; // 计算某个特征点所在网格的网格坐标,如果找到特征点所在的网格坐标,记录在nGridPosX,nGridPosY里,返回true,没找到返回false if(PosInGrid(kp,nGridPosX,nGridPosY)) //如果找到特征点所在网格坐标,将这个特征点的索引添加到对应网格的数组mGrid中 mGrid[nGridPosX][nGridPosY].push_back(i); } }
我们先来看nReserve 的含义,FRAME_GRID_COLS*FRAME_GRID_ROWS是网格数目(64*48的网格),用特征点总数N/FRAME_GRID_COLS*FRAME_GRID_ROWS,含义是每个网格中平均含有的特征点数量,0.5*它为了节省空间。
然后对遍历每个网格分配nReserve 个特征点。
再遍历每个特征点,将每个特征点在mvKeysUn中的索引值(去畸变后的特征点)放到对应的网格mGrid中。
///这个向量中存储的是每个图像网格内特征点的id(左图) std::vector<std::size_t> mGrid[FRAME_GRID_COLS][FRAME_GRID_ROWS];
3. Frame::PosInGrid代码解析
/** * @brief 计算某个特征点所在网格的网格坐标,如果找到特征点所在的网格坐标,记录在nGridPosX,nGridPosY里,返回true,没找到返回false * * @param[in] kp 给定的特征点 * @param[in & out] posX 特征点所在网格坐标的横坐标 * @param[in & out] posY 特征点所在网格坐标的纵坐标 * @return true 如果找到特征点所在的网格坐标,返回true * @return false 没找到返回false */ bool Frame::PosInGrid(const cv::KeyPoint &kp, int &posX, int &posY) { // 计算特征点x,y坐标落在哪个网格内,网格坐标为posX,posY // mfGridElementWidthInv=(FRAME_GRID_COLS)/(mnMaxX-mnMinX); // mfGridElementHeightInv=(FRAME_GRID_ROWS)/(mnMaxY-mnMinY); posX = round((kp.pt.x-mnMinX)*mfGridElementWidthInv); posY = round((kp.pt.y-mnMinY)*mfGridElementHeightInv); //Keypoint's coordinates are undistorted, which could cause to go out of the image // 因为特征点进行了去畸变,而且前面计算是round取整,所以有可能得到的点落在图像网格坐标外面 // 如果网格坐标posX,posY超出了[0,FRAME_GRID_COLS] 和[0,FRAME_GRID_ROWS],表示该特征点没有对应网格坐标,返回false if(posX<0 || posX>=FRAME_GRID_COLS || posY<0 || posY>=FRAME_GRID_ROWS) return false; // 计算成功返回true return true; }
我们将mvKeysUn中的特征点一个个在此函数处理,最终将各个去畸变后的特征点的索引值存放在grid栅格中。
mfGridElementWidthInv=(FRAME_GRID_COLS)/(mnMaxX-mnMinX),这个变量的意义是栅格的列数/图像的宽度,举个例子,比如要把10米分成5个栅格,那么5/10=0.5,用这个数去乘以当前图像的位置就可以得到在哪个栅格中,比如有个物体在7m处,7*0.5=3.5,那么这个物体就在第三个栅格中。
因此,posX、posY是该特征点所在的栅格位置,然后判断栅格位置是否合法,若合法,将特征点的索引赋值给grid栅格,最终应该是这样的。