_detectInitialCandidates
?是 OpenCV 的 ArUco 模塊中一個非常關鍵的函數,它負責檢測圖像中的候選 ArUco 標記。該函數的主要目標是:
- 使用多個尺度(scale)對輸入圖像進行自適應閾值處理;
- 在每個尺度下提取輪廓并篩選出符合要求的四邊形角點;
- 將這些候選標記及其對應的輪廓保存到輸出參數中。
📌 函數簽名
static void _detectInitialCandidates(const Mat &grey,vector<vector<Point2f> > &candidates,vector<vector<Point> > &contours,const DetectorParameters ¶ms)
參數說明:
參數名 | 類型 | 含義 |
---|---|---|
grey | const Mat & | 輸入的灰度圖像 |
candidates | vector<vector<Point2f> > & | 輸出的候選標記角點(4個點組成的矩形) |
contours | vector<vector<Point> > & | 輸出的與候選角點對應的完整輪廓信息 |
params | const DetectorParameters & | 檢測器參數,控制檢測過程的行為 |
🔍 功能詳解
1???設置自適應閾值窗口大小范圍
CV_Assert(params.adaptiveThreshWinSizeMin >= 3 && params.adaptiveThreshWinSizeMax >= 3);
CV_Assert(params.adaptiveThreshWinSizeMax >= params.adaptiveThreshWinSizeMin);
CV_Assert(params.adaptiveThreshWinSizeStep > 0);
確保傳入的參數合法:
- 自適應閾值窗口最小和最大尺寸 ≥ 3(OpenCV 要求)
- 步長必須大于 0
2???計算要使用的窗口大小數量(即圖像金字塔層數)
int nScales = (params.adaptiveThreshWinSizeMax - params.adaptiveThreshWinSizeMin) /params.adaptiveThreshWinSizeStep + 1;
根據設定的最小、最大窗口大小和步長,計算需要嘗試多少種不同的窗口大小。
例如:min=20
,?max=40
,?step=5
?→?nScales = 5
3???為每種窗口大小準備容器
vector<vector<vector<Point2f> > > candidatesArrays((size_t) nScales);
vector<vector<vector<Point> > > contoursArrays((size_t) nScales);
candidatesArrays[i]
:第 i 個窗口大小下的所有候選標記角點集合。contoursArrays[i]
:對應的所有輪廓。
4???多線程處理不同尺度(parallel_for_)
parallel_for_(Range(0, nScales), [&](const Range& range) {for (int i = begin; i < end; i++) {int currScale = params.adaptiveThreshWinSizeMin + i * params.adaptiveThreshWinSizeStep;Mat thresh;_threshold(grey, thresh, currScale, params.adaptiveThreshConstant);_findMarkerContours(thresh, candidatesArrays[i], contoursArrays[i],params.minMarkerPerimeterRate, params.maxMarkerPerimeterRate,params.polygonalApproxAccuracyRate, params.minCornerDistanceRate,params.minSideLengthCanonicalImg);}
});
對于每一個窗口大小:
- 調用?
_threshold()
?進行自適應閾值處理:- 用于將圖像二值化,便于后續提取輪廓。
- 調用?
_findMarkerContours()
?提取輪廓并篩選出可能的 ArUco 標記角點:- 篩選條件包括:周長范圍、是否為凸四邊形、角點距離等。
5???合并所有尺度的結果
for(int i = 0; i < nScales; i++) {for(unsigned int j = 0; j < candidatesArrays[i].size(); j++) {candidates.push_back(candidatesArrays[i][j]);contours.push_back(contoursArrays[i][j]);}
}
將不同尺度下檢測到的候選標記統一合并到最終輸出變量?candidates
?和?contours
?中。
🧠 關鍵輔助函數說明
??_threshold()
static void _threshold(InputArray _in, OutputArray _out, int winSize, double constant)
- 使用?
adaptiveThreshold()
?對圖像進行自適應二值化。 - 確保窗口大小為奇數。
- 采用?
ADAPTIVE_THRESH_MEAN_C
?方法,反向二值化 (THRESH_BINARY_INV
)。
??_findMarkerContours()
static void _findMarkerContours(const Mat &in,vector<vector<Point2f> > &candidates,vector<vector<Point> > &contoursOut,double minPerimeterRate,double maxPerimeterRate,double accuracyRate,double minCornerDistanceRate,int minSize)
這個函數負責從二值圖像中提取輪廓,并篩選出可能是 ArUco 標記的四邊形。
主要步驟:
-
查找所有輪廓
findContours(in, contours, RETR_LIST, CHAIN_APPROX_NONE);
-
逐個輪廓篩選
- 周長在指定范圍內;
- 多邊形逼近后為凸四邊形;
- 四個角點之間最小距離滿足要求;
- 如果啟用 ArUco3 功能,則額外判斷最小邊長。
-
將符合條件的輪廓加入輸出
- 角點存入?
candidates
- 完整輪廓存入?
contoursOut
- 角點存入?
📈 總結流程圖
_detectInitialCandidates()
│
├─ 設置參數檢查
│
├─ 計算使用多少種窗口大小(nScales)
│
├─ 并行遍歷每個窗口大小:
│ ├─ 圖像二值化(_threshold)
│ └─ 提取并篩選候選標記(_findMarkerContours)
│ ├─ 查找輪廓
│ ├─ 篩選輪廓(凸四邊形、周長、角點距離等)
│ └─ 添加進臨時容器
│
└─ 合并所有窗口大小下的結果到輸出
🧰 參數影響分析(DetectorParameters)
參數名 | 作用 |
---|---|
adaptiveThreshWinSizeMin | 最小閾值窗口大小,決定最小可檢測標記大小 |
adaptiveThreshWinSizeMax | 最大閾值窗口大小,決定最大可檢測標記大小 |
adaptiveThreshWinSizeStep | 窗口大小遞增步長 |
minMarkerPerimeterRate | 最小周長比例(相對于圖像寬度/高度) |
maxMarkerPerimeterRate | 最大周長比例 |
polygonalApproxAccuracyRate | 多邊形逼近精度比例 |
minCornerDistanceRate | 角點間最小距離比例 |
minSideLengthCanonicalImg | ArUco3 功能中最小邊長限制 |
📝 示例說明
假設你有如下代碼調用:
Mat grey = ...; // 輸入灰度圖
vector<vector<Point2f>> candidates;
vector<vector<Point>> contours;
DetectorParameters params = DetectorParameters::create();
_detectInitialCandidates(grey, candidates, contours, params);
這段代碼會:
- 使用多個窗口大小對圖像進行自適應閾值;
- 提取輪廓并篩選出潛在的 ArUco 標記;
- 返回所有候選標記的四個角點坐標及其原始輪廓。
? 總結
特性 | 描述 |
---|---|
功能 | 檢測圖像中所有可能的 ArUco 標記候選區域 |
輸入 | 灰度圖像、檢測參數 |
輸出 | 候選角點列表、對應輪廓列表 |
關鍵技術 | 自適應閾值、輪廓檢測、多邊形逼近、幾何篩選 |
性能優化 | 使用?parallel_for_?實現多線程加速 |
后續處理 | 通常交給?_reorderCandidatesCorners() ?排序角點順序 |