ツイストマトリックスグラフィックフィルター

UPD:タイトルは記事のトピックに合わせて変更されました。



この記事では、 コンボリューションマトリックスコンボリューションマトリックスまたはコンボリューションマトリックス)の使用について説明します。これを使用して、ぼかし、シャープ、その他多くのフィルターを作成して画像に適用できます。



この記事は、Webプログラマーだけでなく、何らかの方法で画像処理に関与しているすべての人にも興味があります。これは、ツイストマトリックスを操作するための関数が多くの言語で利用できるためです(phpとflashについて知られています)。 また、この記事にはAdobe Photoshopを使用しているデザイナーが興味を持ちます。これは、対応するフィルター(Filter-Other-Custom)があるためです。



例は、GDライブラリを使用したPHPにあります。 理論、実践、例(慎重に、多くの写真!)





理論



数学言語ではなく、 畳み込みとは、 カーネル (「カーネル」)と呼ばれる別のマトリックスの助けを借りて1つのマトリックスを変換することです。 画像を処理するとき、直交座標のRGBピクセルチャネルの行列が最初の行列として機能します。



コアとして、通常3x3マトリックスが使用されますが、場合によってはより大きくなります(5x5、7x7など)。 コアには、要素自体に対する要素の周囲の値の影響度(「値」)が含まれます。



変換は次のとおりです。 元のマトリックスの各要素には、コアマトリックスの中心値が乗算されます。 さらに、周囲の要素に対応する値(3x3のカーネルサイズでは8)が乗算され、その後、結果が合計されて変換値として受け入れられます。



簡単なグラフィカルな例を次に示します。

画像



変換された値は赤で強調表示され、カーネルマトリックスのスコープは緑で強調表示されます。



変換の結果として起こったこと。 固有値を含む周囲のすべてのピクセルの値は、上部中央が1である場合を除き、ゼロです。 結果は次のとおりです。



(40 * 0)+(42 * 1)+(46 * 0)+(46 * 0)+(50 * 0)+(55 * 0)+(52 * 0)+(56 * 0)+(58 * 0)= 42



ご覧のとおり、この変換は画像を1ピクセル下にシフトします。



したがって、この場合の畳み込みは画像の変換であり、その結果、 周囲の領域が結果の各ピクセルに影響します。 この領域の影響度は、「コア」またはツイストマトリックスを使用して設定されます。



Divおよびオフセット値



1回のコンバージョンで画像を処理する場合、下がらず、正規化が必要です。 結果の値が255より大きいか0より小さい場合はどうなりますか? そのような花はありません。 さらに、色の境界を越えることはかなり頻繁に起こる現象です。



結果を正規化するために、追加の変数div(divider)とoffset(coefficient)が使用されます。 これらは非常に簡単に機能します。変換結果はdivに分割され、それにオフセットが追加されます。



デフォルトではdiv = 1、offset = 0(div = 0は設定できない!)であると推測することは難しくありません。



変換するとき、ツイストマトリックスのすべての要素の合計は通常divとして取得されます。 この条件により、色の歪みが不要な場合に防ぐことができます。



実際、変換される領域に同じ色が含まれる場合、結果はカーネル要素の合計にこの色を掛けたものになります。 したがって、色を変更しないままにするには、この結果で変換結果を除算する必要があります。



簡単な例:ネガティブフィルター。



ソースとして、次の画像を使用します。



画像



その例では、テキスト、画像、線の大小の変化を見ることができます。 ツイストマトリックスを作成して、マイナスの効果を得る:



画像



マトリックスによると、変換の結果として、すべての色が負の値を持つことになります。 色を負にするには、オフセット= 256に設定する必要があります。そのため、すべてのピクセルの色が256から差し引かれます。これは負の画像です。



画像



これはPHPでどのように行われますか:


PHPのGDライブラリには、4つのパラメーターを含むimageconvolution関数があります。 最初は画像識別子です。 2番目は、3つの変数を持つ3つの配列の配列の形式の行列です。 3番目と4番目はdivとoffsetです。



イメージをネガティブにするコードは次のとおりです。



<?php



$img = imagecreatefromjpeg( 'images/pattern.jpg' );



$matrix = array (

array( 0, 0, 0),

array( 0, -1, 0),

array( 0, 0, 0)

);



imageconvolution($img, $matrix, 1, 256);

imagejpeg($img, 'images/pattern_negative.jpg' , 100);



?>




* This source code was highlighted with Source Code Highlighter .








GDの非常に不快な機能の1つにすぐに言及する価値があります。イメージコンボリューションを使用して変換すると、アルファチャネルが「崩壊」します。 このバグは長い間説明されてきましたが 、私が知る限り、修正されていません。 これはフラッシュではありません。さらに、一部のピクセルが抜け落ちたときに画像のエッジを処理する追加のパラメーターがあります。 PHPでは、エッジは単に処理されません。



ぼかし、シャープ、エンボス



効果マトリックスの標準セットは次のとおりです。



画像



ぼかしの場合、係数はdiv = 9であることに注意してください。そのような行列の場合、そのような係数のみが色の歪みにつながりません。 また、ぼかしにはいくつかのオプションがあり、効果の強さがわずかに異なることを言わなければなりません。



結果の画像は次のとおりです。



ぼかし:



画像



シャープ:



画像



エンボス:



画像



「きちんとした」効果。



前のぼかしの例からわかるように、効果は画像にスーパーインポーズされますが、非常に強くなります。 画像への影響を減らすことは可能ですか? それはあなたができることが判明しました。 ただし、このためには、一見したように周囲のピクセルの影響度ではなく、影響するピクセルの数を変更する必要があります。



画像



次に、よりきれいに見えるエフェクトを取得します。



ぼかし:



画像



ライトシャープ:



画像



ライトエンボス:



画像



ここで質問する価値はありますが、効果の強さをどのように高めるのでしょうか? 残念ながら、何度も繰り返し適用するだけで、どのようにねじっても、3x3ピクセル領域は処理されます。 当然、これは非常にリソース集約型であり、ガウスぼかしを使用してスポットにぼかしを付けるためにフィルターを100〜200回かける必要がある場合があります。 非常に長い時間と多くのリソースが必要です。



結論として



...あなた自身が面白い効果を生み出すことができると言いたいです。 これを行うには、ツイストマトリックス実験するだけで十分です。



ツイストマトリックスは次の方法で正常に適用できます。

UPD:素敵なシャドウの作成(ボーナストラック、PHPプログラマのみ)



/**

*

* ! !

*

* @param res $image -

* @param int $shadow_width - (1..10, )

* @param int $shadow_deep - (1..20, , )

* @param string $bg_color - #7def34

*/

function imageaddshadow (&$image, $shadow_width = 4, $shadow_deep = 7, $bg_color = false )

{



$w = imagesx($image);

$h = imagesy($image);

$iw = $w + 4*$shadow_width;

$ih = $h + 4*$shadow_width;

$img = imagecreatetruecolor($iw, $ih);



$shadow_deep= 255-$shadow_deep*12;

$shadow = imagecolorallocate($img, $shadow_deep, $shadow_deep, $shadow_deep);





if (!$bg_color) {

//

$bg = imagecolorallocate($img, 255, 255, 255);

}

else {

list($r, $g, $b) = array_map( 'hexdec' , str_split(ltrim($bg_color, '#' ), 2));

$bg = imagecolorallocate($img, $r+1, $g+1, $b+1);

}



//

imagefilledrectangle($img,0,0,$iw,$ih,$bg);



//

imagefilledrectangle($img,

1+$shadow_width,

1+$shadow_width,

$iw-1-$shadow_width,

$ih-1-$shadow_width,

$shadow);



//

$matrix = array (

array( 1, 1, 1),

array( 1, 1, 1),

array( 1, 1, 1)

);



//

for ($i=0; $i < $shadow_width*2; $i++, imageconvolution($img, $matrix, 9, 0));



//

imagecopyresampled($img, $image, 2*$shadow_width,2*$shadow_width,0,0,$w,$h,$w,$h);



// !

$image = $img;

}




* This source code was highlighted with Source Code Highlighter .






結果:



画像



読んでくれてありがとう! 建設的な批判と個人的なメッセージの助けを借りた文法上の誤りの指摘は大歓迎です。




All Articles