使用 Kernel#
閱讀完這個主題後,您將了解如何建構一個核心、使用濾波運算子對其進行處理,並在 DmaToPC.
核心結構#
核(kernel)是指影像中某個位置周圍鄰近像素值所構成的小範圍區域。許多濾波器——例如降噪、模糊、邊緣偵測——都會根據該鄰域來計算出新的輸出值。
對於 3×3 核,該視窗包含九個值:該位置的當前像素以及八個鄰近像素。若核的大小為奇數,當前像素則位於視窗的中央。
核函數會從左至右,一行一行地在圖像上移動。在每個位置,濾波器都會使用該像素周圍的鄰域:

在 `VisualApplets` 中,該區域是由連結屬性所定義的。視窗的建構方式,以及當前像素在視窗中的位置,取決於運算子。相關細節如下所述。
核心欄與核心列#
核心大小是 連結屬性. KernelColumns 是鄰域視窗的寬度。 KernelRows 即其高度。因此,一個 3×3 核會使用 KernelColumns = 3 且 KernelRows = 3.

在VisualApplets 中,N 代表核函數的行數,M 代表核函數的列數。核函數的元素是透過索引而非座標來定位的。索引的遍歷方向為逐行進行,從左上角到右下角。
請務必查閱運算子文件,以確認核心索引與影像位置之間的確切對應關係。
並非每個運算子都接受或轉發大於 1×1 的核心。每個運算子都會在其文件中記載允許的值, Supported Link Format 表格位於 Operator 參考手冊. 若將核心連結連接到僅允許 Kernel Columns = 1 進行明確的生命週期管理即呼叫 Kernel Rows = 1,VisualApplets 回報連結格式衝突。
如需了解所有連結屬性的概覽,請參閱「參數化教學」主題。
內核與Parallelism#
Parallelism 「內核」和「核心」雖然都能增加連結在每個時鐘週期內傳輸的數據量,但它們所描述的概念卻不同:
| Parallelism | 核心 | |
|---|---|---|
| 問題 | 每個時脈週期會傳輸多少個獨立像素? | 一個位置對應多少個鄰接值? |
| 典型用途 | 匹配攝影機/DMA 頻寬 | 需要鄰近區域的餵食過濾器 |
| 連結屬性 | Parallelism | KernelColumns, KernelRows |
您可以將並行度維持在 1,同時透過使用核心來增加每時鐘週期的資料傳輸量:連結會將一個鄰域(例如 3×3 個值)作為一個資料字來傳輸。每時鐘週期的資料量增加,是因為每時鐘週期傳輸的值更多,而非因為每時鐘週期處理了更多新的影像位置。本 Parallelism 教學主題中的像素速率頻寬公式中,並未乘以核大小。
您也可以將兩者結合使用。運算子 CastKernel 只要該乘積保持不變,即可重新詮釋輸入與輸出間的並行度與核心大小的乘積。例如,並行度為 1 且核心大小為 3×2 的情況,可以轉變為並行度為 6 且核心大小為 1×1 的情況。

詳情請參閱《運算子參考》中的CastKernel以及 Parallelism 教學主題中的 CastKernel 說明。
編譯核心#
若要從一般的像素流中產生鄰域資料,請使用能在其上設定核大小(kernel size)的運算子 輸出 連結。 FIRkernelNxM 建立一個居中的 2D 核心視窗。 LineNeighboursNx1 進行明確的生命週期管理即呼叫 PixelNeighbours1xM 屬於特殊情況:它們收集的是前幾行或前幾個像素,而非以中心為基準的視窗。這些運算子的差異在於當前像素的位置、運算子類型、FPGA 資源消耗與延遲,以及邊緣處理方式(詳見下文)。請根據您的使用情境選擇合適的運算子:以中心為基準的 2D 濾波鄰域、對前幾行或前幾個像素的比較,或是相較於完整的 FIR 風格視窗更節省資源的替代方案。
FIRkernelNxM#
此運算子 FIRkernelNxM (library Filter) 會在每個像素周圍建立一個矩形核窗,其中包含鄰近像素。儘管名稱如此,它實際上 不是 實作一個 FIR 濾波器。它會準備濾波運算子所需的核資料。對於奇數大小的核,當前像素位於 中心 的核。對於大小為偶數的核,並不存在精確的中心;中心位置會偏移至左上方。
使用 3×3 平均濾波器進行平滑處理:

此設計建構了一個居中的 3×3 鄰域,其中包含 FIRkernelNxM (Filterkernel),並與其求平均值,即 FIRoperatorNxM (Average),然後對結果進行縮放,並將其轉換回 8 位元。模擬探測會比較平均運算前後的像素值:原本銳利的局部峰值會變得更平滑,數值也更趨於均勻。
您可以透過編輯輸出連結來設定核心大小(Kernel Columns 進行明確的生命週期管理即呼叫 Kernel Rows). 該運算子會將所需的像素暫存於緩衝區中,直到完整的鄰域皆可取得為止。在影像邊界處,可能會缺少鄰域像素。參數 EdgeHandling 指定如何填補缺失值(EdgeMirrored 或 EdgeConstant)。
FIRkernelNxM 是一個 M型 運算子。建立如 3×3 般的居中鄰域需要緩衝處理,因此相較於下文所述的線鄰域或像素鄰域運算子,會消耗更多 FPGA 資源並增加更多延遲。使用 FIRkernelNxM 當一個篩選器確實需要一個 居中 2D 鄰域 — 例如之前 FIRoperatorNxM 用於模糊處理、平均運算或邊緣偵測。
有關此運算子的詳細資訊,請參閱《運算子參考手冊》中的「FIRkernelNxM」。
LineNeighboursNx1 進行明確的生命週期管理即呼叫 PixelNeighbours1xM#
LineNeighboursNx1 進行明確的生命週期管理即呼叫 PixelNeighbours1xM 屬於一種特殊情況。它們並不會以通常意義上所指的方式建構居中核心。
LineNeighboursNx1 建立一個具有 N 行和 1 列的核。當前像素位於 核心索引 0;其餘元素則是來自前幾行(上方)的像素。 PixelNeighbours1xM 建立一個由 1 行和 M 列組成的核心。當前像素再次位於 核心索引 0;其餘元素則是同一行上(左側)的先前像素。
有別於 FIRkernelNxM, 這些運算子會 不是 將當前像素置於中心,且不提供尚未處理的「未來」鄰域像素。它們僅檢視 過去 (前幾行或前幾個像素)。它們是 O型 運算子,且不會因緩衝居中鄰域而產生行或像素延遲。這使得它們比以下方法更為簡單,且通常在 FPGA 資源消耗上更為節省: FIRkernelNxM. 您仍可形成更大的鄰域——例如將兩個運算子合併為 3×3 視窗——但在線條或影像的起始處,過去的鄰域資料尚未可用,因此這些核函數元素會保持為空,直到收集到足夠的歷史資料為止。影像邊界外的缺失像素會被設定為參數 Constant;沒有鏡像邊緣處理。
典型應用情境:
-
比較或減少各處的數值 前幾行 與
LineNeighboursNx1— 例如,找出當前像素及其上方各行的最小像素值:
-
比較或減少各處的數值 同一行上的前幾個像素 與
PixelNeighbours1xM.
-
向一個縮減運算子(例如
MIN或MAX:這些運算子會對輸入套用一個核函數,從鄰域中選取一個值(例如最小的像素),並輸出一個 1×1 結果。完成該步驟後,會再次解析核心。相鄰行間的最小像素值:

相鄰像素中的最大像素值:

要建立一個二維核函數,您可以將 LineNeighboursNx1 接著是 PixelNeighbours1xM.
有關運算子的詳細資訊,請參閱《運算子參考手冊》中的「LineNeighboursNx1」及「PixelNeighbours1xM」。
ExpandToKernel#
此運算子 ExpandToKernel 將單一像素的輸入擴展至任意大小的核大小。它 複製 每個核心元件的輸入值。您可在輸出鏈結上定義新的核心大小。
使用 ExpandToKernel 當下游運算子預期輸入為一個核心,但您只有一個 單身 像素值 — 例如閾值、平均值或參考像素。常見的做法是擴展該常數或參考值,使其與來自 FIRkernelNxM, LineNeighboursNx1,或 PixelNeighbours1xM. 接著,您可以套用諸如 CMP, SUB,或 ADD 針對整個核函數進行逐元素運算(例如,將每個鄰居元素與同一閾值進行比較)。

有關此運算子的詳細資訊,請參閱《運算子參考指南》中的「ExpandToKernel」。
處理內核#
建立核心後,您可以對其進行篩選、擷取子集、合併或分割核心串流,或是重新排列核心元件。本節中的運算子是用來處理現有核心的。在 DmaToPC, 您必須將核縮減為 1×1 — 請參閱 連線至 DMA.
FIRoperatorNxM#
此運算子 FIRoperatorNxM 將每個核元素乘以一個係數,並將各乘積相加。您可以使用 Coefficients 參數中選擇性地指定 HTML 記錄檔 (*.html) 的路徑與檔名。
該的輸出為 FIRoperatorNxM 該運算子的核心大小為 1×1,這表示每個位置僅會產生一個經過濾波的像素值。使用 FIRkernelNxM, LineNeighboursNx1,或 PixelNeighbours1xM 以產生所需的輸入核心。
當您在連結上已有鄰域,且需要針對每個位置產生一個經過濾波的輸出像素時,請針對經典的 FIR 型濾波器(如平均濾波器、高斯濾波器、索貝爾濾波器及類似濾波器)使用此運算子:

此螢幕截圖顯示了隨VisualApplets 一併提供的設計範例:Examples\Processing\Filter\EdgeDetection\SobelGradientX。
有關此運算子的詳細資訊,請參閱《運算子參考手冊》中的「FIRoperatorNxM」。
SelectSubKernel#
當 SelectSubKernel 此運算子會從輸入核中擷取一個矩形子集。其參數 FirstROW 進行明確的生命週期管理即呼叫 FirstCOL 定義子集的偏移量。新的核大小將設定於輸出連結上。
隨著 SelectSubKernel 你提取該 中央 當您不再需要完整的鄰域時,可僅保留核的元素——通常是該影像位置的原始像素。
一個典型的應用情境是套用濾鏡,同時仍保留 原文 圖片。之後 FIRkernelNxM 在建立鄰域後,您會將核心連結分支。其中一條路徑用於計算過濾後的結果,另一條路徑則使用 SelectSubKernel 以提取一個 1×1 的子核——即該影像位置的原始像素。如此一來,您便同時擁有經過濾波的資料與未經濾波的影像。
將原始影像資料儲存於濾鏡旁:

此設計建構了一個 3×3 的鄰域,其中包含 FIRkernelNxM, 接著是分支。上方的路徑使用 SelectSubKernel 以提取原始像素(1×1 子核)。下方路徑則應用 FIRoperatorNxM 作為索貝爾濾波器。
有關此運算子的詳細資訊,請參閱《運算子參考指南》中的「SelectSubKernel」。
MergeKernel 進行明確的生命週期管理即呼叫 SplitKernel#
此運算子 MergeKernel 將多個輸入連結合併為一個輸出核心。為此,所有輸入的核心必須有一維(行或列)完全一致;輸入的另一維則可以不同。該 Alignment 參數及其值 horizontal 或 vertical 定義了輸入資料如何進行串接。
其逆運算子是 SplitKernel. SplitKernel 將一個 N×M 核函數拆分為 N×M 個獨立的輸出連結,每個連結的核函數大小為 1×1。輸出數量必須等於核函數的成分數,且在實例化該運算子時即已固定。
一個典型的應用案例是將 同一張圖片的幾個版本 — 例如不同的灰階或經過處理的版本 — 整合到同一個核心中,以便您可以一併比較或處理它們。請使用 SplitKernel 當您需要再次將個別核心元件在不同的路徑上進行處理時。
總而言之, MergeKernel 進行明確的生命週期管理即呼叫 SplitKernel 也可以取代原本需要一個 SYNC 運算子: SYNC 通常需要在輸入端設置緩衝區,因此會消耗 FPGA 資源。當資料流可改以內核元件的形式傳輸時,合併與拆分內核往往是更具資源效率的方法。
此範本僅適用於 同一張圖片的幾個版本 這些資料仍源自同一個來源,例如同一台攝影機的影像串流所經由兩種不同的處理方式所產生的結果。請 不是 使用 MergeKernel 以合併兩台獨立的攝影機。獨立的攝影機仍屬非同步來源,且仍需 SYNC (或另一個具有非同步輸入的運算子)以及緩衝區。請參閱 Operator 類型與同步 教學主題。
合併非同步路徑時發生同步錯誤:

在此,兩個分支以不同的方式處理同一張圖像,然後將結果傳入一個共同的 CMP 運算子。由於某條路徑上的 M 型運算子使分支變得非同步,因此VisualApplets 會報告同步錯誤(紫色連結)——您無法直接將它們連接起來。此範例仍僅涉及一台攝影機,而非兩台獨立的攝影機。
透過緩衝區和 SYNC 解決同步錯誤:

一個有效的解決方法是放置一個 ImageFifo 在每個路徑上 (或另一個緩衝區),並與 SYNC 之前 CMP. 雖然這樣可行,但額外的緩衝區會消耗 FPGA 資源。
透過 MergeKernel 和 SplitKernel 解決同步錯誤:

這種資源效率較高的替代方案將這兩種變體都作為核心元件包含其中: MergeKernel 將這兩條路徑合併為一個核心連結,處理程序將繼續在該連結上進行,並且 SplitKernel 在……之前再次將組件分開 CMP. 否 SYNC 且無需額外的同步緩衝區。
有關同步及同步錯誤的詳細資訊,請參閱「運算子類型與同步教學」一節。
有關運算子的詳細資訊,請參閱《運算子參考手冊》中的「MergeKernel」及「SplitKernel」。
CastKernel#
CastKernel 重新組織輸入資料的並行度與核心大小。您可以在輸出連結上變更核心大小。輸入與輸出端的核心行數、核心列數與並行度的乘積必須完全相同。
隨著 CastKernel 您可以轉換 將並行性整合至核心中. 例如,具有 1×1 核心的 48 級並行度,將轉變為擁有 48 個核心欄的 1 級並行度。相同的 48 個像素值仍會在一個時鐘週期內移動,但它們現在是核心的組成部分,而非並行像素。這在處理僅允許特定並行度的記憶體運算子之前特別有用。
將 `Parallelism ` 轉換為記憶體運算子前面的核心:

在螢幕截圖中, PARALLELup 將平行度提高至 48(核心 1×1)。 CastKernel 將其重新詮釋為具有 48 個核心欄位的平行處理 1,因此後續的記憶體運算子便能接收這些資料。
有關此運算子的詳細資訊,請參閱《運算子參考指南》中的「CastKernel」。
KernelRemap#
KernelRemap 在輸入與輸出之間重新映射核心元件。核心的尺寸保持不變。透過 SourceSelect 參數,您可以將輸入核心索引指派給每個輸出核心元件。
透過此運算子,您可以對核心內容進行鏡像或旋轉、將一個輸入元素映射至多個輸出,或捨棄未使用的輸入元素。
使用 KernelRemap 交換核心欄位:

螢幕截圖中的設計展示了如何 KernelRemap 交換核心欄位:第 0 欄與第 3 欄互換位置(其餘欄位依此類推)。此對應關係源自 SourceSelect 參數,此處 0, 1, 2, 3 → 3, 2, 1, 0. 這些模擬探針顯示了重新映射前後的內核組件。
有關此運算子的詳細資訊,請參閱《運算子參考指南》中的「KernelRemap」。
連線至 DMA#
一個原始核心連結必須 不是 直接進入 DmaToPC. DmaToPC 僅接受 Kernel Columns = 1 進行明確的生命週期管理即呼叫 Kernel Rows = 1.
因此,請務必在核心輸出與 DmaToPC. 這些運算子會將核轉換為單一像素,或是轉換為較小的核,供您進一步縮小:
FIRoperatorNxMSelectSubKernelSplitKernelMIN或MAXMedian
設計範例#
典型的過濾路徑如下所示:

- 這台相機輸出單一像素(1×1 核)。
- 例如,一個緩衝區
LineBuffer或ImageBuffer, 將攝影機與處理程序分離,並提供鄰域運算子所需的線性資料。 FIRkernelNxM在其輸出鏈路上,根據相鄰像素(例如 3×3 或 5×5)構建一個核。FIRoperatorNxM套用濾波係數,並針對每個位置輸出一個像素。DmaToPC將單像素資料流傳輸至主機。
詳細的濾波器範例(例如:平均濾波器、高斯濾波器、索貝爾濾波器、自適應閾值濾波器等)列於《運算子參考手冊》中「FIRkernelNxM」的「使用範例」章節,以及《運算子參考手冊》中「FIRoperatorNxM」的「使用範例」章節。
設計指引
請務必檢查 Supported Link Format 在連結上建立大於 1×1 的核心之前,請先使用以下運算子。特別是在 DmaToPC, 將核縮小至 1×1。
相關主題#
- 參數化 教學主題 —
KernelColumns進行明確的生命週期管理即呼叫KernelRows連結屬性 - Parallelism 教學主題 — 並行性與核心資料傳輸速率的權衡
- 延遲教學主題 — 緩衝區與濾波運算子的延遲
- 《運算子參考手冊》中的FIRkernelNxM
- 《運算子參考手冊》中的FIRoperatorNxM
- Operator 參考手冊
- 《使用者手冊》中的參數設定— 在圖形化使用者介面 (GUI) 中編輯連結與模組參數