forked from: Thresholdと二値化について
今更、二値化のコードもないと思いますが、私もASを最近始めたばかり ですので、わからない事をネットであちこち調べてます。 しかし thresholdを使うのは良いのですがどうも明暗のおかしい妙な 二値化画像ばかりみかけます。 まず、Actionscript 二値化といったキーワードでグーグル検索すると トップにrsakaneさんのサイトが出てきます。 申し訳ないですが、こちらのページは間違ってます。 http://www40.atwiki.jp/spellbound/pages/168.html thresholdのパラメータ "<=", 0x7FFFFF, 0xFF000000, 0xFFFFFF これ、実際に塗りつぶして試されるとわかりますが、 0x00FFFF(シアン)は輝度に関係なく通って黒になります。同様に 0x00FF00 、 0x0000FF といった数値も赤輝度が0x80以上でない限り黒くなります。 この方法で二値化するのであれば閾値を0x7F7F7Fに設定する必要があります。 http://aquioux.blog48.fc2.com/blog-entry-694.html 少し前にAquiouxさんがこちらのページで疑問を書かれていますが、 thresholdは大小を32ビットの数値で比較しているだけで、 バイト単位で比較している訳じゃないという事だと思います。 多分、閾値を変えて二値化するのであればRGBの要素それぞれに threshold使わないといけないのではないでしょうか。 上の例で0x7F7F7Fを閾値にする場合は32ビットの中央値になるので良いのですが、 0x404040といった閾値だと不等号では評価できなくなります。 (※追記 すみません。読み直すと上2行は紛らわしかったです。) 普通は、グレースケールに変換する事が多いと思いますが。 単純に二値化=threshold と考えるのは問題かもしれませんね。 10/03/17 SharaQ
♥0 |
Line 153 |
Modified 2010-03-18 10:19:47 |
MIT License
archived:2017-03-10 19:45:18
| (replaced)
ActionScript3 source code
/**
* Copyright cyanpon ( http://wonderfl.net/user/cyanpon )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/u2P3
*/
// forked from Sharakusai's Thresholdと二値化について
package {
/*
今更、二値化のコードもないと思いますが、私もASを最近始めたばかり
ですので、わからない事をネットであちこち調べてます。
しかし thresholdを使うのは良いのですがどうも明暗のおかしい妙な
二値化画像ばかりみかけます。
まず、Actionscript 二値化といったキーワードでグーグル検索すると
トップにrsakaneさんのサイトが出てきます。
申し訳ないですが、こちらのページは間違ってます。
http://www40.atwiki.jp/spellbound/pages/168.html
thresholdのパラメータ
"<=", 0x7FFFFF, 0xFF000000, 0xFFFFFF
これ、実際に塗りつぶして試されるとわかりますが、
0x00FFFF(シアン)は輝度に関係なく通って黒になります。同様に 0x00FF00 、
0x0000FF といった数値も赤輝度が0x80以上でない限り黒くなります。
この方法で二値化するのであれば閾値を0x7F7F7Fに設定する必要があります。
http://aquioux.blog48.fc2.com/blog-entry-694.html
少し前にAquiouxさんがこちらのページで疑問を書かれていますが、
thresholdは大小を32ビットの数値で比較しているだけで、
バイト単位で比較している訳じゃないという事だと思います。
多分、閾値を変えて二値化するのであればRGBの要素それぞれに
threshold使わないといけないのではないでしょうか。
//上の例で0x7F7F7Fを閾値にする場合は32ビットの中央値になるので良いのですが、
//0x404040といった閾値だと不等号では評価できなくなります。
(※追記 すみません。読み直すと上2行は紛らわしかったです。)
普通は、グレースケールに変換する事が多いと思いますが。
単純に二値化=threshold と考えるのは問題かもしれませんね。
10/03/17 SharaQ
*/
import flash.display.Sprite;
import flash.events.*;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.StageScaleMode;
import flash.geom.Point;
import flash.filters.ColorMatrixFilter;
[SWF(width = 465, height = 465,
frameRate = "16", backgroundColor = 0x000000)]
public class BinarizationExample extends Sprite {
// private var myFilter:ImageFilter;
private var myImage:BitmapEX; //読み込み用
private var saveImage:BitmapEX; //書き込み用
private var bmd:BitmapData;
private var bmp:Bitmap;
private const url:String //Lena 画像
= "http://assets.wonderfl.net/images/related_images/"
+ "e/e0/e085/e0856a21af5022be157e95e36bce38bbc50c1500";
// initiarize
public function BinarizationExample() {
stage.scaleMode = StageScaleMode.NO_SCALE;
myImage = new BitmapEX();
myImage.addEventListener(Event.COMPLETE, DrawImage);
myImage.loadURL(url);
}
// main
private function DrawImage(e:Event):void {
myImage.removeEventListener(Event.COMPLETE, DrawImage);
bmd = new BitmapData(myImage.bitmapData.width,
myImage.bitmapData.height);
bmd.draw(myImage);
Binarization(bmd,64);
bmp = new Bitmap(bmd);
addChild(bmp);
} //end of function
//
public function Binarization(src:BitmapData , value:int = 0x7F ):void {
GrayScaleNTSC(src);
var valueR:int = value << 16;
var valueG:int = value << 8;
var valueB:int = value;
//threshold, color, mask
src.threshold(src, src.rect, new Point(), "<=",
valueR, 0xFF000000, 0xFF0000, false);
src.threshold(src, src.rect, new Point(), "<=",
valueG, 0xFF000000, 0x00FF00, false);
src.threshold(src, src.rect, new Point(), "<=",
valueB, 0xFF000000, 0x0000FF, false);
src.threshold(src, src.rect, new Point(), "!=",
0x0, 0xFFFFFFFF, 0xFFFFFF, false);
}
public function GrayScaleNTSC(src:BitmapData):void {
var matrix:Array = [
0.2989, 0.5866, 0.1144, 0, 0,
0.2989, 0.5866, 0.1144, 0, 0,
0.2989, 0.5866, 0.1144, 0, 0,
0, 0, 0, 1, 0
];
src.applyFilter(src, src.rect, new Point(),
new ColorMatrixFilter(matrix));
}
} // end of class
} // end of Package
////////////////////////////////////////////////////////////////
//
// 画像 I/Oユーティリティ (シングルイメージ) Bitmapサブクラス
//
//
// loadURL ドメイン上の画像をロード
// loadLocal ローカル画像をロード
// savePNG PNG形式で保存
// saveJPG JPG形式で保存
// by-SharaQ
////////////////////////////////////////////////////////////////
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.FileReference;
import flash.net.FileFilter;
import flash.utils.ByteArray;
import flash.display.LoaderInfo;
import com.adobe.images.JPGEncoder; // as3Corelib
import com.adobe.images.PNGEncoder;
class BitmapEX extends Bitmap {
private var loadReference:FileReference;
private var loader:Loader;
//コンストラクタ
public function BitmapEX():void {
loadReference = new FileReference();
}
//URL上の画像を取得
public function loadURL(url:String):void {
var urlloader:Loader = new Loader();
var urlrequest:URLRequest = new URLRequest(url);
var loaderContext:LoaderContext = new LoaderContext(true);
urlloader.load(urlrequest , loaderContext);
urlloader.contentLoaderInfo.addEventListener(
Event.COMPLETE, onLoadComplete);
}
private function onLoadComplete(e:Event):void {
var urlloader:Loader = Loader(e.target.loader);
var tmp:Bitmap = Bitmap(urlloader.content);
this.bitmapData = tmp.bitmapData.clone();
tmp.bitmapData.dispose();
var e:Event = new Event(Event.COMPLETE);
dispatchEvent(e);
}
//ローカル画像
public function LoadLocal():void{
var fmt:String = "画像ファイル(*.JPG;*.GIF;*.PNG)";
var ext:String = "*.jpg;*.gif;*.png";
var filefilter:FileFilter = new FileFilter(fmt, ext);
loadReference.addEventListener(Event.SELECT, onLoadFileSelect);
loadReference.browse([filefilter]);
}
private function onLoadFileSelect(e:Event):void{
loadReference.removeEventListener(Event.SELECT, onLoadFileSelect);
loadReference.addEventListener(Event.COMPLETE, onLocalComplete);
loadReference.load();
}
private function onLocalComplete(e:Event):void {
loadReference.removeEventListener(Event.COMPLETE, onLocalComplete);
loader = new Loader();
loader.contentLoaderInfo.addEventListener(
Event.COMPLETE,onLocalLoaded);
loader.loadBytes(loadReference.data);
}
private function onLocalLoaded(e:Event):void {
var loaderInfo:LoaderInfo = (e.target as LoaderInfo);
loader.contentLoaderInfo.removeEventListener(
Event.COMPLETE,onLocalLoaded);
var tmp:BitmapData = new BitmapData(loader.width, loader.height);
tmp.draw(loader.content);
this.bitmapData = tmp.clone();
tmp.dispose();
//addEventListerner の指定先に返す。引数を忘れないように(エラーにならない)
var e:Event = new Event(Event.COMPLETE);
dispatchEvent(e);
}
//PNG イメージで保存
public function SavePNG():void{
if (!this.bitmapData) return;
var encoder:Object = new Object();
var defaultName:String;
encoder.encode = PNGEncoder.encode;
defaultName = "Sample.png";
var imageBytes:ByteArray = encoder.encode(this.bitmapData);
var fileRef:FileReference = new FileReference();
fileRef.save(imageBytes, defaultName);
var e:Event = new Event(Event.COMPLETE);
dispatchEvent(e);
}
//JPG イメージで保存
private function SaveJPG():void{
if (! this.bitmapData) return;
var encoder:Object = new Object();
var defaultName:String;
var je:*;
je = new JPGEncoder(100);
encoder.encode = je.encode;
defaultName = "Sample.jpg";
var imageBytes:ByteArray = encoder.encode(this.bitmapData);
var fileRef:FileReference = new FileReference();
fileRef.save(imageBytes, defaultName);
var e:Event = new Event(Event.COMPLETE);
dispatchEvent(e);
}
}
