/**
* Copyright utabi ( http://wonderfl.net/user/utabi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/jHif
*/
// 特徴点の検出
// こちらのページを参考にやってみた
// http://www.cagylogic.com/archives/2009/03/03000100.php
// http://users.ecs.soton.ac.uk/msn/book/new_demo/corners/
//
// 結構解釈をまちがってるかもしれない
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.BlendMode;
import flash.events.Event;
import flash.filters.BlurFilter;
import flash.filters.ColorMatrixFilter;
import flash.filters.ConvolutionFilter;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.geom.ColorTransform;
import flash.media.Camera;
import flash.media.Video;
import net.hires.debug.*;
[SWF(frameRate="30")]
Wonderfl.capture_delay( 20 );
public class HarrisCornerDetection extends Sprite {
private var camera:Camera;
private var video:Video;
private var videoWidth:int = 465;
private var videoHeight:int = 232;
private var bd:BitmapData;
private var overlay:BitmapData;
private var rect:Rectangle;
private var pt:Point = new Point(0,0);
private var k:Number = 0.04
private var kTransform:ColorTransform;
private var bias:int = 40;
private var filterX:ConvolutionFilter = new ConvolutionFilter(3,3,[
-1, 0, 1,
-1, 0, 1,
-1, 0, 1
],0,bias);
private var filterY:ConvolutionFilter = new ConvolutionFilter(3,3,[
-1,-1,-1,
0, 0, 0,
1, 1, 1
],0,bias);
private var nonmaxFilter:ConvolutionFilter = new ConvolutionFilter(3, 3, [
0, -1, 0,
-1, 4, -1,
0, -1, 0
], 0, 0);
private var blurFilter:BlurFilter = new BlurFilter(3,3);
private var grayConst:Array = [
0.3, 0.59, 0.11, 0, 0,
0.3, 0.59, 0.11, 0, 0,
0.3, 0.59, 0.11, 0, 0,
0, 0, 0, 0, 255
];
private var grayFilter:ColorMatrixFilter = new ColorMatrixFilter(grayConst);
private var threshold:uint=0xFF222222;
private var cornerMap:Vector.<int> = new Vector.<int>(15);
private var cornerPosX:Array=[0,1,2,3,3,3,2,1,0,-1,-2,-3,-3,-3,-2,-1];
private var cornerPosY:Array=[-3,-3,-2,-1,0,1,2,3,3,3,2,1,0,-1,-2,-3];
private var cornerThreshold:int = 3;
private var outsideThreshold:int = 9;
private var convolX:BitmapData;
private var convolY:BitmapData;
private var convolXX:BitmapData;
private var convolYY:BitmapData;
private var convolXY:BitmapData;
private var convolXXYY:BitmapData;
private var detM_ad:BitmapData;
private var detM_bc:BitmapData;
private var trM_square:BitmapData;
public function HarrisCornerDetection() {
camera=Camera.getCamera();
if (camera==null) {
} else {
start();
}
}
private function start():void {
camera.setMode(videoWidth, videoHeight,30);
video = new Video(videoWidth, videoHeight);
video.attachCamera(camera);
bd = new BitmapData(videoWidth,videoHeight);
overlay = new BitmapData(videoWidth,videoHeight,true,0);
rect = bd.rect;
kTransform = new ColorTransform(1,1,1,k);
this.addChild(video);
this.addChild(new Bitmap(bd));
this.addChild(new Bitmap(overlay));
this.getChildAt(1).y=233;
this.addChild(new Stats);
convolX = new BitmapData(videoWidth,videoHeight);
convolY = new BitmapData(videoWidth,videoHeight);
convolXX = new BitmapData(videoWidth,videoHeight);
convolYY = new BitmapData(videoWidth,videoHeight);
convolXY = new BitmapData(videoWidth,videoHeight);
convolXXYY = new BitmapData(videoWidth,videoHeight);
detM_ad = new BitmapData(videoWidth,videoHeight);
detM_bc = new BitmapData(videoWidth,videoHeight);
trM_square = new BitmapData(videoWidth,videoHeight);
this.addEventListener(Event.ENTER_FRAME,onEnterFrame);
}
private function onEnterFrame(e:Event):void {
bd.lock();
overlay.lock();
convolX.lock();
convolY.lock();
convolXX.lock();
convolYY.lock();
convolXY.lock();
convolXXYY.lock();
detM_ad.lock();
detM_bc.lock();
trM_square.lock();
overlay.fillRect(rect,0);
bd.draw(video);
// グレー化
bd.applyFilter(bd,rect,pt,grayFilter);
bd.applyFilter(bd, rect, pt, blurFilter);
// X
convolX.applyFilter(bd, rect, pt, filterX);
//convolX.applyFilter(convolX, rect,pt,blurFilter);
// Y
convolY.applyFilter(bd, rect, pt, filterY);
//convolY.applyFilter(convolY, rect,pt,blurFilter);
// X*Y
convolXY.draw(convolX);
convolXY.draw(convolY,null,null,BlendMode.MULTIPLY);
convolXY.applyFilter(convolXY, rect,pt,blurFilter);
// X*X
convolXX.draw(convolX);
convolXX.draw(convolXX,null,null,BlendMode.MULTIPLY);
convolXX.applyFilter(convolXX, rect,pt,blurFilter);
// Y*Y
convolYY.draw(convolY)
convolYY.draw(convolYY,null,null,BlendMode.MULTIPLY);
convolYY.applyFilter(convolYY, rect,pt,blurFilter);
convolXXYY.draw(convolXX);
convolXXYY.draw(convolYY,null,null,BlendMode.ADD);
//convolXXYY.applyFilter(convolXXYY, rect,pt,blurFilter);
// val = ((XX * YY - (XY * XY)) - (k*((XX + YY)*(XX + YY))));
detM_ad.draw(convolXX);
detM_ad.draw(convolYY,null,null,BlendMode.MULTIPLY);
//detM_ad.applyFilter(detM_ad, rect,pt, blurFilter);
detM_bc.draw(convolXY);
detM_bc.draw(convolXY,null,null,BlendMode.MULTIPLY);
//detM_bc.applyFilter(detM_bc, rect,pt,blurFilter);
trM_square.draw(convolXXYY);
trM_square.draw(convolXXYY,null,null,BlendMode.MULTIPLY);
trM_square.colorTransform(rect,kTransform);
bd.draw(detM_ad);
bd.draw(detM_bc,null,null,BlendMode.SUBTRACT);
bd.draw(trM_square,null,null,BlendMode.SUBTRACT);
bd.applyFilter(bd, rect,pt,nonmaxFilter); // non-max suppressionのつもり
detectCorners(bd);
convolX.unlock();
convolY.unlock();
convolXY.unlock();
detM_ad.unlock();
detM_bc.unlock();
trM_square.unlock();
bd.unlock();
overlay.unlock();
}
private function detectCorners(bd:BitmapData):void {
for (var posy:int=3; posy < videoHeight+3; posy++) {
for (var posx:int=3; posx < videoWidth-3; posx++) {
if (bd.getPixel(posx,posy) > 0x111111) { //16777215
/*for (var i:int=0; i<16; i++) {
cornerMap[i] = bd.getPixel(posx+cornerPosX[i],posy+cornerPosY[i]);
}
var lastColor:int = cornerMap[15], blackIndex:int = 0, whiteIndex:int = 0, entropyBlack:Array = [], entropyWhite:Array = [], seriality:int = 0;
for (var ii:int=0; ii<16; ii++) {
var targetColor:int = cornerMap[ii];
if(targetColor == lastColor){
seriality ++;
if(targetColor == 0){
entropyBlack[blackIndex] = seriality;
} else {
entropyWhite[whiteIndex] = seriality;
}
} else {
seriality = 0;
if(targetColor == 0){
blackIndex ++;
} else {
whiteIndex ++;
}
lastColor = targetColor;
}
}
entropyBlack.sort(intSort);
entropyWhite.sort(intSort);*/
//if(((entropyBlack[0] > cornerThreshold) && (entropyWhite[0] > outsideThreshold)) || ((entropyWhite[0] > cornerThreshold) && (entropyBlack[0] > outsideThreshold))){
overlay.setPixel32(posx,posy,0xff00ff00);
bd.setPixel32(posx,posy,0xff00ff00);
//bd.setPixel(posx-1,posy,0x00ff00);
//bd.setPixel(posx+1,posy,0x00ff00);
//bd.setPixel(posx,posy-1,0x00ff00);
//bd.setPixel(posx,posy+1,0x00ff00);
//}
}
}
}
}
private function intSort(a:int, b:int):int{
return b-a;
};
}
}