2012-04-04 14 views
2

私は慣れていない概念でC++の難しい問題を解決しようとしています。実際にフィルタを適用するのは何ですか?

私はマトリックスにフィルターを適用しようとしています。しかし、私が言ったように私はこれでかなり新しく、いくつかの調査の後、私はフィルタを適用することが基本的には乗算であることを示すこのリンクを見つけました。

しかし、私のフィルタが[0,1 、0]と私はそれを5x5行列に適用する必要があります。どのように私はそれを行うことができるでしょうか?

GIMP Filtering with kernel

An alternative to first link

EDIT: 2番目のリンクは本当に私を混乱。私は今かなり "アプリケーション"プロセスを決定しようとしています。対角線[0,1,0]だけの3x3行列を作成するという考え方に従えば、2番目のリンクのようにそれを適用するか、それを行列のすべての単一セルに適用する必要があります。または、実際に1次元フィルタにする場合は、再びすべての単一セルに適用するか、エッジとコーナーを外す必要がありますか?

+0

[[0、1、0] 'フィルタは、異なる値が_colors_を表す場合を除いて、識別変換になります[ElKamina suggests](http://stackoverflow.com/a/10003402/377270)、またはその他の情報が欠落しています。 – sarnold

+0

私は例としてその1つを与えました、私が使用したいと思う主なフィルターは[-1,0,1] – Ali

答えて

3

私が見逃していることは、入力データのサブセットを使用して入力配列のすべての要素に対して乗算が繰り返されることです。

GIMPの例では、単一の画素に対して3x3のフィルタを使用して、5×5イメージをフィルタリングする方法を示した:

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

Iは-@、その隣人と一方の入力ピクセルをラベル付けしました。 @ピクセルの代わりに、新しいイメージに値

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

サムアップ結果の3×3アレイ内の数値、および店舗:あなたは、小さな行列を使用しています。 3×1フィルタ使用した5×5の画像をフィルタリングするとき、あなたの例にこれを取るために

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

をあなたのカーネルに一致するように、入力配列のより小さなサブセットを使用します。

- @ - x . . . = 1x3 array 

そして、再度、得られた配列に数値を合計し、@ピクセルの代わりに、新たな画像にその値を格納します。

+0

これは理にかなっています。私はそれをチェックし、より多くの質問で戻ってくる可能性がありますが、あなたの投稿は私が思考を開始するための本当に良い基盤を設定しました。ありがとう! :) – Ali

+0

私はもう一度それをチェックしており、フィルタはx軸とy軸にそれぞれ適用する必要があります。最初の行の最初の3つの数字に2〜4(3を含む)、3〜5などを掛ける必要がありますか? – Ali

0

私はあなたがカラーフィルターについて話していると思います。技術的には、5X5画像は実際には5X5X3(A)で、3は3つの基本色(RGB)に対応しています。今、対角[0,1,0](T)で3X3の行列を作成します。

ここで、新しい5X5X3画像マトリックスを得るために2つのマトリックス(AXT)を掛けます。

+0

です。これで「あまりにも新しい」のために申し訳ありませんが、私はいくつかの質問があります。 1)対角線[0,1,0]を持つ行列を作成すると、残りの数値に大きな影響はありませんか? – Ali

+0

2)私は本当に5x5x3と3x3を乗算する方法を知らない。三次元と二次元は私を混乱させる。 – Ali

+0

1.はい。基本的に、画像には緑色の色合いしかありません。 2. 5倍の5X3および3X3マト​​リクスを掛け合わせます。 – ElKamina

4

これはコンボリューションカーネルです。

考えてみましょう。各ピクセルを、そのピクセルとその近隣ピクセルの加重平均で置き換えます。ここでは、コンボリューションカーネルによって重みが与えられます。このプロセスは、例えば、 here

あなたは1次元畳み込みカーネル(すなわち、これは1次元画像に適しています)、画像処理のために2次元畳み込みカーネル(これは上/下の行からもピクセルを取る)が使用されているときに使用されますが、アルゴリズムはピクセルだけで動作する必要があります現在の行から

+0

私は1次元カーネルの2つの可能な用途を考えることができます。デインタレースは3x1ベクトル(垂直)で十分に機能し、_simple_モーションブラーはおそらく1x3ベクトル(水平)で実行できます。 – sarnold

+0

本当に畳み込みカーネルであることは間違いありません。フィルタ処理を適用すると行列の数値がフィルタに乗算されるかどうかを調べるだけです。私はちょうど "適用"の部分を知らない。適用手段のように、行ごとに列を、次に列ごとに何かを掛けるか? – Ali

+0

私はその記事を読んだことがあります。私はちょうど2つの質問を持っています:1)行列のすべての単一の番号に対してこのプロセスを適用しますか?(エッジとコーナーを含む)2)あなたの意見では、エッジやコーナーに関してはどうすればよいですか?カーネルが多くの問題を引き起こしますか?) – Ali

2

答えで探しているものが混乱しています。

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)); 

    } 
} 
:私たちはあなたのフィルタが filterと呼ばれる std::vector<double>に格納されており、あなたのイメージが本当に2Dであると imageと呼ばれる std::vector< std::vector<double> >型を持つこと、そして私たちは、次は、1-Dフィルタ [-1,0,1]を適用するために行うことができますという仮定をした場合あなたが例えば

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

をこのような2次元フィルタを持つようにしたい場合は

は、我々はそれが同様にベクトルのベクトルとして保存されていると仮定して、基本的には同じことを行います。

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); 

    } 
} 

注意してください - 私は、フィルタアレイの境界チェックを行うためのあらゆる努力をしていないよ、あなたは本当にあなただけの画像のエッジから離れてこれを適用する、または適用するためにコードを追加する必要がありますどのようなフィルタに必要な境界条件の種類。私はまた、これが最適化されているという主張はしていません。ほとんどの場合、ベクトルの使用は、動的にサイズ変更が可能で、多くの便利な画像操作を行うのに十分なビルトインサポートを提供するため、良い方法です。しかし、実際に大規模な処理を行うには、フィルター操作のようなものを最適化する必要があります。

3Dアレイをフィルタリングする方法については、考慮すべき点が2つあります。 1つは、実際に配列全体をフィルタリングする必要があることを確認してください。多くの画像処理タスクでは、すべてのカラーチャンネルをそれぞれの2D配列に分割し、処理してから戻す方が効率的です。真の3Dフィルタが必要な場合は、フィルタが実際に3Dであることを確認します。つまり、ベクトルのベクトルのベクトルになります。次に、上記とまったく同じロジックを使用しますが、画像の各カラーチャンネル、つまり「スライス」に適用されるフィルタの部分の用語を追加します。