当前位置: 首页 > wzjs >正文

网站 建设初步西安搜索引擎优化

网站 建设初步,西安搜索引擎优化,网络工程公司属于什么行业,厦门网页设计ComputeKeyPointsOctTree是ORB特征提取器中计算关键点的部分&#xff0c;特别是使用八叉树&#xff08;OctTree&#xff09;方法进行关键点分布。 首先&#xff0c;函数参数是vector<vector的引用allKeypoints&#xff0c;用来存储各层的关键点。代码开头调整了allKeypoint…

ComputeKeyPointsOctTree是ORB特征提取器中计算关键点的部分,特别是使用八叉树(OctTree)方法进行关键点分布。

首先,函数参数是vector<vector的引用allKeypoints,用来存储各层的关键点。代码开头调整了allKeypoints的大小为nlevels,即金字塔层数。接下来,循环处理每一层图像金字塔。

在循环内部,首先定义了边界minBorderX和minBorderY,可能是为了避开边缘区域,因为边缘附近的关键点可能不完整。然后计算了maxBorderX和maxBorderY,确定当前层的有效区域。接着初始化vToDistributeKeys,预留空间用于存储待分配的关键点。

然后根据宽度和高度划分网格,每个网格大小为W(30)。这里计算了nCols和nRows,即网格的行列数。wCell和hCell是每个网格的实际大小,可能因为不能整除而向上取整。

接下来是双重循环遍历每个网格。对于每个网格,计算初始坐标iniY和iniX,以及最大坐标maxY和maxX。这里有一些条件判断,确保网格不超过最大边界。然后在每个网格内使用FAST算法检测关键点,首先使用iniThFAST阈值,如果没检测到则改用minThFAST阈值。

检测到关键点后,调整它们的坐标,加上网格的偏移量,并存入vToDistributeKeys。这一步是因为FAST检测是在网格的子图像上进行的,所以需要将坐标转换回原图的坐标。

之后,调用DistributeOctTree函数,将关键点按八叉树分布,筛选出符合数量要求的关键点,并存入当前层的keypoints。这里可能涉及到关键点的均匀分布和响应值排序,确保每层的关键点数量符合mnFeaturesPerLevel的设置。

接着处理每个关键点的坐标,加上minBorderX和minBorderY的偏移,设置octave(金字塔层)和size(根据缩放因子调整的尺寸)。最后,循环结束后,计算每个关键点的方向,使用computeOrientation函数。

需要注意的是,代码中的EDGE_THRESHOLD、mvImagePyramid、PATCH_SIZE、mvScaleFactor等变量可能在类的其他部分定义。此外,DistributeOctTree函数的具体实现细节会影响关键点的分布方式,可能涉及四叉树分割和响应值筛选。

void ORBextractor::ComputeKeyPointsOctTree(vector<vector<KeyPoint> >& allKeypoints)
{allKeypoints.resize(nlevels);const float W = 30;for (int level = 0; level < nlevels; ++level){const int minBorderX = EDGE_THRESHOLD-3;const int minBorderY = minBorderX;const int maxBorderX = mvImagePyramid[level].cols-EDGE_THRESHOLD+3;const int maxBorderY = mvImagePyramid[level].rows-EDGE_THRESHOLD+3;vector<cv::KeyPoint> vToDistributeKeys;vToDistributeKeys.reserve(nfeatures*10);const float width = (maxBorderX-minBorderX);const float height = (maxBorderY-minBorderY);const int nCols = width/W;const int nRows = height/W;const int wCell = ceil(width/nCols);const int hCell = ceil(height/nRows);for(int i=0; i<nRows; i++){const float iniY =minBorderY+i*hCell;float maxY = iniY+hCell+6;if(iniY>=maxBorderY-3)continue;if(maxY>maxBorderY)maxY = maxBorderY;for(int j=0; j<nCols; j++){const float iniX =minBorderX+j*wCell;float maxX = iniX+wCell+6;if(iniX>=maxBorderX-6)continue;if(maxX>maxBorderX)maxX = maxBorderX;vector<cv::KeyPoint> vKeysCell;FAST(mvImagePyramid[level].rowRange(iniY,maxY).colRange(iniX,maxX),vKeysCell,iniThFAST,true);if(vKeysCell.empty()){FAST(mvImagePyramid[level].rowRange(iniY,maxY).colRange(iniX,maxX),vKeysCell,minThFAST,true);}if(!vKeysCell.empty()){for(vector<cv::KeyPoint>::iterator vit=vKeysCell.begin(); vit!=vKeysCell.end();vit++){(*vit).pt.x+=j*wCell;(*vit).pt.y+=i*hCell;vToDistributeKeys.push_back(*vit);}}}}vector<KeyPoint> & keypoints = allKeypoints[level];keypoints.reserve(nfeatures);keypoints = DistributeOctTree(vToDistributeKeys, minBorderX, maxBorderX,minBorderY, maxBorderY,mnFeaturesPerLevel[level], level);const int scaledPatchSize = PATCH_SIZE*mvScaleFactor[level];// Add border to coordinates and scale informationconst int nkps = keypoints.size();for(int i=0; i<nkps ; i++){keypoints[i].pt.x+=minBorderX;keypoints[i].pt.y+=minBorderY;keypoints[i].octave=level;keypoints[i].size = scaledPatchSize;}}// compute orientationsfor (int level = 0; level < nlevels; ++level)computeOrientation(mvImagePyramid[level], allKeypoints[level], umax);
}

以下是 ORBextractor::ComputeKeyPointsOctTree 函数的逐行解析及原理说明,结合 ORB 特征提取的算法设计与实现细节:


功能概述

该函数用于在图像金字塔各层级上提取并均匀分布 ORB 特征点,通过分块检测 FAST 角点并结合四叉树筛选策略,保证特征点分布的均匀性和尺度不变性。这是 ORB-SLAM 等视觉系统的核心步骤之一。


输入与输出

  • 输入:图像金字塔 mvImagePyramid(通过高斯模糊生成的多尺度图像集合)。
  • 输出:分层的关键点集合 allKeypoints,包含每个金字塔层级的关键点信息。

代码解析

1. 分层处理图像金字塔
allKeypoints.resize(nlevels);
for (int level = 0; level < nlevels; ++level) {// 各层参数初始化const int minBorderX = EDGE_THRESHOLD - 3;const int maxBorderX = mvImagePyramid[level].cols - EDGE_THRESHOLD + 3;// 类似处理Y方向
}

以下是代码的逐行解析,结合ORB特征提取及图像分块处理逻辑:

代码功能概述

该代码段用于在图像金字塔的指定层级上进行分块FAST特征点检测,并通过动态阈值调整和特征点再分配策略实现关键点的均匀分布,属于ORB特征提取流程中的核心步骤。


行级解析

for(int i=0; i<levelRows; i++) 
{// 计算当前行的起始Y坐标(考虑边界扩展3像素)const float iniY = minBorderY + i*cellH - 3;iniYRow[i] = iniY;  // 保存当前行的起始Y坐标// 处理最后一行的高度计算if(i == levelRows-1) {hY = maxBorderY + 3 - iniY;  // 计算实际高度if(hY <= 0) continue;        // 跳过无效行}float hX = cellW + 6;  // 列的默认宽度(包含左右各3像素扩展)// 遍历每一列for(int j=0; j<levelCols; j++) {float iniX;// 第一行初始化X坐标if(i == 0) {iniX = minBorderX + j*cellW - 3;iniXCol[j] = iniX;  // 保存列的起始X坐标} else {iniX = iniXCol[j];  // 复用已保存的X坐标}// 处理最后一列的宽度计算if(j == levelCols-1) {hX = maxBorderX + 3 - iniX;if(hX <= 0) continue;  // 跳过无效列}// 提取当前单元格图像块Mat cellImage = mvImagePyramid[level].rowRange(iniY, iniY+hY).colRange(iniX, iniX+hX);// 预分配内存(避免多次扩容)cellKeyPoints[i][j].reserve(nfeaturesCell * 5);// 使用初始阈值检测FAST特征点(启用非极大值抑制)FAST(cellImage, cellKeyPoints[i][j], iniThFAST, true);// 特征点不足时,改用最小阈值重新检测if(cellKeyPoints[i][j].size() <= 3) {cellKeyPoints[i][j].clear();FAST(cellImage, cellKeyPoints[i][j], minThFAST, true);}// 统计当前单元格特征点数量const int nKeys = cellKeyPoints[i][j].size();nTotal[i][j] = nKeys;  // 记录实际特征点数// 判断是否需要保留更多特征点if(nKeys > nfeaturesCell) {nToRetain[i][j] = nfeaturesCell;  // 保留上限bNoMore[i][j] = false;            // 标记可继续分配} else {nToRetain[i][j] = nKeys;          // 保留全部现有特征点nToDistribute += nfeaturesCell - nKeys;  // 累计待分配数量bNoMore[i][j] = true;             // 标记无法分配更多nNoMore++;                        // 统计无法分配的单元格数}}
}

关键设计原理

  1. 分块策略

    • 将图像划分为levelRows×levelCols的网格,每个单元格独立检测特征点,确保空间均匀性。
    • 边界扩展3像素(cellW+6cellH+6),避免边缘特征遗漏。
  2. 动态阈值调整

    • 初始阈值iniThFAST检测失败时,改用更低阈值minThFAST,适应低纹理区域。
  3. 特征点再分配

    • 通过nToDistribute累计需要补充的特征点数,后续步骤可能通过非极大值抑制或四叉树分割重新分配。
  4. 内存优化

    • reserve(nfeaturesCell*5)预分配内存,减少动态扩容开销。

应用场景

  • ORB特征提取:用于SLAM(如ORB-SLAM3)、目标跟踪等需要旋转不变性和实时性的场景。
  • 多尺度处理mvImagePyramid支持图像金字塔,实现多尺度特征检测。

性能优化点

  • 复用坐标:首行初始化iniXCol[j],后续行直接复用,减少重复计算。
  • 提前终止hY<=0hX<=0时跳过无效区域,减少冗余计算。
  • 并行潜力:分块结构天然适合多线程处理(需注意线程安全)。
  • 目的:遍历金字塔的每一层(nlevels),处理不同尺度的图像。
  • 边界处理EDGE_THRESHOLD 是特征点距图像边缘的最小距离,±3 的调整用于扩展有效检测区域,避免边缘特征不稳定。
2. 网格分块与FAST角点检测
const float W = 30;
const int nCols = width / W;  // 列方向分块数
const int nRows = height / W; // 行方向分块数for (int i = 0; i < nRows; i++) {for (int j = 0; j < nCols; j++) {// 定义当前网格的坐标范围const float iniY = minBorderY + i * hCell;const float iniX = minBorderX + j * wCell;// 执行FAST角点检测FAST(mvImagePyramid[level].rowRange(iniY, maxY).colRange(iniX, maxX),vKeysCell, iniThFAST, true);}
}
  • 网格划分:将当前金字塔层级的有效区域划分为 30x30 的网格,每个网格独立检测 FAST 角点,确保初步均匀性。
  • FAST检测优化
    • 使用两种阈值(iniThFASTminThFAST),优先用高阈值检测强角点,若失败则改用低阈值,平衡特征点数量与质量。
    • 检测到的角点坐标需根据网格位置偏移,转换为全局坐标((*vit).pt.x += j * wCell)。
3. 四叉树筛选关键点
keypoints = DistributeOctTree(vToDistributeKeys, minBorderX, maxBorderX,minBorderY, maxBorderY, mnFeaturesPerLevel[level], level);
  • 四叉树算法:将初步检测的角点(vToDistributeKeys)按空间分布均匀性筛选,最终保留 mnFeaturesPerLevel[level] 个关键点。
    • 原理:递归将区域划分为四个子节点,保留响应最强的角点,避免特征点聚集。
    • 终止条件:当子节点中仅剩一个角点或达到预设特征数量时停止分割。
4. 关键点属性设置
const int scaledPatchSize = PATCH_SIZE * mvScaleFactor[level];
keypoints[i].octave = level;          // 所属金字塔层级
keypoints[i].size = scaledPatchSize;  // 特征点邻域直径(尺度自适应)
  • 尺度不变性scaledPatchSize 根据金字塔层级缩放,高层级特征点对应更大的邻域,用于后续计算旋转和描述子。
  • 坐标修正:将筛选后的关键点坐标还原到原始图像坐标系(minBorderX/Y 偏移)。
5. 计算关键点方向
computeOrientation(mvImagePyramid[level], allKeypoints[level], umax);
  • 灰度质心法:通过计算图像块的一阶矩(m10m01),确定关键点的主方向,实现旋转不变性。
  • 预计算参数 umax:用于加速圆形区域的像素采样,确保方向计算的效率。

关键设计原理

  1. 多尺度处理

    • 通过图像金字塔(mvImagePyramid)实现尺度不变性,高层级检测大尺度特征,低层级检测细节。
    • 特征点邻域大小(PATCH_SIZE)随层级缩放,匹配图像分辨率变化。
  2. 均匀分布策略

    • 网格分块:初步分块检测避免特征点过度集中。
    • 四叉树筛选:二次优化分布,保证每层特征数量与质量。
  3. 效率优化

    • FAST检测加速:网格化检测减少无效区域遍历,双阈值策略平衡速度与鲁棒性。
    • 预计算参数:如 umax 和金字塔图像,减少运行时计算量。

应用场景

  • ORB-SLAM:用于实时特征提取与匹配,支撑相机位姿估计和地图构建。
  • 目标跟踪:均匀分布的特征点提升匹配稳定性,减少误匹配。

扩展说明

  • 浮点坐标问题:尽管代码中关键点坐标为整数,但在高层级金字塔中,坐标经缩放后可能为浮点数(如 mvScaleFactor 作用)。
  • 边界与异常处理:依赖 EDGE_THRESHOLD 避免越界,但未显式处理极端情况(如全图无角点),需前置步骤保证鲁棒性。

以下是ORBextractor::ComputeKeyPointsOctTree函数的逐行注释分析:

  1. 初始化多尺度关键点容器
allKeypoints.resize(nlevels);  // 根据金字塔层数调整容器维度
const float W = 30;           // 网格划分基准宽度
  1. 金字塔层级遍历
for (int level = 0; level < nlevels; ++level) {// 计算有效检测区域边界(EDGE_THRESHOLD通常取19像素)const int minBorderX = EDGE_THRESHOLD-3;  // 左边界留3像素缓冲const int minBorderY = minBorderX;        // 上边界同理const int maxBorderX = mvImagePyramid[level].cols-EDGE_THRESHOLD+3;  // 右有效边界const int maxBorderY = mvImagePyramid[level].rows-EDGE_THRESHOLD+3;  // 下有效边界
  1. 网格化特征检测
    vector<cv::KeyPoint> vToDistributeKeys;vToDistributeKeys.reserve(nfeatures*10);  // 预分配10倍特征数空间const float width = (maxBorderX-minBorderX);const float height = (maxBorderY-minBorderY);const int nCols = width/W;        // 水平网格数const int nRows = height/W;       // 垂直网格数const int wCell = ceil(width/nCols);  // 实际网格宽度(向上取整)const int hCell = ceil(height/nRows); // 实际网格高度
  1. 网格遍历与FAST检测
    for(int i=0; i<nRows; i++) {const float iniY = minBorderY + i*hCell;  // 网格起始Y坐标float maxY = iniY + hCell + 6;            // 网格终止Y坐标(+6扩展检测范围)// 边界溢出处理if(iniY >= maxBorderY-3) continue;if(maxY > maxBorderY) maxY = maxBorderY;for(int j=0; j<nCols; j++) {const float iniX = minBorderX + j*wCell;  // 网格起始X坐标float maxX = iniX + wCell + 6;            // 网格终止X坐标// 边界溢出处理if(iniX >= maxBorderX-6) continue;if(maxX > maxBorderX) maxX = maxBorderX;
  1. 双阈值FAST检测策略
            vector<cv::KeyPoint> vKeysCell;// 先使用初始阈值iniThFAST检测FAST(mvImagePyramid[level].rowRange(iniY,maxY).colRange(iniX,maxX),vKeysCell, iniThFAST, true);  // true表示使用非极大值抑制// 若未检测到,改用更低阈值minThFASTif(vKeysCell.empty()) {FAST(mvImagePyramid[level].rowRange(iniY,maxY).colRange(iniX,maxX),vKeysCell, minThFAST, true);}
  1. 关键点坐标校正
            if(!vKeysCell.empty()) {for(auto vit=vKeysCell.begin(); vit!=vKeysCell.end(); vit++) {(*vit).pt.x += j*wCell;  // X坐标恢复全局坐标系(*vit).pt.y += i*hCell;  // Y坐标恢复全局坐标系vToDistributeKeys.push_back(*vit);  // 存入待分配容器}}
  1. 八叉树关键点分布
        vector<KeyPoint> & keypoints = allKeypoints[level];keypoints.reserve(nfeatures);// 执行四叉树分配算法(关键步骤)keypoints = DistributeOctTree(vToDistributeKeys, minBorderX, maxBorderX,minBorderY, maxBorderY, mnFeaturesPerLevel[level], level);
  1. 关键点属性赋值
        const int scaledPatchSize = PATCH_SIZE*mvScaleFactor[level];for(int i=0; i<keypoints.size(); i++) {keypoints[i].pt.x += minBorderX;  // 补偿初始偏移量keypoints[i].pt.y += minBorderY;keypoints[i].octave = level;      // 记录金字塔层级keypoints[i].size = scaledPatchSize;  // 特征点邻域直径(尺度自适应)}
  1. 方向计算
    // 对所有层关键点计算主方向for (int level = 0; level < nlevels; ++level)computeOrientation(mvImagePyramid[level], allKeypoints[level], umax);
}

核心设计解析

  • 网格化检测:通过30x30网格划分实现特征点初步均匀分布,避免特征聚集
  • 双阈值策略:先使用较高阈值(iniThFAST)确保质量,失败后降阈值(minThFAST)保证数量
  • 边界缓冲:±3像素的边界处理既避免越界,又保证边缘特征的有效提取
  • 坐标校正:将网格局部坐标转换为金字塔层全局坐标,保持空间一致性
  • 八叉树分配:通过递归区域分割和响应值排序,实现特征点最优空间分布
  • 尺度自适应:scaledPatchSize根据金字塔缩放系数调整邻域大小,实现尺度不变性

注:EDGE_THRESHOLD的取值(通常为19)与ORB描述子计算相关,保证特征点周围有足够区域计算描述子。computeOrientation使用灰度质心法计算特征方向,umax为模式匹配预计算表。

http://www.dtcms.com/wzjs/43375.html

相关文章:

  • 网站建设空间主机的选择汉中seo培训
  • 做网站链接要多少钱百度推广运营这个工作好做吗
  • 银川网站建设哪家好b站推广网站mmmnba
  • 网站开发怎样实现上传视频武汉seo技术
  • 做网站用什么云服务器竞价托管收费标准
  • 建设一个网站需要哪些软硬件条件昆山网站制作公司
  • axure做网站原型教程网络营销策划的内容
  • 网站建设的客户都在哪里东莞seo顾问
  • 包头住房与城乡建设局网站成年学校培训班
  • 顺德网站建设seo培训机构哪家好
  • 西乡网站开发营销推广网
  • WordPress添加CA百度搜索关键词排名优化推广
  • 如何判断网站seo做的好坏5118站长网站
  • 网站建设品爱站工具包官网
  • 网站建设的任务运营是做什么的
  • 网站建设与管理 吴代文百度客服怎么转人工电话
  • 福建设计招聘网站自有品牌如何推广
  • css做网站常用软文推广新闻发布
  • 这里是我做的网站链接平台
  • 宁波网站建设开发公司专门做排名的软件
  • 高端网站设计元素图片逆冬seo
  • 怎么样做国外推广网站百度数据研究中心
  • 网站建设找哪个好外包seo公司
  • wordpress 主题 小说昆明seo案例
  • 中学生制作的网站知乎推广公司
  • wordpress 插件配置seo关键字优化软件
  • 顺德销售型网站建设江门网站定制多少钱
  • 微网站建站系统源码广州seo效果
  • 自己做网站怎么搜索广州线下教学
  • 同时优化几个网站推广普通话的内容