簡體   English   中英

實際應用過濾器的是什么?

[英]What is actually applying a filter?

我正在嘗試用我不熟悉的概念解決 C++ 中的一個具有挑戰性的問題。

我正在嘗試將過濾器應用於矩陣。 但是就像我說的那樣,我對此很陌生,經過一些調查后,我發現此鏈接顯示應用過濾器基本上是乘法

但是讓我感到困惑的是,如果我的過濾器是 [0,1,0] 並且我必須將它應用於 5x5 矩陣怎么辦。 我怎么能那樣做?

使用 kernel 進行 GIMP 過濾

第一個鏈接的替代方法

編輯:第二個鏈接真的讓我很困惑。 我現在幾乎正在嘗試決定“申請”流程。 如果我遵循創建僅具有對角線 [0,1,0] 的 3x3 矩陣的想法,我將像在第二個鏈接中那樣應用它,還是必須將它應用於矩陣中的每個單元格。 或者如果它真的是一個一維過濾器,我應該再次將它應用於每個單元格還是忽略邊緣和角落?

那是一個卷積 kernel。

這個想法是你用它和它的鄰居的加權平均值替換每個像素,其中權重由你的卷積 kernel 給出。這個過程解釋得很好,例如這里

我發現奇怪的是你有一個一維卷積 kernel (即適合一維圖像),通常用於圖像處理的二維卷積核(也從上面/下面的行中獲取像素) ,但您的算法可能只需要處理當前行中的像素。

我認為被忽略的是使用輸入數據的子集對輸入數組的每個元素重復乘法。

GIMP 示例展示了如何使用 3x3 過濾器對單個像素過濾 5x5 圖像:

. . . . .                  . . . . .
. - - - .     . . .        . . . . .
. - @ - .  x  . . .   ->   . . @ . . 
. - - - .     . . .        . . . . .
. . . . .                  . . . . .

我用@標記了一個輸入像素,用-標記了它的鄰居。 您使用較小的矩陣:

- - -     . . .
- @ -  x  . . .  = 3x3 array
- - -     . . .

對生成的 3x3 數組中的數字求和,並將該值存儲到圖像中,代替@像素。

以您的示例為例,當使用 3x1 過濾器過濾 5x5 圖像時:

. . . . .                  . . . . .
. . . . .                  . . . . .
. - @ - .  x  . . .   ->   . . @ . . 
. . . . .                  . . . . .
. . . . .                  . . . . .

您將使用輸入數組的較小子集來匹配您的 kernel;

- @ -  x  . . .  = 1x3 array

然后,再次對結果數組中的數字求和,並將該值存儲到新圖像中以代替@像素。

它混淆了您在答案中尋找的內容。 如果我們假設您的過濾器存儲在名為filterstd::vector<double>中,並且您的圖像確實是 2D 並且類型為std::vector< std::vector<double> >稱為image ,那么我們可以執行以下操作以應用一維過濾器[-1,0,1]

 std::vector< std::vector<double> > new_image;
 std::vector<double> filter;
 filter.push_back(-1.0); filter.push_back(0.0); filter.push_back(1.0);

 for(int i = 0; i < image.size(); i++){
     for(int j = 0; j < image.at(i).size(); j++){

         new_image.at(i).push_back( filter.at(0)*image.at(i).at(j-1)
                                    + filter.at(1)*image.at(i).at(j)
                                    + filter.at(2)*image.at(i).at(j+1) );

     }
 }

例如,如果你想要一個像這樣的二維過濾器

 [0 1 0]
 [1 0 1]
 [0 1 0]

然后我們假設它也存儲為向量的向量,並且基本上做同樣的事情。

 std::vector< std::vector<double> > new_image;

 for(int i = 0; i < image.size(); i++){
     for(int j = 0; j < image.at(i).size(); j++){

         top_filter_term = filter.at(0).at(0)*image.at(i-1).at(j-1)
                          + filter.at(0).at(1)*image.at(i-1).at(j)
                          + filter.at(0).at(2)*image.at(i-1).at(j+1);

         mid_filter_term = filter.at(1).at(0)*image.at(i).at(j-1)
                          + filter.at(1).at(1)*image.at(i).at(j)
                          + filter.at(1).at(2)*image.at(i).at(j+1);

         bot_filter_term = filter.at(2).at(0)*image.at(i+1).at(j-1)
                          + filter.at(2).at(1)*image.at(i+1).at(j)
                          + filter.at(2).at(2)*image.at(i+1).at(j+1);

         new_image.at(i).push_back(top_filter_term + mid_filter_term + bot_filter_term);

     }
 }

請注意——我沒有為過濾器 arrays 做任何邊界檢查,你真的應該只在遠離圖像邊緣的地方應用它,或者添加代碼來應用你想要的任何類型的過濾器邊界條件. 我也沒有就此優化做出任何聲明。 對於大多數用途,使用矢量是 go 的好方法,因為它們可以動態調整大小並提供足夠的內置支持來執行許多有用的圖像操作。 但對於真正大規模的處理,您需要優化諸如過濾操作之類的事情。

至於你關於過濾 3D 數組的問題,有幾件事需要考慮。 第一,確保您確實想要過濾整個數組。 對於許多圖像處理任務,將所有顏色通道拆分為各自的 2D arrays 進行處理,然后將它們放回一起會更好、更高效。 如果您確實想要一個真正的 3D 過濾器,那么請確保您的過濾器實際上是 3D,也就是說,它將是一個向量的向量。 然后,您將使用與上述完全相同的邏輯,但對於應用於圖像的每個顏色通道或“切片”的濾鏡部分,您將有一個額外的術語層。

我想你是在談論濾色鏡。 從技術上講,5X5 圖像實際上是 5X5X3 (A),其中“3”對應於 3 個基本 colors (RGB)。 現在,創建一個 3X3 矩陣,對角線為 [0,1,0] (T)。

現在將兩個矩陣 (AXT) 相乘得到新的 5X5X3 圖像矩陣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM