목표
2대의 Wiimote를 이용하여 3D 공간에 위치한 광점(IRED)의 x,y,z 좌표값을 구한다.

본 기능은 다음의 경우에 응용할 수 있습니다.
1. 3D 스캐너 만들기
2. 헤드 트래킹(단순 위치 파악형 및 3광점 헤드 트래킹)
3. 3D 마우스

※ 3광점 헤드 트래킹:
3개의 IRED를 이용하면 단순히 위치를 파악하는것 뿐아니라 어느방향을 바라보는지도 알수 있습니다. 관련링크 참조

준비물
Wiimote 2개,  IRED(적외선LED) (참고링크2 참조) 
기타 Wiimote 사용을 위해 필요한 게이트웨이 SW 및 BT 장치 등.

Wiimote 설치 및 연동
Wiimote와 Flash를 연동하는 방법은  참고링크1.을 참고하시기 바랍니다. 

Wiimote로 측정 가능한 정보
wiimote에는 3축 가속센서, 여러개의 버튼이 포함되어있고, 내장된 적외선 카메라로 적외선 광점의 좌표값을 4개까지 인식할 수 있습니다. 물론 wiimote에서 출력해주는 좌표값은 카메라 스크린을 기준으로한 x,y 좌표(2D)좌료 값이므로 이것만으로는 3D좌표값을 구할수 없습니다. 하지만 wiimote를 2개 이상 사용한다면, 이 값들의 조합으로 3D 좌표값을 구해 낼 수 있습니다.
참고로 일반적인 WebCam으로도 가능합니다. 다만 wiimote를 사용하므로써 광점을 인식처리해주는 이미지 처리과정이 필요없고, wiimote의 기타 센서 기능을 함께 사용할 수 있으므로 목적에따라 선택하여 사용하면 됩니다.
아래의 이미지는 WiiFlash Server에서 기본 제공되는 데모 실행화면입니다. 버튼의 눌림상태와 각종 센서들의 수치값이 실시간으로 보여지는 것을 볼 수있습니다.




예제 소스
아래에 첨부된 소스는 Wiimote 2개( WA와 WB)를 이용하여  3차원공간상에 위치한 광점(ir Point)의 좌표값을 계산하는 예제 소스입니다. 저는 이를 기초로하여 3D 스캐너와 헤드트래킹을 구현했습니다. 좀더 고급 수학을 이용한 복잡한 방법이 있을듯 합니다만  저는 잘 모르고요, 제가 아는 범위의 단순한 삼각함수를 이용했습니다. 중.고등학교 과정의 수학이면 이해 가능할 듯 합니다.

package{
	import org.wiiflash.Wiimote;
	import org.wiiflash.events.ButtonEvent;
	import org.wiiflash.events.WiimoteEvent;
	import flash.events.*;
	import flash.display.*;
	import flash.text.TextField;
	
	public class PositionDetector extends Sprite{

		public const D2R:Number = Math.PI / 180;
		public const R2D:Number = 180 / Math.PI;
		// Calibration 수치
		public const IRX2DEG:Number = 41;
		public const IRY2DEG:Number = 32;
		private var L:Number = 500;				//500mm
		private var WA_LRCenterDeg:Number = 60;
		private var WA_UDCenterDeg:Number = 0;
		private var WB_LRCenterDeg:Number = 120;
		private var WB_UDCenterDeg:Number = 0;

		// p(x,y,z)산출 기본자료
		private var WAirx:Number;
		private var WAiry:Number;
		private var WBirx:Number;
		private var WBiry:Number;

		private var p1x:Number;
		private var p1y:Number;
		private var p1z:Number;

		// create a new Wiimote
		private var WA:Wiimote = new Wiimote();
		private var WB:Wiimote = new Wiimote();
				
		public function PositionDetector(){
			//ir value update EventListener 설정
			WA.addEventListener( Event.CONNECT, onWiimoteConnect );
			WA.addEventListener( IOErrorEvent.IO_ERROR, onWiimoteConnectError );
			WA.addEventListener( Event.CLOSE, onCloseConnection );
			WA.addEventListener( WiimoteEvent.UPDATE, WiimoteAUpdateHandler );
			WB.addEventListener( Event.CONNECT, onWiimoteConnect );
			WB.addEventListener( IOErrorEvent.IO_ERROR, onWiimoteConnectError );
			WB.addEventListener( Event.CLOSE, onCloseConnection );
			WB.addEventListener( WiimoteEvent.UPDATE, WiimoteBUpdateHandler );								
			WA.connect ();
			WB.connect ();
			Canvas2D.point.visible = false;
		}

		function onCloseConnection ( pEvent:Event ):void{
			trace("onClose: " + pEvent.target );
		}
		
		function onWiimoteConnectError ( pEvent:IOErrorEvent ):void{
			trace("onError: " + pEvent.target );
		}
		
		function onWiimoteConnect ( pEvent:Event ):void{
			trace( "Wiimote successfully connected: " + pEvent.target );
		}		

		public function WiimoteAUpdateHandler(pEvent:WiimoteEvent){
			if(pEvent.target.ir.p1){	
				WAirx = WA.ir.x1;
				WAiry = WA.ir.y1;
			}			
		}
		public function WiimoteBUpdateHandler(pEvent:WiimoteEvent){
			if(pEvent.target.ir.p1){	
				WBirx = WB.ir.x1;
				WBiry = WB.ir.y1;
				Canvas2D.point.visible = true;				
				CalcProcess();
			}else{
				Canvas2D.point.visible = false;
			}
		}
		public function CalcProcess(){
			//irx => WADeg => WAm(기울기)  , WBm도함께
			var WADeg:Number = WA_LRCenterDeg - ( WAirx - 0.5 ) * IRX2DEG;
			var WAm:Number = Math.tan( WADeg * D2R);
			trace( WADeg, WAm);
			var WBDeg:Number = WB_LRCenterDeg - ( WBirx - 0.5 ) * IRX2DEG;
			var WBm:Number = Math.tan( WBDeg * D2R);

			// 기울기를 알고있는 두 선분의 교점P(x,z) 구하기  
			// WA는 (0,0)  WB는 (L,0)을 지나는경우이며,  WA/WB 수평평면이 x/z 평면이다.
			p1x = ( -WBm * L ) / ( WAm - WBm ) ;
			p1z = WAm * p1x;

			// py구하기
			var Lxz:Number = Math.sqrt( p1x * p1x + p1z * p1z ) ;
			var WA_UDDeg:Number = WA_UDCenterDeg - ( WAiry - 0.5 ) * IRY2DEG;
			p1y = - Math.tan( WA_UDDeg *D2R ) * Lxz;

			// p(x,y,z)표시
			PointXYZ.text = "px = " + String(p1x);
			PointXYZ.text += "\npy = " + String(p1y);
			PointXYZ.text += "\npz = " + String(p1z);			
			
			var Lcan = Canvas2D.WB.x - Canvas2D.WA.x;
			Canvas2D.point.x = Canvas2D.WA.x + p1x  * Lcan / L;
			Canvas2D.point.y = Canvas2D.WA.y - p1z * Lcan / L;
		}
	}
}


예제 소스 설명

1. 장비 설치에 따른 수치 정의
측정하기 전에 WA와 WB의 world좌표상의 거리 L과  x축을 기준으로 한 회전각을 정의합니다.
좀더 노력하면 자동으로 Calibration하여 이값들을 구해낼 수 도 있으나, 본 예제는 기초적인 수학으로 3차원 자표값을 구해내는것을 목표로 하므로, 단순하게 직접 측정하여 기입하는 방식을 사용합니다.
 정의되야할 정보는 아래와 같습니다.

private var L:Number = 500;                           // WA와 WB 사이의 거리, 이경우 500mm
private var WA_LRCenterDeg:Number = 60;      // WA의 좌우 회전각 (Deg)
private var WA_UDCenterDeg:Number = 0;        // WA의 상하 회전각
private var WB_LRCenterDeg:Number = 120;     // WB의 좌우 회전각
private var WB_UDCenterDeg:Number = 0;        // WB의 좌우 회전각
public const IRX2DEG:Number = 41;                // Wiimote의 수평 화각이다.  (측정 값이며 오차있음)
public const IRY2DEG:Number = 32;                // Wiimote의 수직 화각이다.  (측정 값이며 오차있음)


그림1. Wiimote 설정치 참조도 (xz평면도)

2. 작동프로세스
Wiimote의 update 이벤트 발생시마다,  WA,WB모두에서 irPoint 가 발견될 경우에만 WA,WB의 irx,iry를 구한 뒤, p(x,y,z) 값  px,py,pz을 구합니다.


3. 실제 좌표값을 구하는 수학은 간단한 삼각함수를 이용합니다.  소스를 보시고 이해해 보시거나 직접 삼각함수로 연산을 해보시면 됩니다. 단, 한가지 알아둘 사항은 Wiimote에서 출력해주는 좌표값은 0~1 사이의 값이기 때문에 이값을 각도에 해당하는 값으로 변환해줘야 삼각함수 연산이 가능합니다.  이때문에 Wiimote의 화각정보를 미리 측정해 둬야하는데요, 가령 Wiimote의 좌우방향 화각이 30도라고 합시다.   이경우 광점이 가장 왼쪽경계에서 발견된다면  wiimote의 irx값은 0으로 출력됩니다.  그리고 만약 우측 경계부분에서 광점이 발견되면 irx의 값은 1이 됩니다.  또한 Wiimote 화각의 중심점에서 발견될 경우 이값은 정확이 0.5로 출력됩니다.

즉, 아래와 같이 변환될 수 있습니다.
 irx  0  0.25  0.5 0.75
1
중심기준 각도(deg)
 -15  -7.5 0
 7.5  15

실제 코드상에서는 아래와 같이 계산합니다.
var WADeg:Number = WA_LRCenterDeg - ( WAirx - 0.5 ) * IRX2DEG;


추가로, D2R 과 R2D 는 Deg각도 값과 Radian값을 변환해주는 상수 값입니다. 
Degree값을 Radian값으로 바꾸려면 D2R을 곱해주면 됩니다.  마찬가지로 Rad를 Deg로 변환하려면 R2D값을 곱해주면 됩니다.




동영상1. 3차원 좌표값 실시간 구하기


사진1. 설치예




SymBall은 2004년 겨울 플래시를 처음 접한 후 만든 첫 작품? 입니다.
이번에 로보밥 블로그 오픈을 계기로 다시 Online에 올려봤습니다. 한번 심심풀이 심볼 해보시죠!!

본 어플의 목적:
  동그란 Ball들을 3D 공간상에 자유롭게 배치하여 3D 상징(Symbol)을 만드는 것입니다.

왜 Symball인가?
  Ball로 만들어진 상징물(Symbol)이므로  새로운 합성어로 Symball 이란 단어를 만들어 봤습니다.


3D Symball  강아지 만들어본 예

[3D Symball  강아지 만들어본 예]


사용법:

사용법은 매우 간단하여 10분이면 독파가능한 수준입니다. 
키보드 키를 눌러서 바로바로 작동하게 하는 방법을 사용하여, 불필요한 기능별 메뉴 선택작업이 없으며,
가령 A 키는  Add 를 연상시키며, D 키는 Delete키를 연상시킬 수 있도록 키를 배정하여 기억하기 쉽게 구성하였습니다.
하지만, 화면상의 키를 마우스로 눌러도 아무 작동도 안하고, 키보드로 눌러줘야 한다는점을 잊지 말아주세요!
화면상의 아이콘 키들은  본 어플 작동을 위한 모든 기능키들을 화면에 보여줘서 곧바로 모든 키를 익힐 수 있도록 하기 위함입니다.  궁굼한 기능키에 마우스를 올려보면 기능키 mini도움말이 바로 뜹니다.
화면상의 아이콘 키들의 기능만 알면, 본 어플 작동법을 마스터 하는것입니다.

일단, 아래의 글을 읽고 작동해보신다면 더 쉽게 이해가 되실 듯 합니다.


기능키 소개

------- Ball 다루기  ----------------

사이트 접속 후, 처음 뜨는 도움말 창을 보신 후, Close 버튼을 눌러서 도움말창을 닫습니다.

이제부터는 키보드 키와 마우스를 이용하여 3D 조형을 해봅니다.

1단계. Ball추가하기   -  Add key

 A(dd) 키를 눌러보세요.   ->  Ball이 하나 생성됩니다.
 주의.  키보드상의 A키를 눌러야 A 기능이 작동됩니다. A키를 마우스로 클릭하면 A키 도움말만 뜹니다.

2단계. Ball 이동하기

 생성된 Ball을 마우스로 Drag하면 이동합니다.

 이때 마우스 왼쪽 버튼대신 키보드 Space버튼을 이용할 수 도 있습니다.

 ☆ 오른손 검지손가락 휴식모드:
  본 기능은 디자인, 프로그래밍, 웹서핑, 게이밍 작업시 너무 많은 클릭으로 고생하고 있는 검지손가락을
  잠시나마 쉬게 해줄 수 있도록 특별히 개발한 기능입니다. 제가 이때쯤 손가락이 너무 아팠습니다. ㅡㅡ; )

3단계. 특정 지점에 Ball 생성하기

 Ball을 Drag중에 A 버튼을 누르면 마우스 현 위치에 Ball이 생성됩니다.
 이 기능으로 원하는 위치에 Ball들을 배치할 수 있습니다.

4단계. Ball 지우기   - Delete key

 지우려는 Ball 위에 마우스를 가져다 된 후,  D(elete) 키를 눌러줍니다.

5단계. Ball 선택하기  - Select key

 Ball을 하나 선택하려면, 원하는 Ball에 마우스를 가져간후 S(elect) Key를 눌러줍니다.
 여러번 반복하여 S 선택가능합니다.

6단계. Ball 영역 선택하기  

 여러개의 Ball을 한번에 선택하려면,  마우스로 해당영역을 Drag 해줍니다.

7단계. 다중 선택된 Ball들의 이동

 다중 선택된 Ball중의 하나를 선택후 드레그하면 전체 이동됩니다.

8단계. 다중 선택된 Ball들의 삭제

 D(elete) Key를 눌러주면 선택된 Ball들이 일괄적으로 삭제됩니다.

9단계. Ball의 복사 Copy

C(opy) key;  특정 Ball(들)이 선택된 상태에서 C키를 눌러주면 선택된 Ball들이 현재 위치에 복제됩니다.
                   선택된 Ball들을 Drag or 3D 회전 하면서 Copy를 수행하면, 손쉽게 특정 모양들을 복제해 낼 수 있습니다.
                   가령 직선을 회전하면서 copy를 반복하면 원이 됩니다.  2축회전을 하면서 복사를 하면 구가 됩니다.


---------  3D 이동 기능  X,Y,Z 평명이동 --------------

X-Y평면 드레그 모드

 X key를 눌러주면  선택된 Ball(들)을 Drag시 x,y 평면상 이동이 됩니다.  (기본상태)
 일반적인, 마우스 좌/우, 상/하 이동이 됩니다.

Z-X평명 드레그 모드

 Z key를 눌러주면 선택된 Ball(들)을 Drag시 z,x 평면상 이동이 됩니다.
 즉, 위아래 이동시 모니터 뒷쪽, 앞쪽으로 이동 (멀고,가까워지는 이동)
 일반모드로 되돌아 가려면 X key를 눌러줘야합니다.


----------  3D View 보기 및 선택 Ball 회전하기   ------------------
3D View 모드
선택된 Ball이 없는경우, 전체 Ball이 해당되고,
선택된 Ball이 있다면 선택된 Ball만 회전되게 됩니다.

V(iew) 키를 눌러주면 Z축과 Y축 회전용 핸들이 보입니다.
용도1. 작품 감상: 이 두 핸들을 조절하여 Z/Y축 회전 속도를 부여하면,  3D공간상의 회전하는 조형물을 볼 수 있습니다.
용도2. 조형 작업: 특정 Ball들만 선택하여 회전하여 3D 배치 작업에 이용합니다.
          힌트.  회전중에도 S, F, C, D키 사용이 가능합니다. 이를 통해 복잡한 3D 조형물도 손쉽게 만들 수 있습니다.

--- 저장하기 ---
PgUp key를 누르면 뜨는 폼에 제목을 적어줍니다. 
중요, 저장하려는 Ball 들은 선택된 상태여야합니다.  미선택된 Ball들은 저장되지 않습니다.

--- 불러오기 ---
PgDown key
검색어를 입력하여 찾기 기능을 지원하며, 목록에서 선택후 불러오기 하면, 저장되었던 Symball을 볼 수 있습니다.
참고로, 상단의 Sample download는 원 data가 손실되어 작동하지 않는상태입니다.

--- Ball 크기와 색상 변경 ----

F(unction) key를 누르면  마우스 스크롤 모드가 토글 되며 변경됩니다.
 모드1. Ball Size 조절 모드
 모드2. Ball 색상 조절 모드

모드에 따라 선택된 Ball(들)에 마우스 올린 후 스크롤을 해보면  크기 or 색상이 변화됩니다.


--- 기능키 숨기기 모드 ---

H(idden)키를 눌러주면, 안내키들을 숨기기/보이기 를 반복. 이미 기능키들을 충분히 익힌 후에 사용하면 좋은 기능

--- 도움말 ----

mini 도움말: 화면에 있는 기능안내키 A, S, D, F 등에 마우스를 올려놓으면 각 키들의 도움말이 화면 하단에 뜹니다.

자세한 도움말:  Q(uestion) Key를 눌러주면 도움말 창이 뜹니다.
                     본 도움말 모드에서 화면상에 떠 도는 키를 클릭해주면,  각 기능키별 상세한 도움말이 보입니다.


-- 안내. 2014년 8월 현재 --
  무료로 서버 호스팅을 지원하던 paran.com 서비스가 종료되어  제가 올렸던 서비스도 종료되게 되었습니다.  차후 재등록 되면 링크를 올리도록 하겠습니다!!





따뜻한 봄 날,  3D관련 전시회에 갔다가 신기한 녀석을 봐 버렸습니다.
빔프로젝터에 카메라가 달려있는 녀석이었는데,  이게 3D 스캐너라는 겁니다.
보자마자 원리가 보이더군요... 하지만 이게 정말 된단 말이야???


[사진1. 코엑스 3D영상기기 전시회에서 본 빔프로젝터 이용한 3D 스캐너 ]

예전부터 3D스캐너를 만들고 싶다는 생각은 했지만,  고가의 레이져 장비가 있어야 된다는 생각에 포기했었는데요,
뒤통수 맞은 기분이었습니다.  아니, 생각의 덫이 하나 떨어져 나가서 홀가분해졌다고 해야할까요!!

어쨌든, 중요한건,,,,  오홋! 그럼 나도 만들 수 있겠다.

그래서 일단 만들어봤습니다.
준비물은 매우 간단한 편입니다.

하드웨어: 일반 USB웹캠 1대(2대면 더 좋음),  빔프로젝터 1대,  고정용 스탠드.
개발환경: 제 경우 플래시 액션스크립트 3.0으로 직접 구현하는 것을 목표로 하였습니다.
              ( 보통은 C/C++, MATLAB,  기타 Tool을 이용하더군요,  관련링크 참조)



[사진2. 자작 3D 스캐너 - 웹캠 1대와 빔프로젝터 1대로 구성]

참고사항. 함께 설치된 Wiimote 2개는 IR Tracking용으로 일반적인 3D 스캐닝 용도로는 없어도 됩니다.



[동영상1. 스캐닝 후 공간분할이 잘 되었는지 확인하는 영상입니다. ]





[동영상2. 스캔 결과 Data(3D Points Cloud)를 별도의 MeshLab 뷰어로 확인해 봤습니다. ]

수만개의 단색 점을 3D 공간에 표시하기만 해도 대략적 형상이 나오는것을 확인 할 수 있습니다.



[동영상3. 몇가지 스캔 결과물을 모아놓은 영상입니다. ]

1. 종전의 영상은단색 점인것과 달리 본 영상의 점은 색상있는 점입니다.
2. 수만개의 점중에 일부 점만 무작위 추출하여 매핑을 한 영상입니다.
3. 위 결과를 라운드 처리하여 본 결과입니다.
4. 벽면의 붙인 그림을 스캔할 결과물입니다. 평면의 물체가 굴곡면으로 스캔된 것을 볼 수 있습니다.
    렌즈굴곡 보정을 안해줘서 그런것 같습니다.


사실 아직 완성된건 아니고, 렌즈굴곡보정, 노이즈처리, Point Cloud로 Polygon 형성, 3D Viewer 등등의 작업이 남아있습니다. 차후에 좀더 개량을 해야하겠습니다.  가능하면 관련 이론 소개를 별도의 문서로 올려보도록 하겠습니다. 새로운 참고자료도 본 글을 통해 업데이트 하도록 하겠습니다.


추가사항(2010.Nov.15)

스캔원리에대해 요약 소개:

링크 자료중 byo3d pdf 문서를 보시면  chapter5  structured lighting 이라는 개념이 있습니다.
사실 이게 빔프로젝터로 3D스캐너를 만드는데 있어서 핵심내용입니다.
카메라와  빔프로젝트가 거리 L만큼 떨어져있고,  빔에서 선이 하나 발사되어 벽에 반사되어 카메라로 캡쳐되는 상황을 가정해보시면 카메라와 프로젝터의 상대각을 구할 수 있고, 간단한 삼각함수만으로 그 점의 3차원 x,y,z 좌표값(카메라+빔프로젝터를 기준으로한 상대적인)을 구하실 수 있을겁니다.  

사실 이것만으로도 3d스캐닝이 가능합니다. 빔프로젝터에서 점을 이동하면서 카메라에서 그 위치를 캡쳐하게되면, (매우 느리겠지만) 원하는 point cloud를 구할 수 있습니다. 근데 문제는 너무 느려서 비효율적입니다. 점하나당 한번의 캡쳐를 해야한다는 결론이나오므로 실용성이 없습니다.

그래서 Structed Lighiting 이라는 방식이 도입되었습니다.
이 방법을 사용하면 n번의 갭쳐만으로 2^n * row  개의 기준화소점군(라인)을 구해낼 수 있게됩니다.
즉, 8장을 캡쳐하는것 만으로도 256개의 기준선을 추출할 수 있고, 각 기준선마다 m개의 화소를 추출할 수 있게되어,  한차례( 해상도에 따라 다름: 가령 8장 안팍)의 연사촬영만으로 수만개의 화소점을 구해낼 수 있게됩니다.

원리는 빛을 동일한곳에 다른 패턴으로 방사하고 촬영한 후 이 값들을 단순히 누적하기만 하면, 거의 화소단위로 영역이 구분이 된다는 것입니다. byo3d pdf문서를 잘 살펴보시면 원리를 알게될 겁니다. 

링크6. 정보가 추가 되었습니다. 

정보를 제공해주신 분에의하면 해당 자료를 다운받아 따라해보니 스캔 결과물도 괜찮게 나온다고 하셨습니다. 1대의 웹캠과 1대의 빔프로젝터, 90도 직각으로 설계된 캘리브레이션 도구를 이용하여 3d 스캐너를 구현한 방식입니다.


추가사항(2010.DEC.10)


사진. 단계노출 및 그로부터 계산된 line으로 그룹화된 점 정보들.

최하단의 결과 이미지에서 동일한 색상 및 명함으로 이뤄진 화소점들(Line)을 구해낸것을 볼 수 있습니다. 이 결과값으로 화소점들의 3D 좌표값을 구할수 있습니다.


사진. Point Net 씨우기

계산할 점의 개수가 너무 많으므로 일부만을 선택하여 사용하기 위해서 특정 점들만 선택하는 과정입니다. 왼쪽이 Convert 이전의 상태이며, 이때 일부 점들은 수동으로 위치시킬 수 있으며(얼굴부분) 나머지는 자동으로 가장 근처에 있는 점이 선택되어 최종적인 3D 좌표값으로 변환되게 됩니다.


사진. 3D스캐닝 세트 전경



관련자료
1. 제가 아는한 자작 3D스캐너와 관련하여 가장 자세한 기술소개문이 있는 사이트입니다.
   소스와 유틸리티, 원리소개등의 모든자료가 있다네요.    http://mesh.brown.edu/byo3d/index.html
  
2. 위 사이트에서 배포하는 기술소개문 pdf 파일입니다.  http://mesh.brown.edu/byo3d/notes/byo3D.pdf
3. 3D Photography on your desk  http://www.vision.caltech.edu/bouguetj/ICCV98/
    한수 더 떠서 막대기와 조명기구만으로 만드는 3D스캐너입니다. 
4.  Model-Based Face Capture from Orthogonal Images 사진 두장으로 3D얼굴 재현하기 입니다.
     http://mesh.caltech.edu/ee148/projects/EngLanmanMayes/
5. 독일 공항에 설치된 화려한 색광을 사용하는 얼굴스캐너  http://mtcave.blogspot.com/2009/09/face-scanner-test.html

6. 켄터키 대학에서 구현한 3d 스캐너: http://www.engr.uky.edu/~lgh/soft/soft.htm 





플래시로 AR(증강현실)을 구현해 봤습니다.

3D Engine은 Sandy3D, 마커인식은 FlarToolKit  을 사용했습니다.

증강현실 개발 지원킷인 ARToolKit을 AS용으로 포팅한것이 FlarToolKit인 데요

플래시도 AS3.0 들어와서 속도도 꽤빨라지고, 거의 못하는게 없는것 같습니다.

FlarToolKit 내에 예제용 3D모델까지 포함되어있으니 여러분도 한번 시도해 보시죠~

시중에 돌고있는 Simson 종이인형을 3D모델링하고 관절 몇개 만들어 왕복운동 시켜본 것 입니다.





체험 서버 종료

무료 호스팅 서비스를 이용하던중 해당 회사 서비스가 종료되어  현재 체험이 불가합니다.  죄송합니다!!

동영상에서 보셨듯이 별다른 기능은 없고요, 그냥 목과 팔을 흔드는 심슨 3D 로봇이랍니다. 

차후 서버에 재등록하게되면 링크를 수정하도록하겠습니다.


준비물:

  1. 웹캠 : 플래시에서 인식되는 웹캠이면 됩니다.

  2. 마커(인식용 이미지가 인쇄된 종이) : 첨부파일을 다운로드 하셔서 가능한 두꺼운 종이에 인쇄하세요.


사용 방법:

접속 후 웹캠 사용 허락하기를 선택하신 후,  인쇄된 마커용지를 카메라에 비춰줍니다. 이후 마커의 위치와 방향에 맞쳐서 3D 로봇이 오버레이 되는것을 보실 수 있습니다. 조명이 중요하니 적절히 주변광을 맞춰주시면 인식이 더 잘됩니다.


어떻게 작동하는가?

웹캡으로 실시간 캡쳐한 영상에서 마커(특정 이미지 패턴이 인쇄된 종이)를 찾고, 그 위치와 방향을 계산해 냅니다. 여기까지가 FlarTooKkit(ARToolkit)이 하는 일이고요, 마커의 위치와 방향에 해당되는 영상이미지 위에 3D로 가상의 영상을 오버레이시켜서 실제화면과 가상화면을 동기화 시키게됩니다. 이때 3D 형상을 보여주는데 사용되는것이 Flash 3D 엔진입니다.  본 예에선 Flash 액션스크립트 개발환경을 이용하여 Flash Player상에서 작동되게되므로 별도의 프로그램 설치없이 웹카메라와 웹브라우져만으로 작동되는 장점이 있습니다.  다만 속도가 조금(많이?) 느립니다.  때문에 매우 빠르고 고화질을 원하는경우는 C/C++기반의 개발환경을 이용하곤 합니다. 다만 이경우엔 별도의 실행파일을 설치하여야 한다는 단점이 있습니다.


[]첨부파일: 증강현실FlarToolkit용 마커이미지(pdf파일)

flarlogo-marker.pdf


[]참고자료

FlarToolKitSandy3D  , Away3D

심슨종이로봇: http://cubeecraft.com/  직접인쇄해서 종이로봇 만들어보시면 로봇 장난감이 뚝딱~.


+ Recent posts