細線化と境界抽出
画像処理の練習 -->細線化と境界抽出
/**
* Copyright termat ( http://wonderfl.net/user/termat )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/itjD
*/
/*
画像処理の練習 -->細線化と境界抽出
*/
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
[SWF(framerate = "30", width = "480",height="480",backgroundColor="0xffffff")]
public class Practice34 extends Sprite{
private var text:TextField;
private var image:StrImage;
private var tf:TextFormat;
public function Practice34() {
text = new TextField();
text.type = TextFieldType.INPUT;
text.text = "2月28日";
text.restrict = null;
text.width = 60; text.height = 20;
text.border = true;
text.x = 2; text.y = 5;
addChild(text);
var bt0:Button = new Button(30, 20, 4, "exe", 11);
bt0.x = 50; bt0.y = 5;
bt0.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void { image.draw(text.text, tf);} );
addChild(bt0);
tf = new TextFormat();
tf.size = 128;
tf.color = 0x000000;
tf.bold = true;
image = new StrImage(text.text, tf);
addChild(image);
image.x = 5; image.y = 30;
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.filters.ColorMatrixFilter;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
class StrImage extends MovieClip {
public var bmpdata:BitmapData;
public var thin:BitmapData;
public var border:BitmapData;
private var bmp:Bitmap;
private var list:Vector.<uint>;
public function StrImage(str:String,format:TextFormat):void {
var text:TextField = new TextField();
text.defaultTextFormat = format;
text.text = str;
text.width = text.textWidth;
text.height = text.textHeight;
bmpdata = new BitmapData(text.textWidth + 2, text.textHeight + 2, false, 0xffffff);
bmpdata.fillRect(bmpdata.rect,0xffffff);
bmpdata.lock();
bmpdata.draw(text);
bmpdata.unlock();
addChild(new Bitmap(bmpdata, "auto", true));
thin = new BitmapData(text.textWidth + 2, text.textHeight + 2, false, 0xffffff);
thin.fillRect(thin.rect, 0xffffff);
var b2:Bitmap = new Bitmap(thin, "auto", true);
b2.y = bmpdata.height + 5;
addChild(b2);
border = new BitmapData(text.textWidth + 2, text.textHeight + 2, false, 0xffffff);
border.fillRect(border.rect, 0xffffff);
var b3:Bitmap = new Bitmap(border, "auto", true);
b3.y = bmpdata.height * 2 + 10;
addChild(b3);
}
public function draw(str:String,format:TextFormat):void {
var text:TextField = new TextField();
text.defaultTextFormat = format;
text.text = str;
text.width = text.textWidth;
text.height = text.textHeight;
bmpdata.fillRect(bmpdata.rect,0xffffff);
bmpdata.lock();
bmpdata.draw(text);
bmpdata.unlock();
traceBorder();
thinning();
}
public function thinning():void {
thin.fillRect(thin.rect,0xffffff);
var main:Vector.<Vector.<uint>> = new Vector.<Vector.<uint>>();
var sub:Vector.<Vector.<uint>> = new Vector.<Vector.<uint>>();
for (var x:int = 0; x < bmpdata.width; x++) {
var mp:Vector.<uint> = new Vector.<uint>();
var ss:Vector.<uint> = new Vector.<uint>();
for (var y:int = 0; y < bmpdata.height; y++) {
if (bmpdata.getPixel(x, y) == 0x000000) {
mp[y] = 1; ss[y] = 1;
}else {
mp[y] = 0; ss[y] = 0;
}
}
main[x] = mp; sub[x] = ss;
}
var aa:Array = [0, 0, 0, 0, 0, 0, 0, 0, 0];
var bb:Array = [0, 0, 0, 0, 0, 0, 0, 0, 0];
var rev:int = 1;
var num:int = 0;
while(rev!=0){
rev=0;
num++;
for(y=1;y<bmpdata.height-1;y++){
for(x=1;x<bmpdata.width-1;x++){
if(main[x][y]==0)continue;
aa[0]=main[x+1][y]; bb[0]=sub[x+1][y];
aa[1]=main[x+1][y-1]; bb[1]=sub[x+1][y-1];
aa[2]=main[x][y-1]; bb[2]=sub[x][y-1];
aa[3]=main[x-1][y-1]; bb[3]=sub[x-1][y-1];
aa[4]=main[x-1][y]; bb[4]=sub[x-1][y];
aa[5]=main[x-1][y+1]; bb[5]=sub[x-1][y+1];
aa[6]=main[x][y+1]; bb[6]=sub[x][y+1];
aa[7]=main[x+1][y+1]; bb[7]=sub[x+1][y+1];
var sum:int=0;
for (var i:int=0;i<8;i++) sum +=aa[i];
if(sum==0)sub[x][y]=0;
if(sum>=2&&sum<=5){
if(connect(aa)==1&&connect(bb)==1){
for(var j:int=1;j<5;j++){
if(bb[j]==0){
var c:int=aa[j];
aa[j]=0;
if(connect(aa)!=1){
aa[j]=c;
break;
}
aa[j]=c;
}
sub[x][y]=0;
}
}
}
if(sub[x][y]==0)rev++;
}
}
for(y=1;y<bmpdata.height-1;y++){
for(x=1;x<bmpdata.width-1;x++){
main[x][y]=sub[x][y];
}
}
}
for (y = 1; y < bmpdata.height - 1; y++) {
for (x = 1; x < bmpdata.width-1; x++) {
if (main[x][y] == 1) thin.setPixel(x, y, 0xff0000);
}
}
}
private function connect(val:Array):int {
val[8]=val[0];
var num:int=0;
for (var i:int = 1; i < val.length; i++) {
if (val[i] == 1 && val[i - 1] == 0) num++;
}
return num;
}
public function traceBorder():void {
border.fillRect(thin.rect,0xffffff);
var p:Vector.<Vector.<uint>> = new Vector.<Vector.<uint>>();
var b:Vector.<Vector.<uint>> = new Vector.<Vector.<uint>>();
for (var x:int = 0; x < bmpdata.width; x++) {
var mp:Vector.<uint> = new Vector.<uint>();
var ss:Vector.<uint> = new Vector.<uint>();
for (var y:int = 0; y < bmpdata.height; y++) {
if (bmpdata.getPixel(x, y) == 0x000000) {
mp[y] = 1;
ss[y] = 0;
}else {
mp[y] = 0;
ss[y] = 0;
}
}
p[x] = mp;
b[x] = ss;
}
b=border_trace(p,b);
for(y=0;y<bmpdata.height;y++){
for(x=0;x<bmpdata.width;x++){
if (b[x][y] == 1) border.setPixel(x, y, 0xff0000);
}
}
}
private function border_trace(p:Vector.<Vector.<uint>>,b:Vector.<Vector.<uint>>):Vector.<Vector.<uint>>{
var code:int=0;
for(var y:int=1;y<bmpdata.height-1;y++){
for(var x:int=1;x<bmpdata.width-1;x++){
if(p[x][y]==1&&b[x][y]==0){
if(p[x-1][y]==0){
code=0;
trace(x,y,code,p,b);
}else if(p[x+1][y]==0){
code=4;
trace(x,y,code,p,b);
}
}
}
}
return b;
}
private function trace(x:int,y:int,code:int,p:Vector.<Vector.<uint>>,b:Vector.<Vector.<uint>>):void{
if(!check(x,y,p))return;
var xs:int= x; var ys:int=y; var x1:int=x; var x2:int=0; var y1:int=y; var y2:int=0;
while(x2!=xs||y2!=ys){
switch(code){
case 0:
x2=x1;
y2=y1+1;
if(y2<height&&p[x2][y2]==1){
code=6;
}else{
code=2;
}
break;
case 2:
x2=x1+1;
y2=y1;
if(x2<width&&p[x2][y2]==1){
code=0;
}else{
code=4;
}
break;
case 4:
x2=x1;
y2=y1-1;
if(y2>=0&&p[x2][y2]==1){
code=2;
}else{
code=6;
}
break;
case 6:
x2=x1-1;
y2=y1;
if(x2>=0&&p[x2][y2]==1){
code=4;
}else{
code=0;
}
break;
}
if(x2>=0&&x2<width&&y2>=0&&y2<height){
if(p[x2][y2]==1){
b[x2][y2]=1;
x1=x2;
y1=y2;
}
}
}
}
private function check(x:int,y:int,p:Vector.<Vector.<uint>>):Boolean{
if(p[x-1][y]==0&&p[x+1][y]==0&&p[x][y-1]==0&&p[x][y+1]==0){
return false;
}else{
return true;
}
}
}
class Button extends Sprite{
private static const mono:ColorMatrixFilter = new ColorMatrixFilter([
1 / 3, 1 / 3, 1 / 3, 0, 10, 1 / 3, 1 / 3, 1 / 3, 0, 10,
1 / 3, 1 / 3, 1 / 3, 0, 10, 0,0,0, 1, 0]);
private var _hover:Boolean = false;
public function get hover():Boolean{
return _hover;
}
public function set hover(value:Boolean):void{
if(_hover != value){
_hover = value;
filters = (_hover ? null : [mono]);
}
}
public function Button(W:Number, H:Number, R:Number, label:String = "", size:int = 11){
var matrix:Matrix = new Matrix();
matrix.createGradientBox(W, H, Math.PI / 2);
var bg:Sprite = new Sprite();
bg.graphics.beginGradientFill("linear", [0xDDE9F4, 0xD5E4F1, 0xBAD2E8], [1, 1, 1],[0, 120, 136], matrix);
bg.graphics.drawRoundRect(0, 0, W, H, R, R);
bg.graphics.endFill();
bg.filters = [new GlowFilter(0xFFFFBE, .5, 10, 10, 2, 1, true)];
addChild(bg);
var line:Sprite = new Sprite();
line.graphics.lineStyle(3, 0xBAD2E8);
line.graphics.drawRoundRect(0, 0, W, H, R, R);
addChild(line);
filters = [mono];
buttonMode = true;
mouseChildren = false;
if (label != ""){
var textField:TextField = new TextField();
textField.selectable = false;
textField.autoSize = "left";
textField.htmlText = <font size={size} color="#6B8399">{label}</font>.toXMLString();
textField.x = (W - textField.width) / 2;
textField.y = (H - textField.height) / 2;
addChild(textField);
}
addEventListener("rollOver", buttonRollOver);
addEventListener("rollOut", buttonRollOut);
addEventListener("removed", function(event:Event):void{
removeEventListener("rollOver", buttonRollOver);
removeEventListener("rollOut", buttonRollOut);
removeEventListener("removed", arguments.callee);
});
}
protected function buttonRollOver(event:Event):void{
hover = true;
}
protected function buttonRollOut(event:Event):void{
hover = false;
}
}