Harris Corner Detection

by utabi
特徴点の検出
こちらのページを参考にやってみた
http://www.cagylogic.com/archives/2009/03/03000100.php
http://users.ecs.soton.ac.uk/msn/book/new_demo/corners/
結構解釈をまちがってるかもしれない
♥0 | Line 163 | Modified 2009-10-04 14:32:03 | MIT License
play

ActionScript3 source code

/**
 * 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;
		};
	}
}