自動新技術化アルゴリズムになる予定だった何か
自動新技術化アルゴリズムになる予定だった何か.
もう飽きたので誰か夢を叶えてください。
- ステージクリックで画像ファイルを選択出来ます
- 肌色以外のところをいい感じに隠してくれ (たらいいなぁ…) ます
- 処理時間かかります
/**
* Copyright beinteractive ( http://wonderfl.net/user/beinteractive )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/i8zl
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
import flash.filters.ColorMatrixFilter;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.net.FileReference;
import flash.utils.ByteArray;
import frocessing.color.ColorHSV;
/**
* 自動新技術化アルゴリズムになる予定だった何か.
*
* もう飽きたので誰か夢を叶えてください。
*
* - ステージクリックで画像ファイルを選択出来ます
* - 肌色以外のところをいい感じに隠してくれ (たらいいなぁ…) ます
* - 処理時間かかります
*/
public class CheckmateFinal extends Sprite
{
//----------------------------------------
// Constatns
//----------------------------------------
private static const YIQFILTER:ColorMatrixFilter = new ColorMatrixFilter([
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.596, -0.274, -0.322, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0, 0.0
]);
private static const BLURFILTER:BlurFilter = new BlurFilter(8, 8);
private static const MASKBLURFILTER:BlurFilter = new BlurFilter(18, 18);
private static const ZERO:Point = new Point(0, 0);
private static const SKIN_THRESHOLD_MIN_I:uint = 20;
private static const SKIN_THRESHOLD_MAX_I:uint = 65;
private static const DIVIDE_MAX_LEVEL:uint = 7;
//----------------------------------------
// Constructor
//----------------------------------------
public function CheckmateFinal()
{
Wonderfl.capture_delay(20);
setupBackground();
setupEventHandler();
}
//----------------------------------------
// Properties
//----------------------------------------
private var _file:FileReference;
private var _displayBitmap:Bitmap;
//----------------------------------------
// Initializing
//----------------------------------------
private function setupBackground():void
{
var bg:Sprite = new Sprite();
bg.graphics.beginFill(0xffffff);
bg.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
bg.graphics.endFill();
addChild(bg);
}
private function setupEventHandler():void
{
stage.addEventListener(MouseEvent.CLICK, stageClickHandler);
}
//----------------------------------------
// Stage Event Handlers
//----------------------------------------
private function stageClickHandler(e:MouseEvent):void
{
selectImageFile();
}
//----------------------------------------
// File Selection
//----------------------------------------
private function selectImageFile():void
{
_file = new FileReference();
_file.addEventListener(Event.SELECT, fileSelectHandler);
_file.browse();
}
//----------------------------------------
// FileReference Event Handlers
//----------------------------------------
private function fileSelectHandler(e:Event):void
{
_file.addEventListener(Event.COMPLETE, fileLoadCompleteHandler);
_file.load();
}
private function fileLoadCompleteHandler(e:Event):void
{
processImageData(_file.data);
_file = null;
}
//----------------------------------------
// Image Processing
//----------------------------------------
private function processImageData(bytes:ByteArray):void
{
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageDataLoadCompleteHandler);
loader.loadBytes(bytes);
}
private function imageDataLoadCompleteHandler(e:Event):void
{
var loaderInfo:LoaderInfo = e.target as LoaderInfo;
var matrix:Matrix = getScaleMatrixToFitStage(loaderInfo.width, loaderInfo.height);
var image:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000);
image.draw(loaderInfo.content, matrix);
makeImaginationInterpolation(image);
displayImage(image);
}
private function getScaleMatrixToFitStage(w:uint, h:uint):Matrix
{
var scale:Number = 1.0;
if (w > stage.stageWidth || h > stage.stageHeight) {
if (w > h) {
scale = stage.stageWidth / w;
}
else {
scale = stage.stageHeight / h;
}
}
var x:Number = (stage.stageWidth - (w * scale)) / 2.0;
var y:Number = (stage.stageHeight - (h * scale)) / 2.0;
var matrix:Matrix = new Matrix();
matrix.scale(scale, scale);
matrix.translate(x, y);
return matrix;
}
private function makeImaginationInterpolation(bitmapData:BitmapData):void
{
// Create working bitmapdata
var aBitmapData:BitmapData = bitmapData.clone();
// YIQ Convertion
aBitmapData.applyFilter(aBitmapData, aBitmapData.rect, ZERO, YIQFILTER);
aBitmapData.applyFilter(aBitmapData, aBitmapData.rect, ZERO, BLURFILTER);
// Extract Skin Color
aBitmapData.threshold(aBitmapData, aBitmapData.rect, ZERO, '>', SKIN_THRESHOLD_MAX_I, 0xff000000, 0x000000ff);
aBitmapData.threshold(aBitmapData, aBitmapData.rect, ZERO, '<', SKIN_THRESHOLD_MIN_I, 0xff000000, 0x000000ff);
aBitmapData.threshold(aBitmapData, aBitmapData.rect, ZERO, '!=', 0x000000, 0xffffffff, 0x00ffffff);
// Reduce Noise
aBitmapData.applyFilter(aBitmapData, aBitmapData.rect, ZERO, BLURFILTER);
aBitmapData.threshold(aBitmapData, aBitmapData.rect, ZERO, '<', 0x555555, 0xff000000, 0x00ffffff);
aBitmapData.threshold(aBitmapData, aBitmapData.rect, ZERO, '!=', 0x000000, 0xffffffff, 0x00ffffff);
// Divide Image
var dividedRects:Array = [];
divideImage(aBitmapData, aBitmapData.clone(), aBitmapData.rect, 0, dividedRects);
// Make mask
var mask:Sprite = new Sprite();
var color:uint = new ColorHSV(Math.random() * 360, 0.8, 0.8).value;
var l:uint = dividedRects.length;
mask.graphics.beginFill(color);
for (var i:uint = 0; i < l; ++i) {
var r:Rectangle = dividedRects[i];
mask.graphics.drawRect(r.x, r.y, r.width, r.height);
}
mask.graphics.endFill();
var maskBitmapData:BitmapData = new BitmapData(bitmapData.width, bitmapData.height, true, 0x00000000);
maskBitmapData.draw(mask);
maskBitmapData.applyFilter(maskBitmapData, maskBitmapData.rect, ZERO, new GlowFilter(color, 1.0, 24, 24, 24));
bitmapData.copyPixels(maskBitmapData, maskBitmapData.rect, ZERO, maskBitmapData, ZERO, true);
}
private function divideImage(bitmapData:BitmapData, tempBitmapData:BitmapData, rect:Rectangle, level:uint, dividedRects:Array):void
{
if (level >= DIVIDE_MAX_LEVEL) {
return;
}
tempBitmapData.fillRect(tempBitmapData.rect, 0xff00ffff);
tempBitmapData.copyPixels(bitmapData, rect, ZERO);
var whiteBounds:Rectangle = tempBitmapData.getColorBoundsRect(0xffffff, 0xffffff);
if (whiteBounds.isEmpty()) {
if (rect.width <= stage.stageWidth / 8 && rect.height <= stage.stageHeight / 8) {
if (rect.width >= stage.stageWidth / 128 && rect.height >= stage.stageHeight / 128) {
dividedRects.push(rect);
}
}
return;
}
var blackBounds:Rectangle = tempBitmapData.getColorBoundsRect(0xffffff, 0x000000);
if (blackBounds.isEmpty()) {
return;
}
var x:Number = blackBounds.x + rect.x;
var y:Number = blackBounds.y + rect.y;
var w:Number = blackBounds.width / 2.0;
var h:Number = blackBounds.height / 2.0;
if (w < 1.0 || h < 1.0) {
return;
}
var lv:uint = level + 1;
divideImage(bitmapData, tempBitmapData, new Rectangle(x, y, w, h), lv, dividedRects);
divideImage(bitmapData, tempBitmapData, new Rectangle(x + w, y, w, h), lv, dividedRects);
divideImage(bitmapData, tempBitmapData, new Rectangle(x, y + h, w, h), lv, dividedRects);
divideImage(bitmapData, tempBitmapData, new Rectangle(x + w, y + h, w, h), lv, dividedRects);
}
//----------------------------------------
// Display
//----------------------------------------
private function displayImage(image:BitmapData):void
{
if (_displayBitmap == null) {
_displayBitmap = addChild(new Bitmap(image)) as Bitmap;
}
else {
_displayBitmap.bitmapData = image;
}
}
}
}