スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

--.--.-- | | スポンサー広告

Pixel Benderでエッジ抽出

前回のエントリにひきつづき、Pixel Benderをflashでフィルタとして使用してみました。なので、実行するにはFlash Player 10が必要デス。
今回は、エッジ抽出です。






左上の読込ボタンをクリックしてフィルタをかけたい画像ファイルを選択すると、エッジ抽出後の画像が表示されます。
反転ボタンで、明暗が反転します。テキストボックスに0.0~1.0までの値を入力して二値ボタンで、二値化します。
反転ボタンと二値ボタンはもう一度押すとキャンセルされます。

今回も、メインの処理はPixel Bender Toolkitを使って作って、ソレをflashでフィルタとして使用しています。
Pixel Bender側のソースはこんなカンジです。

<languageVersion : 1.0;>

kernel edge5
< namespace : "Your Namespace";
vendor : "Your Vendor";
version : 1;
description : "your description";
>
{
input image4 src;
output pixel4 dst;

// 反転するかどうか
parameter int reverse
<
minValue:0;
maxValue:1;
defaultValue:0;
>;
// 二値化するかどうか
parameter int binalize<
minValue:0;
maxValue:1;
defaultValue:0;
>;
// 二値化する場合の閾値
parameter float threshold;

void
evaluatePixel()
{
// 対象となる座標のピクセルを取得する
float2 pos = outCoord();
pixel4 p0 = sampleNearest(src, float2(pos.x - 1.0, pos.y - 1.0));
float b0 = 0.2125 * p0.r + 0.7154 * p0.g + 0.0721 * p0.b;
pixel4 p1 = sampleNearest(src, float2(pos.x, pos.y - 1.0));
float b1 = 0.2125 * p1.r + 0.7154 * p1.g + 0.0721 * p1.b;
pixel4 p2 = sampleNearest(src, float2(pos.x + 1.0, pos.y - 1.0));
float b2 = 0.2125 * p2.r + 0.7154 * p2.g + 0.0721 * p2.b;
pixel4 p3 = sampleNearest(src, float2(pos.x - 1.0, pos.y));
float b3 = 0.2125 * p3.r + 0.7154 * p3.g + 0.0721 * p3.b;
pixel4 p4 = sampleNearest(src, float2(pos.x, pos.y));
float b4 = 0.2125 * p4.r + 0.7154 * p4.g + 0.0721 * p4.b;
pixel4 p5 = sampleNearest(src, float2(pos.x + 1.0, pos.y));
float b5 = 0.2125 * p5.r + 0.7154 * p5.g + 0.0721 * p5.b;
pixel4 p6 = sampleNearest(src, float2(pos.x - 1.0, pos.y + 1.0));
float b6 = 0.2125 * p6.r + 0.7154 * p6.g + 0.0721 * p6.b;
pixel4 p7 = sampleNearest(src, float2(pos.x, pos.y + 1.0));
float b7 = 0.2125 * p7.r + 0.7154 * p7.g + 0.0721 * p7.b;
pixel4 p8 = sampleNearest(src, float2(pos.x + 1.0, pos.y + 1.0));
float b8 = 0.2125 * p8.r + 0.7154 * p8.g + 0.0721 * p8.b;
// 変化量を算出する
float dx = (b2 + 2.0 * b5 + b8) - (b0 + 2.0 * b3 + b6);
float dy = (b0 + 2.0 * b1 + b2) - (b6 + 2.0 * b7 + b8);
// 明度を算出する
float v = sqrt(dx * dx + dy * dy);
// 反転
if (reverse > 0) {
v = 1.0 - v;
}
// 閾値で二値化
if (binalize > 0) {
if (v > threshold) {
v = 1.0;
} else {
v = 0.0;
}
}
// 結果を設定する
dst = pixel4(v, v, v, 1);
}
}

エッジ抽出には、Sobel オペレータというやり方を使っています。対象の近傍の座標のピクセルの明度の変化量から出力対象となるピクセルの明度を決定しています。

パラメータは、reverse=反転するかどうか/binalize=二値化するかどうか/threshold=二値化する場合の閾値です。
reverseとbinalizeはbool型でよいはずなのですが、bool型のパラメータを使うとflash用にexportできなかったので代わりに0か1を設定するようにしています。
0=false、1=trueです。

これをPixel Bender Toolkitで、flash用にexportしてpbjファイルを作っています。

フラッシュ側は、フレームアクションとして以下のようなコードを記述しています。
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

// シェーダを読み込む
[Embed (source="edge.pbj", mimeType="application/octet-stream")]
var ShaderClass:Class;
var shader:Shader = new Shader(new ShaderClass());

// シェーダフィルタ
var shaderFilter:ShaderFilter = new ShaderFilter(shader);

// 表示領域
var screen:Sprite = new Sprite();
screen.y = 40;
screen.filters = [shaderFilter];
addChild(screen);

// 読み込んだ画像
var image:Bitmap;

// 反転するか?
var isReverse:Boolean = false;
// 二値化するか?
var isBinalize:Boolean = false;

// 画像読み込みダイアログ
var fr:FileReference = new FileReference();
fr.addEventListener(Event.SELECT,
function (e:Event):void {
// ファイルが選択されたら読み込む
fr.load();
});
fr.addEventListener(Event.COMPLETE,
function (e:Event):void {
// 画像データを取得する
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT,
function (e:Event): void {
// 表示中の画像があったら削除する
if (image) {
screen.removeChild(image);
}
// スクリーンに画像を追加する
image = Bitmap(e.target.content);
screen.addChild(image);
});
loader.loadBytes(fr.data);
});

// 読込ボタン
loadBtn.addEventListener(MouseEvent.CLICK,
function (e:MouseEvent):void {
fr.browse();
});

// 反転ボタン
reverseBtn.addEventListener(MouseEvent.CLICK,
function (e:MouseEvent):void {
isReverse = !isReverse;
setupFilter();
});

// 二値ボタン
binalizeBtn.addEventListener(MouseEvent.CLICK,
function (e:MouseEvent):void {
isBinalize = !isBinalize;
setupFilter();
});

// フィルタを設定します
function setupFilter():void {
shader.data.reverse.value = [isReverse ? 1 : 0];
shader.data.threshold.value = [Number(binalizeTxt.text)];
shader.data.binalize.value = [isBinalize ? 1 : 0];
screen.filters = [shaderFilter];
}


Embedメタタグを使ってpbjファイルを組み込んでいます。そのためライブラリパスにFlexSDKが必要です。

ステージには、読込/反転/二値の3つのボタンと、二値化したときの閾値を入力するためのテキストフィールドが配置してあります。

読込ボタンをクリックしたときは、FileReferenceを使ってファイルを開くダイアログを表示して、選ばれたファイルを表示用のスプライト(screen)にaddChildしています。screenのfiltersプロパティにShaderFilterを設定することで、フィルタをかけた画像が表示される仕組みデス。

反転ボタン/二値ボタンをクリックしたときに実行しているsetupFilterメソッドで、Pixel Benderのパラメータを設定してフィルタを更新しています。

スポンサーサイト

テーマ:Flash - ジャンル:コンピュータ

2009.02.04 | | Comments(0) | Trackback(0) | Flash CS4

«  | HOME |  »

プロフィール

HundredthMonkey

Author:HundredthMonkey
プログラマ。

ブロとも申請フォーム

この人とブロともになる

メールフォーム

名前:
メール:
件名:
本文:

ブログ内検索


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。