【SVO】klt與極限搜索塊匹配findEpipolarMatchDirect

Matcher::findEpipolarMatchDirect 函數邏輯與原理分析

核心目標

在極線上搜索參考幀特征點 ref_ftr 在當前幀 cur_frame 中的最佳匹配點,并通過三角化計算深度。


關鍵步驟解析

1. 極線端點計算
const BearingVector A = T_cur_ref.getRotation().rotate(ref_ftr.f) + T_cur_ref.getPosition() * d_min_inv;
const BearingVector B = T_cur_ref.getRotation().rotate(ref_ftr.f) + T_cur_ref.getPosition() * d_max_inv;
cur_frame.cam()->project3(A, &px_A);  // 投影到當前幀像素坐標
cur_frame.cam()->project3(B, &px_B);
epi_image_ = px_A - px_B;  // 極線方向向量
  • 原理:利用深度倒數范圍 [d_min_inv, d_max_inv] 計算參考幀特征點對應的3D點在當前幀中的投影范圍(px_A, px_B)。
  • 作用:確定極線搜索區間。
2. 仿射扭曲矩陣計算
warp::getWarpMatrixAffine(ref_frame.cam_, cur_frame.cam_, ref_ftr.px, ref_ftr.f,1.0 / d_estimate_inv, T_cur_ref, ref_ftr.level, &A_cur_ref_);
  • 原理:根據兩幀間位姿變換 T_cur_ref 和深度估計值,計算參考幀到當前幀的仿射變換矩陣 A_cur_ref_
  • 作用:補償視角變化導致的圖像變形。
3. 邊緣特征方向過濾
if (isEdgelet(ref_ftr.type) {const Eigen::Vector2d grad_cur = (A_cur_ref_ * ref_ftr.grad).normalized();const double cosangle = fabs(grad_cur.dot(epi_image_.normalized()));if (cosangle < options_.epi_search_edgelet_max_angle) return MatchResult::kFailAngle;  // 邊緣方向與極線夾角過大
}
  • 原理:邊緣特征的梯度方向應與極線方向一致(夾角小)。
  • 作用:過濾掉梯度方向與極線方向不一致的邊緣特征,提升匹配魯棒性。
4. 圖像金字塔預處理
search_level_ = warp::getBestSearchLevel(A_cur_ref_, ref_frame.img_pyr_.size() - 1);
epi_length_pyramid_ = epi_image_.norm() / (1 << search_level_);
  • 原理:根據仿射矩陣尺度選擇最佳金字塔層級 search_level_,并計算該層級的極線長度。
  • 作用:在粗分辨率上快速搜索,減少計算量。
5. 參考圖像塊扭曲
warp::warpAffine(A_cur_ref_, ref_frame.img_pyr_[ref_ftr.level], ...);
patch_utils::createPatchFromPatchWithBorder(...);  // 提取參考圖像塊
  • 原理:將參考幀中的圖像塊通過仿射變換 A_cur_ref_ 扭曲到當前幀視角。
  • 作用:生成用于匹配的模板圖像塊 patch_
6. 極線搜索策略
  • 情況1:極線過短(epi_length_pyramid_ < 2.0
    px_cur_ = (px_A + px_B) / 2.0;  // 取極線中點
    findLocalMatch(cur_frame, epi_dir_image, search_level_, px_cur_);  // 局部搜索
    
  • 情況2:極線較長
    PatchScore patch_score(patch_);  // 預計算參考圖像塊評分
    scanEpipolarLine(cur_frame, A, B, C, patch_score, ...);  // 沿極線掃描
    
  • 原理
    • 短極線:直接在極線中點附近局部搜索。
    • 長極線:在極線上滑動參考圖像塊,通過 ZMSSD(零均值平方和差) 計算匹配得分,選擇得分最高的位置。
7. 匹配驗證與優化
if (zmssd_best < PatchScore::threshold()) {if (options_.subpix_refinement) findLocalMatch(...);  // 亞像素優化cur_frame.cam()->backProject3(px_cur_, &f_cur_);  // 反投影到3DdepthFromTriangulation(T_cur_ref, ref_ftr.f, f_cur_, &depth);  // 三角化深度
}
  • 原理
    • 亞像素優化:在粗匹配位置附近進行高斯牛頓迭代,提升精度。
    • 三角化:利用兩幀間位姿和匹配點光線,求解3D點深度。

失敗處理

失敗原因返回值觸發條件
邊緣特征方向與極線夾角過大MatchResult::kFailAngle夾角余弦值小于閾值 epi_search_edgelet_max_angle
圖像塊扭曲失敗MatchResult::kFailWarpwarpAffine 返回失敗
匹配得分不足MatchResult::kFailScore最佳 ZMSSD 得分超過閾值

關鍵算法與技巧

  1. 仿射光流(Affine Warping)
    • 補償視角變化,使圖像塊在不同幀間保持形狀一致。
  2. 金字塔搜索(Pyramid Search)
    • 在低分辨率圖像上快速定位,逐步細化到高分辨率。
  3. 極線約束(Epipolar Constraint)
    • 將搜索范圍從整幅圖像壓縮到一條直線,減少計算量。
  4. ZMSSD 匹配度量
    • 對光照變化魯棒:通過減去圖像塊均值,消除亮度差異影響。
  5. 亞像素優化(Subpixel Refinement)
    • 通過二次擬合或高斯牛頓法,使匹配精度達到亞像素級別。

代碼流程總結

在這里插入圖片描述

此函數實現了高效且魯棒的直接法特征匹配,適用于視覺里程計(VO)和SLAM系統中的特征跟蹤與深度估計。

    Matcher::MatchResult Matcher::findEpipolarMatchDirect(const Frame& ref_frame,const Frame& cur_frame,const Transformation& T_cur_ref,const FeatureWrapper& ref_ftr,const double d_estimate_inv,const double d_min_inv,const double d_max_inv,double& depth){int zmssd_best = PatchScore::threshold();// Compute start and end of epipolar line in old_kf for match search, on image planeconst BearingVector A = T_cur_ref.getRotation().rotate(ref_ftr.f) + T_cur_ref.getPosition() * d_min_inv;const BearingVector B = T_cur_ref.getRotation().rotate(ref_ftr.f) + T_cur_ref.getPosition() * d_max_inv;Eigen::Vector2d px_A, px_B;cur_frame.cam()->project3(A, &px_A);cur_frame.cam()->project3(B, &px_B);epi_image_ = px_A - px_B;//LOG(INFO) << "A:" << A;//LOG(INFO) << "B:" << B;//LOG(INFO) << "px_A:" << px_A;//LOG(INFO) << "px_B:" << px_B;// Compute affine warp matrixwarp::getWarpMatrixAffine(ref_frame.cam_, cur_frame.cam_, ref_ftr.px, ref_ftr.f,1.0 / std::max(0.000001, d_estimate_inv), T_cur_ref, ref_ftr.level, &A_cur_ref_);// feature pre-selectionreject_ = false;if (isEdgelet(ref_ftr.type) && options_.epi_search_edgelet_filtering){const Eigen::Vector2d grad_cur = (A_cur_ref_ * ref_ftr.grad).normalized();const double cosangle = fabs(grad_cur.dot(epi_image_.normalized()));if (cosangle < options_.epi_search_edgelet_max_angle){reject_ = true;return MatchResult::kFailAngle;}}//LOG(INFO) << "A_cur_ref_: " << A_cur_ref_;// prepare for match//    - find best search level//    - warp the reference patchsearch_level_ = warp::getBestSearchLevel(A_cur_ref_, ref_frame.img_pyr_.size() - 1);// length and direction on SEARCH LEVELepi_length_pyramid_ = epi_image_.norm() / (1 << search_level_);GradientVector epi_dir_image = epi_image_.normalized();if (!warp::warpAffine(A_cur_ref_, ref_frame.img_pyr_[ref_ftr.level], ref_ftr.px,ref_ftr.level, search_level_, kHalfPatchSize + 1, patch_with_border_))return MatchResult::kFailWarp;patch_utils::createPatchFromPatchWithBorder(patch_with_border_, kPatchSize, patch_);// Case 1: direct search locally if the epipolar line is too shortif (epi_length_pyramid_ < 2.0){px_cur_ = (px_A + px_B) / 2.0;MatchResult res = findLocalMatch(cur_frame, epi_dir_image, search_level_, px_cur_);if (res != MatchResult::kSuccess)return res;cur_frame.cam()->backProject3(px_cur_, &f_cur_);f_cur_.normalize();return matcher_utils::depthFromTriangulation(T_cur_ref, ref_ftr.f, f_cur_, &depth);}// Case 2: search along the epipolar line for the best matchPatchScore patch_score(patch_); // precompute for reference patchBearingVector C = T_cur_ref.getRotation().rotate(ref_ftr.f) + T_cur_ref.getPosition() * d_estimate_inv;//LOG(INFO) << "C: " << C;//LOG(INFO) << "px_cur_: " << std::setprecision(15) << px_cur_.transpose();scanEpipolarLine(cur_frame, A, B, C, patch_score, search_level_, &px_cur_, &zmssd_best);//LOG(INFO) << "zmssd_best: " << zmssd_best;// check if the best match is good enoughif (zmssd_best < PatchScore::threshold()){if (options_.subpix_refinement){MatchResult res = findLocalMatch(cur_frame, epi_dir_image, search_level_, px_cur_);if (res != MatchResult::kSuccess)return res;}//LOG(INFO) << "BACK PROJECT";cur_frame.cam()->backProject3(px_cur_, &f_cur_);f_cur_.normalize();//LOG(INFO) << "f_cur_ NORM: " <<std::setprecision(15)<< f_cur_.x() <<" " << f_cur_.y() << " " << f_cur_.z();//LOG(INFO) << "T_cur_ref: \n" << std::setprecision(15) << T_cur_ref;//LOG(INFO) << "ref_ftr.f: " << std::setprecision(15) << ref_ftr.f.transpose();return matcher_utils::depthFromTriangulation(T_cur_ref, ref_ftr.f, f_cur_, &depth);}elsereturn MatchResult::kFailScore;}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/87644.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/87644.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/87644.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C 語言基礎入門:基本數據類型與運算符詳解

一、基本數據類型C 語言提供了豐富的基本數據類型&#xff0c;用于存儲不同類型的數據&#xff0c;主要包括整數類型、浮點類型和布爾類型。1. 整數類型整數類型用于存儲整數&#xff0c;根據是否帶符號以及占用存儲空間的不同&#xff0c;可進一步細分&#xff1a;類型名占用存…

應用在核電行業的虛擬現實解決方案

核能領域正處于創新與責任的交匯點。盡管核反應堆提供了高效且可持續的能源&#xff0c;但由于放射性物質的危險性&#xff0c;其也帶來了獨特挑戰。虛擬現實&#xff08;VR&#xff09;技術正通過為遠程操作、應急響應和放射性物質處理提供先進解決方案&#xff0c;徹底革新這…

CTF Web的數組巧用

PHP數組繞過intval和preg_match的CTF技巧 原題目 <?php include("flag.php"); // 引入flag文件&#xff0c;flag變量在這里定義 show_source("index.php"); // 顯示index.php文件的源碼&#xff08;方便選手查看&#xff09;// 判斷是否通過GET方式傳入…

vue2+elementui使用compressorjs壓縮上傳的圖片

首先是npm install compressorjs 然后新建一個compressorjs.js的文件 import Compressor from "compressorjs";// 默認壓縮配置 const DEFAULT_COMPRESS_OPTIONS {quality: 0.6, // 默認壓縮質量 (0-1)maxWidth: 1920, // 最大寬度maxHeight: 1080, // 最大高度con…

GPIO詳解:不僅僅是輸入輸出那么簡單

GPIO詳解&#xff1a;不僅僅是輸入輸出那么簡單 “別小看一個小小的引腳&#xff0c;它可是 MCU 世界的社交之門。” &#x1f44b; 先打個招呼&#xff1a;什么是 GPIO&#xff1f; GPIO&#xff0c;全稱是 General Purpose Input/Output —— 通用輸入輸出口。 簡單說&…

深度學習5(深層神經網絡 + 參數和超參數)

深層神經網絡簡介 深層神經網絡是機器學習中一種重要的模型&#xff0c;它通過增加網絡的“深度”&#xff08;即隱藏層的數量&#xff09;來提升模型對復雜數據的表示和學習能力。同淺層類似&#xff0c;也分為三個部分&#xff1a; 輸入層&#xff1a;接收原始數據&#xff…

時間復雜度與空間復雜度分析

一、什么是復雜度&#xff1f; 1.1 為什么需要復雜度分析&#xff1f; 假設你寫了兩個程序來解決同一個問題&#xff0c;如何判斷哪個程序更好&#xff1f;我們不能只看運行時間&#xff0c;因為&#xff1a; 不同電腦性能不同同一電腦在不同時刻狀態也不同數據規模不同&#x…

上下文工程:從提示詞到自動化流程的AI應用新范式

上下文工程&#xff1a;從提示詞到自動化流程的 AI 應用新范式 一、背景與概述&#xff1a;從提示詞工程到上下文工程的演進 隨著大語言模型 (LLM) 技術的飛速發展&#xff0c;AI 應用開發正經歷從 “提示詞工程”(Prompt Engineering) 到 “上下文工程”(Context Engineerin…

HTML網頁應用打包Android App 完整實踐指南

技術準備與工具下載 必需工具清單 在開始之前&#xff0c;需要準備以下開發工具&#xff1a; Android Studio官網&#xff1a;https://developer.android.com/studio HBuilderX官網&#xff1a;https://www.dcloud.io/hbuilderx.html 離線SDK下載&#xff1a;https://nati…

簡單 Python 爬蟲程序設計

爬蟲是獲取網頁數據的常用工具&#xff0c;我們一起來設計一個基于 requests 和 BeautifulSoup 的簡單爬蟲&#xff0c;它可以獲取網頁內容并提取文本信息。 所需庫安裝 首先需要安裝兩個必要的庫&#xff1a; pip install requests beautifulsoup4 完整代碼 import reques…

AUTOSAR圖解==>AUTOSAR_AP_EXP_ARAComAPI

AUTOSAR ara::com API詳解 自適應平臺通信API技術詳解 目錄 1. 概述2. ara::com API架構 2.1 Proxy/Skeleton架構2.2 通信方式2.3 服務連接方式 3. 詳細API說明 3.1 Proxy類3.2 Skeleton類3.3 實例標識符3.4 通信組 4. ara::com API狀態管理 4.1 服務生命周期4.2 事件與方法狀…

Spring Boot + 本地部署大模型實現:優化與性能提升

在將大語言模型集成到 Spring Boot 應用中時&#xff0c;性能優化是一個關鍵環節。本地部署的大模型雖然提供了強大的功能&#xff0c;但也可能帶來一些性能挑戰&#xff0c;如響應時間較長、資源占用較高等問題。本文將介紹如何在 Spring Boot 應用中優化本地部署大模型的性能…

QML 鼠標只響應左鍵處理方法

【1】問題描述 默認情況下qml支持左鍵&#xff0c;如果需要支持右鍵&#xff0c;甚至是中鍵那需要設置 【2】設置方法 MouseArea{ id: mouse anchors.fill: parent property int cx: 0 pr…

北方算網亮相2025全球數字經濟大會|共繪數字友好城市建設

7月2日&#xff0c;以“建設數字友好城市”為主題的2025全球數字經濟大會隆重開幕&#xff0c;為構建技術與人、城市與生態和諧共進的全球數字經濟新生態提供交流合作平臺。自7月3日開始&#xff0c;北方算網將在大會集中亮相&#xff0c;先后在多個論壇中發表主題演講&#xf…

Android PNG/JPG圖ARGB_8888/RGB_565?解碼形成Bitmap在物理內存占用大小的簡單計算

Android PNG/JPG圖ARGB_8888/RGB_565?解碼形成Bitmap在物理內存占用大小的簡單計算 Android的Bitmap 是一個用于表示圖像數據的核心類&#xff0c;代表一張圖片在內存中的存儲&#xff0c;Bitmap存儲了圖像的像素信息數據。 Bitmap把圖像理解為像素點組成的二維矩陣&#xff…

力扣網編程55題:跳躍游戲之逆向思維

一. 簡介 前面一篇文章使用貪心算法解決 力扣網55題&#xff1a;跳躍游戲&#xff0c;文章如下&#xff1a; 力扣網編程55題&#xff1a;跳躍游戲之貪心算法-CSDN博客 二. 力扣網編程55題&#xff1a;跳躍游戲之逆向思維 給你一個非負整數數組 nums &#xff0c;你最初位于數…

蒼穹外賣--day12數據統計-Excel報表

1.工作臺1.1實現思路工作臺是系統運營的數據看板&#xff0c;并提供快捷操作入口&#xff0c;可以有效提高商家的工作效率。工作臺展示的數據&#xff1a;①今日數據②訂單管理③菜品總覽④套餐總覽⑤訂單信息名詞解釋&#xff1a;①營業額&#xff1a;已經完成訂單的總金額②有…

鴻蒙應用開發:從網絡獲取數據

一、網絡狀態概述上述任一指標的變化均可視為網絡狀態的改變 二、獲取網絡信息 創建網絡對象 //創建網絡對象 //?表示可傳可不傳 connection.createNetConnection(netSpecifier?:NetSpecifier,timeout?:number):NetConnection;獲取默認激活網絡及其能力 //獲取默認激活網絡 …

探索開源虛擬 Excel 函數模塊:Python 中的 Excel 功能利器

在數據處理和分析的領域中&#xff0c;Excel 一直是一款備受青睞的工具&#xff0c;它提供了豐富多樣的函數&#xff0c;幫助用戶高效地完成各種數據操作。而現在&#xff0c;我&#xff08;董翔&#xff09;開發一個基于 Python 的虛擬 Excel 函數模塊&#xff0c;它將 Excel …

開源 vGPU 方案 HAMi: corememory 隔離測試

本文主要對開源的 vGPU 方案 HAMi 的 GPU Core&Memory 隔離功能進行測試。 省流&#xff1a; HAMi vGPU 方案提供的 Core&Memory 隔離基本符合預期&#xff1a; Core 隔離&#xff1a;Pod 能使用的算力會圍繞設定值波動&#xff0c;但是一段時間內平均下來和申請的 g…