2

よく知らない概念を使用して、C++ で困難な問題を解決しようとしています。

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

しかし、私のフィルターが [0,1,0] で、それを 5x5 マトリックスに適用しなければならない場合、何が混乱するのでしょうか。どうすればそれができるでしょうか?

カーネルによる GIMP フィルタリング

最初のリンクの代替

編集: 2番目のリンクは本当に混乱しました。私は今、「申請」プロセスを決定しようとしています。対角線 [0,1,0] のみで 3x3 マトリックスを作成するという考えに従う場合、2 番目のリンクのように適用するか、マトリックス内のすべてのセルに適用する必要がありますか。それとも、本当に 1-D フィルターにする場合は、もう一度、すべてのセルに適用するか、エッジとコーナーを除外する必要がありますか?

4

4 に答える 4

4

それが畳み込みカーネルです。

アイデアは、各ピクセルをそのピクセルとその隣接ピクセルの加重平均で置き換えることです。重みは畳み込みカーネルによって与えられます。プロセスは、たとえばここでうまく説明されています。

通常、画像処理に2-D畳み込みカーネル(上下の行からもピクセルを取得する)が使用される場合、1-D畳み込みカーネル(つまり、1次元画像に適している)があるのは奇妙だと思います、しかし、アルゴリズムが現在の行のピクセルでのみ機能する必要がある可能性があります。

于 2012-04-04T00:55:27.317 に答える
3

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

GIMP の例では、1 つのピクセルに対して 3x3 フィルターを使用して 5x5 の画像をフィルター処理する方法を示しました。

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

1 つの入力ピクセルを でラベル付けし@、その隣接ピクセルを でラベル付けしました-。より小さい行列を使用します。

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

結果の 3x3 配列の数値を合計し、その値をピクセルの代わりに新しい画像に格納します@

これを例に取ると、3x1 フィルターを使用して 5x5 画像をフィルター処理する場合:

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

カーネルに合わせて、入力配列の小さなサブセットを使用します。

- @ -  x  . . .  = 1x3 array

次に、結果の配列の数値を合計し、その値を@ピクセルの代わりに新しいイメージに格納します。

于 2012-04-04T00:55:10.780 に答える
2

答えで何を探しているのか混乱しています。std::vector<double>フィルターが呼び出された に格納され、filter画像が実際には 2D であり、型がstd::vector< std::vector<double> >呼び出されていると仮定するとimage、次のようにして 1-D フィルターを適用できます[-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) );

     }
 }

たとえば、このような2次元フィルターが必要な場合

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

     }
 }

注意してください-私はフィルター配列の境界チェックを行う努力をしていません。実際には、これを画像の端から離れた場所にのみ適用するか、フィルターに必要な境界条件を適用するコードを追加する必要があります. また、これが最適化されていることについても主張していません。ベクトルは動的にサイズ変更可能であり、多くの有用な画像操作を実行するための十分な組み込みサポートを提供するため、ほとんどの場合、ベクトルを使用することをお勧めします。しかし、非常に大規模な処理では、フィルター操作などを最適化する必要があります。

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

于 2012-04-04T01:11:19.383 に答える
0

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

次に、2 つの行列 (AXT) を乗算して、新しい 5X5X3 画像行列を取得します。

于 2012-04-04T00:34:18.947 に答える