List
ImageTracker를 이용한 ar coloring
Posted Date: 2019-10-15 5:24     Edited Date: 2019-10-29 2:42     Writer: inactive

Please provide your development details as below;

1. SDK Version: 4.1.4
2. Development Environment: Unity-Android, Unity-iOS
3. Tracker/Scanner:ImageTracker
4. License Type(Free / Pro-One Time Fee / Pro-Subscription / Enterprise):Free
5. Target Device(Optional):

안녕하세요!

저는 맥스트를 이용해서 AR Coloring 앱을 만들고 싶습니다.(이미지마커에 색을 칠하면, 마커 위에 놓인 3D 객체에 색이 반영되는 기능 예시 : https://www.youtube.com/watch?v=3Tnk1958PmY)

현재 카메라 화면 전체를 텍스처로 다른 객체에 입히는 건 성공했습니다.

그런데 카메라 화면 전체가 아니라 카메라에서 원하는 부분만 잘라서 가져올 수 있을까요?

아니면 카메라 백그라운드에서 마커의 위치를 알 수 있는 방법이 있나요?

감사합니다.

 

Posted Date: 2019-10-16 9:25     Edited Date: 2019-10-16 9:25     Writer: inactive

안녕하세요. 
MAXST SDK에 관심을 가져주셔서 감사합니다.
꼭지점의 이미지 상 좌표를 얻는 것은 약간의 매트릭스 연산이 필요합니다. 

1. 먼저 타겟 이미지의 좌측 상단점 벡터를 구합니다. 

타겟 이미지의 벡터는 타겟의 실측 사이즈를 2로 나눈후 좌측 상단이기 때문에 음수를 취해줍니다. 
Xw = (-trackable.getWidth()/2.0, -trackable.getHeight()/2.0, 0.0, 1.0)

2. 그 후 카메라 벡터를 구합니다. 트래커블의 포즈 매트릭스를 얻어 타겟 이미지 벡터와 곱해 구할 수 있습니다. 
Xc = Trackable.getPoseMatrix * Xw

여기서 Xc는 {x,y,z,1}이라는 벡터가 나오며 Xc_로 {x,y,z}만 취해줍니다. 

3. 카메라 이미지에 대한 3x3매트릭스를 구합니다. 

K = (w 0 w/2
       0 w h/2
       0 0   1  )

위와 같이 구할 수 있으며, 여기서 w, h값은 카메라 resolution을 뜻합니다. 
TrackingState state = TrackerManager.getInstance().updateTrackingState();
TrackedImage image = state.getImage()
image.getWidth(), image.getHeight() 함수를 통해 얻을 수 있습니다. 

4. 이제 2D상에서 카메라 좌표를 얻어야 합니다. 
p = K * Xc_를 통해 {x,y,z}값을 얻은 후 z값을 1로 만들어 주기 위해 모든 항을 z로 나눠 
{x/z, y/z, z/z}로 만들어줍니다. 

그럼 최종적으로 남은 {x/z, y/z} 두 개의 값이 현재 트래킹된 이미지의 좌측 상단 값입니다. 

5. 마찬가지로 우측 하단 값을 구하려면 1번 식에서 Width, Height 항에 양수를 취하면 됩니다. 
Xw = (trackable.getWidth()/2.0, trackable.getHeight()/2.0, 0.0, 1.0)

위와 같은 매트릭스 연산을 통해 원하는 좌표와 영역을 얻어 해당 영역의 텍스처만 취하면 됩니다. 

이와 비슷한 질문이 있어, 다음 글도 참조하시면 좋을 것 같습니다. 
https://developer.maxst.com/BoardQuestions/Details/371

감사합니다.

Leo
Maxst Support Team

Posted Date: 2019-10-29 1:30     Edited Date: 2019-10-29 1:30     Writer: inactive

답변 주신대로 해보았는데 z값이 0이 나와서 x/z와 y/z값이 모두 무한대가 됩니다..

그리고 혹시 이미지가 인식되었을 때, 증강되는 객체의 좌표도 얻을 수 있을까요??

Posted Date: 2019-10-29 1:59     Edited Date: 2019-10-29 1:59     Writer: inactive

증강되는 객체의 좌표는 x/z, y/z 값으로 카메라 화면에서 이미지가 어디에 위치하느냐에 따라 다릅니다. 

카메라 화면의 정중앙에 이미지가 위치하면 제 화면의 1280x720 기준으로 {x/z, y/z} 값은 640,360으로 출력됩니다. 

화면상에 이미지 위치에 따라 좌표가 계속 변하게됩니다. 

Posted Date: 2019-10-29 2:28     Edited Date: 2019-10-29 2:29     Writer: inactive

 

 

 

 

 

위와 같이 해보았는데 left_top의 x와 y 모두 -Infinity가 됩니다.

저는 Unity를 사용중인데 혹시 무엇을 잘 못한 걸까요..?

Posted Date: 2019-10-29 2:41     Edited Date: 2019-10-29 2:42     Writer: inactive
		for (int i = 0; i < trackingResult.getCount(); i++) {
			Trackable trackable = trackingResult.getTrackable(i);

			float[] Xw = {-trackable.getWidth()/2.0f, -trackable.getHeight()/2.0f, 0.0f, 1.0f};
			//float[] Xw = {-trackable.getWidth()/2.0f, trackable.getHeight()/2.0f, 0.0f, 1.0f};
			//float[] Xw = {trackable.getWidth()/2.0f, -trackable.getHeight()/2.0f, 0.0f, 1.0f};
			//float[] Xw = {trackable.getWidth()/2.0f, trackable.getHeight()/2.0f, 0.0f, 1.0f};
			float[] Xc = new float[4];

			Matrix.multiplyMV(Xc, 0, trackable.getPoseMatrix(),0, Xw, 0);

			float[] Xc_ = new float[3];
			Xc_[0] = Xc[0];
			Xc_[1] = Xc[1];
			Xc_[2] = Xc[2];

			float[] K = {
					image.getWidth(), 0, 0,
					0, image.getWidth(), 0,
					image.getWidth()/2, image.getHeight()/2, 1
			};

			float[] p = new float[3];

			p[0] = K[0] * Xc_[0] + K[3] * Xc_[1] + K[6] * Xc_[2];
			p[1] = K[1] * Xc_[0] + K[4] * Xc_[1] + K[7] * Xc_[2];
			p[2] = K[2] * Xc_[0] + K[5] * Xc_[1] + K[8] * Xc_[2];

			p[0] = p[0]/p[2];
			p[1] = p[1]/p[2];
			p[2] = p[2]/p[2];

			Log.i(TAG, "P[0] = " + p[0] + "P[1] = " + p[1]);

저는 안드로이드 네이티브로 실행하였고, 위 소스를 참조해보시기 바랍니다.

위 소스는 안드로이드의 OnDrawFrame 함수에서 발췌했으며, 유니티의 Update 함수와 같습니다.

MAXST SDK는 Column Major이기 때문에 행렬이 Row Major이면 행과 열의 값을 바꾸어서 Column Major로 바꾸어서 실행시키기 바랍니다.

 

Leo

Maxst Support Team