上一個教程: 使用OpenCV掃描影像、查詢表和時間測量
下一個教程: 影像操作
| 原始作者 | Bernát Gábor |
| 相容性 | OpenCV >= 3.0 |
矩陣上的掩模操作非常簡單。其思想是根據掩模矩陣(也稱為核)重新計算影像中每個畫素的值。該掩模包含一些值,這些值將調整相鄰畫素(以及當前畫素)對新畫素值的影響程度。從數學角度來看,我們使用指定的值進行加權平均。
讓我們考慮一個影像對比度增強方法的問題。基本上,我們想對影像中的每個畫素應用以下公式:
\[I(i,j) = 5*I(i,j) - [ I(i-1,j) + I(i+1,j) + I(i,j-1) + I(i,j+1)]\]
\[\iff I(i,j)*M, \text{其中 } M = \bordermatrix{ _i\backslash ^j & -1 & 0 & +1 \cr -1 & 0 & -1 & 0 \cr 0 & -1 & 5 & -1 \cr +1 & 0 & -1 & 0 \cr }\]
第一種表示方法是使用公式,而第二種是透過使用掩模對第一種進行壓縮。使用掩模時,您將掩模矩陣的中心(在上述情況下由零零索引表示)放在您要計算的畫素上,並將畫素值與重疊的矩陣值相乘後求和。它們是相同的,但在大型矩陣的情況下,後一種表示方法更容易檢視。
您可以從此處下載此原始碼,或者在OpenCV原始碼庫的示例目錄中檢視samples/cpp/tutorial_code/core/mat_mask_operations/mat_mask_operations.cpp。
您可以從此處下載此原始碼,或者在OpenCV原始碼庫的示例目錄中檢視samples/java/tutorial_code/core/mat_mask_operations/MatMaskOperations.java。
您可以從此處下載此原始碼,或者在OpenCV原始碼庫的示例目錄中檢視samples/python/tutorial_code/core/mat_mask_operations/mat_mask_operations.py。
現在讓我們看看如何透過使用基本的畫素訪問方法或使用filter2D()函式來實現這一點。
這是一個可以實現此功能的函式
首先,我們確保輸入影像資料是無符號字元(unsigned char)格式。為此,我們使用CV_Assert函式(宏),當其中的表示式為假時,它會丟擲錯誤。
首先,我們確保輸入影像資料是無符號8位格式。
首先,我們確保輸入影像資料是無符號8位格式。
我們建立一個與輸入影像大小和型別相同的輸出影像。如您在儲存一節中所見,根據通道數,我們可能有一個或多個子列。
我們將透過指標遍歷它們,因此元素的總數取決於此(通道)數量。
我們將使用普通的C語言 `[]` 運算子來訪問畫素。由於我們需要同時訪問多行,因此我們將獲取每行的指標(前一行、當前行和下一行)。我們還需要另一個指標來儲存計算結果。然後,只需使用 `[]` 運算子訪問正確的項。為了將輸出指標向前移動,我們只需在每次操作後將其增加(一個位元組)。
在影像的邊界處,上述表示法會導致不存在的畫素位置(例如負一 - 負一)。在這些點,我們的公式是未定義的。一個簡單的解決方案是,在這些點不應用核,例如,將邊界上的畫素設定為零。
我們需要訪問多行和多列,這可以透過向當前中心(i,j)新增或減去1來實現。然後我們應用求和並將新值放入Result矩陣中。
在影像的邊界處,上述表示法會導致不存在的畫素位置(例如(-1,-1))。在這些點,我們的公式是未定義的。一個簡單的解決方案是,在這些點不應用核,例如,將邊界上的畫素設定為零。
我們需要訪問多行和多列,這可以透過向當前中心(i,j)新增或減去1來實現。然後我們應用求和並將新值放入Result矩陣中。
這類濾波器在影像處理中非常常見,以至於OpenCV中有一個函式可以處理掩模(在某些地方也稱為核)的應用。為此,您首先需要定義一個持有掩模的物件。
然後呼叫filter2D()函式,指定輸入影像、輸出影像和要使用的核。
該函式甚至還有一個可選的第五個引數用於指定核的中心,第六個引數用於在將過濾後的畫素儲存到K中之前向其新增一個可選值,以及第七個引數用於確定在操作未定義的區域(邊界)中如何處理。
這個函式更短,更簡潔,而且由於存在一些最佳化,它通常比手動編寫的方法更快。例如,在我的測試中,第二個方法只用了13毫秒,而第一個方法用了大約31毫秒。差異相當大。
例如
在我們的YouTube頻道上檢視執行該程式的一個例項。
