요즘 한창 Image Processing에 관해서 공부를 하다가 제스처를 인식하여 마스크 효과를 적용해보면 어떨까하여 만들어 보았다. 이미지를 다루는 것이 아직도 서툴고 개념적으로 박히기에는 멀었다. 하지만 결과적으로는 재미있는 아웃풋이 나왔다.
우선, 제스처에 관련된 소스를 검색하여 개념을 익히는 일을 선행하였고, 이것을 어떻게 요리를 할 것인가에 대한 접근을 하면서 Step by Step으로 풀어나갔다.
코드의 중요 핵심은 제스처로 얻어낸 이미지를 어떠한 형태로 변형하여 마스크에 적용하느냐는 것이였다. 생각해 보면 그리 어렵지 않다고 판단했지만… 어려웠다.
우선 아래와 같이 Bitmap에 마스크를 적용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
_image = new Bitmap( new NightImage( 0 , 0 ) , "auto" , true ) ;
_image.x = 10 ;
_image.y = 10 ;
_image.width = _output.width ;
_image.height = _output.height ;
addChild( _image)
_mask = new Bitmap( new BitmapData( _output.width , _output.height ) ) ;
_mask.x = 10 ;
_mask.y = 10 ;
addChild( _mask) ;
_image.mask = _mask;
_image.cacheAsBitmap = true ;
_mask.cacheAsBitmap = true ;
위에서 보면 단순하지만 이미지 데이터는 쉽게 마스킹이 되지 않는다.
이미지 속성에 마스크를 적용하기 위해서는 “white & black” 으로만 적용을 할 수가 있다.
그래서 아래와 같이 캠 화면에 찍힌 이미지에 필터를 적용하여 반전을 시켜 흰색만을 추출해 내야 한다.
1
2
3
4
5
6
7
8
_now.draw ( _src, _mtx) ;
_now.draw ( _old, null , null , BlendMode.DIFFERENCE ) ;
_now.applyFilter ( _now, _now.rect , new Point( ) , _col) ;
_now.applyFilter ( _now, _now.rect , new Point( ) , _blr) ;
_now.threshold ( _now, _now.rect , new Point( ) , '>' , 0xFF333333, 0xFFFFFFFF) ;
_old.draw ( _src, _mtx) ;
그리고 다음 코드와 같이 검은색을 알파 처리해서 적용하면 끝이다.
1
2
_mask.bitmapData .threshold
( _output.bitmapData , _output.bitmapData .rect , new Point( ) , '>' , 0xFF000000, 0x00000000) ;
요번 작업으로 많은 이미지 데이터 처리가 존재한다는 것을 알게되었다.
이러한 효과를 여러가지 형태로 응용이 가능해 보인다.
작업을 하면서 느낀점은 빛에 대한 처리가 가장 힘들다.
그리고, 플래시의 캠 인식 속도가 느려서 많은 것을 시도하기에는 어렵다는 것이다.
결론적으로, 플래시로도 요번과 같은 인식에 대한 것들을 제작할 수 있지만
프로토타입핑 수준이라고 생각된다.
회사를 그만 두고 잠시 쉴려고 하였는데,
우연찮게 재미있는 프로젝트가 들어와 내 정신을 사로잡아 버렸다.
소켓 통신으로 제스처 명령을 받아 처리를 하는 것으로 콘텐츠 만드는게 조금은 번거롭다.
마우스와 키보드, 외부 소켓 명령을 동시에 소화를 시켜야 하니 작업 시간이 만만치 않다.
풀 플래시 콘텐츠로 스트럭처 역시 화면의 따라 명령을 받게 처리해야 하므로 쉽게 만들 수 없는 부분이라 내 머리가 아플 정도다. 우선은 타스크 기반으로 작업을 하고 있는데, 거의 개발 수준으로 진행이 되고 있다. 그래서 요즘 정신이 없다. 화도 약간 났지만… 머~ 이런것도 프로젝트의 묘미지…
소켓 통신을 처음 해봤는데 생각보다 로컬에서는 쉽게 작동한다.
소켓 프로그램을 열고 명령을 받아서 작동되는 것도 몇 개 테스트 해봤다.
프로젝트가 끝나면 동영상으로 소켓 통신으로 작동되는 콘텐츠를 찍어 올리고,
간단한 통신에 대한 부분도 기재하려 한다.
프로젝트를 진행하면서 문제점이 있다면, 아직 상용화되지 않은 부분이라 콘셉트나 콘티 보다는 작동에 대한 디테일한 동작에 대해서 작업이 진행이 되어 조금은 힘들다는 정도? 알고 가는 길이 아니라 그냥 따라서 걷는 듯한 느낌의 프로젝트?? ㅋ
어쨌든 재미있게 작업하고 있으니 잘 되리라 생각된다. 연구소에도 한번 가서 작동 되는 원리라던지 기타 궁금한 것들도 여력이 된다면 배워보고 싶다.
요번달은 금방 지나갈듯…
처리할 것들이 많은데… 냠냠…
오늘 작업을 하다가 XML 노드에 엔터 문자(\n) 적용이 안되어서 고생을 좀 했다.
var s:String ="Drama & \n Movie & \n Animation" ;
trace ( -1 < s.indexOf ( "\n " ) )
true
var xml :XML = < a> Drama & \nMovie & \nAnimation</ a>
s = xml .toString ( ) ;
trace ( -1 < xml .indexOf ( "\n " ) )
false
XML 데이터는 ‘\n’ 문자를 왜 찾지를 못할까?
아마도 내부의 태그 중 무엇인가가 포장이 되어있을 것이다.
TextField에서는 이와 같은 경우가 눈으로 확인이 가능하다.
아래는 TextField를 생성하여 “엄진우” 라고 입력하고, trace(TextFieild.htmlText) 한 결과다.
<TEXTFORMAT LEADING="2">
<P ALIGN="LEFT">
<FONT FACE="Dotum" SIZE="20" COLOR="#000000" LETTERSPACING="0" KERNING="1">
엄진우
</FONT>
</P>
</TEXTFORMAT>
위와 같이 “엄진우” 란 글자를 htmlText 속성으로 넣고 출력하면,
텍스트 포멧 태그가 생성이 된다.
어쨌든, XML이 위와 같은 상태인지는 더 자세히 알아보려 했지만 작업을 해야하므로,
아래의 명령어로 아주 간단하게 치환을 시킬 수 있다.
바로 escape , unescape 을 사용하여서 말이다.
아래의 메서드는 원하는 XML 값과 치환하고자 하는 값을 인자로 넘겨주면 된다.
즉, \n로 치환을하여 리턴을 해주므로 바로 text 속성에 대입을 하면 끝이다.
/** xml 데이터 중 치환하고자 하는 escape(String)을 넘기면 문자로 변환하여 반환함. */
function splitXMLToString( node:String = "" , pat:String = "" ) :String
{
var s:String = escape( node) ;
var a:Array = s.split ( pat) ; // "%5Cn" == /n
var leng:int = a.length ;
for ( var i:int = 0 ; i < leng; i++)
{
a[ i] = unescape ( a[ i] )
}
return a.join ( "\n " ) ;
}
var xml :XML = < test> 엄\n진\n우</ test> ;
tf.text = splitXMLToString( xml .toString ( ) , escape( "\\ n" ) ) as String ;
아래와 같은 텍스트 필드 결과가 출력된다.
이런 방식 말고, 다른 류가 존재한다면 코멘트를 달아주면 감사. ^^