細線化
/**
* Copyright mchang ( http://wonderfl.net/user/mchang )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/xzNN
*/
/**
* このサイトのを AS でやってみました
* そのまま AS で書いただけ。
* 「パターン認識の前処理に必要な二値画像の細線化」
* http://codezine.jp/article/detail/98
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFormat;
[SWF(width="465", height="465", backgroundColor="#ffffff", frameRate="60")]
public class ThinningSample extends Sprite
{
private static const UPPER_LEFT:int = 2;
private static const LOWER_RIGHT:int = 6;
private static const UPPER_RIGHT:int = 0;
private static const LOWER_LEFT:int = 4;
private var _bd:BitmapData;
private var _width:int;
private var _height:int;
private var _newPixels:Array;
private var _oldPixels:Array;
private var _change:Boolean;
public function ThinningSample()
{
addEventListener(Event.ADDED_TO_STAGE, initialize);
}
private function initialize(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, initialize);
// テキストフィールドを作成します
var field:TextField = new TextField();
field.defaultTextFormat = new TextFormat("_ゴシック", 18);
field.text = "て";
// テキストを BitmapData にします
var textBitmapData:BitmapData = new BitmapData(465, 465, true, 0x000000);
var matrix:Matrix = new Matrix();
matrix.scale(10, 10);
textBitmapData.draw(field, matrix);
addChild(new Bitmap(textBitmapData));
// 不透明の黒(0xff000000) ではない領域を、透明(0x00000000)にします
textBitmapData.threshold(textBitmapData, textBitmapData.rect, new Point(0, 0), '!=', 0xff000000, 0x00000000, 0xffffffff, true);
// BitmapData をコピーします
_bd = new BitmapData(textBitmapData.width, textBitmapData.height, true, 0x000000);
_bd.copyPixels(textBitmapData, textBitmapData.rect, new Point(0,0));
var bitmap:Bitmap = new Bitmap(_bd);
addChild(bitmap);
_width = _bd.width;
_height = _bd.height;
paint();
}
private function paint():void
{
_bd.lock();
_newPixels = [];
_oldPixels = [];
// 1 が黒で、 0 が白
var y:int, x:int;
for (x = 0; x < _width + 2; x++) {
_newPixels[x] = [];
_oldPixels[x] = [];
for (y = 0; y < _height + 2; y++) {
_newPixels[x][y] = 0;
_oldPixels[x][y] = 0;
}
}
for (x = 1; x < _width + 1; x++) {
for (y = 1; y < _height + 1; y++) {
if (_bd.getPixel32(x - 1, y - 1) == 0xff000000) {
_newPixels[x][y] = 1;
_oldPixels[x][y] = 1;
}
}
}
var width:int = _width + 2;
var height:int = _height + 2;
for (;;) {
_change = false;
// 左上から細線化
drawAndCopy();
for (y = 1; y < height - 1; y++) {
for (x = 1; x < width - 1; x++) {
if (_oldPixels[x][y] == 1) {
thinImage(x, y, UPPER_LEFT);
}
}
}
// 右下から細線化
drawAndCopy();
for (y = height - 2; 1 <= y; y--) {
for (x = width - 2; 1 <= x; x--) {
if (_oldPixels[x][y] == 1) {
thinImage(x, y, LOWER_RIGHT);
}
}
}
// 右上から細線化
drawAndCopy();
for (y = 1; y < height - 1; y++) {
for (x = width - 2; 1 <= x; x--) {
if (_oldPixels[x][y] == 1) {
thinImage(x, y, UPPER_RIGHT);
}
}
}
// 左上から細線化
drawAndCopy();
for (y = height - 2; 1 <= y; y--) {
for (x = 1; x < width - 1; x++) {
if (_oldPixels[x][y] == 1) {
thinImage(x, y, LOWER_LEFT);
}
}
}
if (!_change) {
break;
}
}
_bd.unlock();
}
/**
* 描画とコピーします
*/
private function drawAndCopy():void
{
var x:int, y:int;
for(y = 0; y < _height + 2; y++) {
for(x = 0; x < _width + 2; x++){
if (_newPixels[x][y] == 1) {
_bd.setPixel32(x, y, 0xffff0000);
} else {
// 透明
_bd.setPixel32(x, y, 0x00000000);
// 次の細線化のためのコピー
_oldPixels[x][y] = _newPixels[x][y];
}
}
}
}
/**
* 細線化を実行します
*/
private function thinImage(x:int, y:int, start:int):void
{
var p:Array = [];
var product:int, sum:int;
p[0] = _oldPixels[x - 1][y - 1];
p[1] = _oldPixels[x - 1][y];
p[2] = _oldPixels[x - 1][y + 1];
p[3] = _oldPixels[x][y + 1];
p[4] = _oldPixels[x + 1][y + 1];
p[5] = _oldPixels[x + 1][y];
p[6] = _oldPixels[x + 1][y - 1];
p[7] = _oldPixels[x][y - 1];
for (var i:int = start; i < start + 3; i++) {
product = p[i % 8] * p[(i + 1) % 8] * p[(i + 2) % 8];
sum = p[(i + 4) % 8] + p[(i + 5) % 8] + p[(i + 6) % 8];
if (product == 1 && sum == 0) {
_newPixels[x][y] = 0;
_change = true;
break;
}
}
}
}
}