알쓸전컴(알아두면 쓸모있는 전자 컴퓨터)

unity arcore camera 이미지 얻기 본문

ARCore(google)

unity arcore camera 이미지 얻기

백곳 2019. 1. 24. 12:31

unity arcore camera 이미지 얻기 


arcore에서 카메라 이미지를 얻기 위해서 여러가지 코드를 테스트해본 결과 


첫번째 샘플 코드이다.  흑백 사진을 얻어 온다. 


void TaskOnClick()
{
    var image = Frame.CameraImage.AcquireCameraImageBytes();

    byte[] bufferY = new byte[image.Width * image.Height];
    byte[] bufferU = new byte[image.Width * image.Height / 2];
    byte[] bufferV = new byte[image.Width * image.Height / 2];
    System.Runtime.InteropServices.Marshal.Copy(image.Y, bufferY, 0, image.Width * image.Height);
    System.Runtime.InteropServices.Marshal.Copy(image.U, bufferU, 0, image.Width * image.Height / 2);
    System.Runtime.InteropServices.Marshal.Copy(image.V, bufferV, 0, image.Width * image.Height / 2);


    m_TextureRender = new Texture2D(image.Width, image.Height, TextureFormat.RGBA32, false, false);


    Color c = new Color();
    for (int y = 0; y < image.Height; y++) {
        for (int x =0; x<image.Width;x++) {
            float Y = bufferY[y * image.Width + x];
            float U = bufferU[(y/2) * image.Width + x];
            float V = bufferV[(y/2) * image.Width + x];
            c.r = Y;
            c.g = Y;
            c.b = Y;

            c.r /= 255.0f;
            c.g /= 255.0f;
            c.b /= 255.0f;

            if (c.r < 0.0f) c.r = 0.0f;
            if (c.g < 0.0f) c.g = 0.0f;
            if (c.b < 0.0f) c.b = 0.0f;

            if (c.r > 1.0f) c.r = 1.0f;
            if (c.g > 1.0f) c.g = 1.0f;
            if (c.b > 1.0f) c.b = 1.0f;

            c.a = 1.0f;
            m_TextureRender.SetPixel(image.Width-1-x, y, c);      
        }
    }

    var encodedJpg = m_TextureRender.EncodeToJPG();
    var path = Application.persistentDataPath;
    File.WriteAllBytes(path + "/test.jpg", encodedJpg);
}


아래 코드는 컬러 사진을 얻어 온다 



해당 펑션은 


    var image = Frame.CameraImage.AcquireCameraImageBytes(); 
을 받고 위에 처럼 사용할수 있습니다. 
private void _OnImageAvailable(int width, int height, IntPtr pixelBuffer, int bufferSize)
		{

			m_TextureRender = new Texture2D (width, height, TextureFormat.RGBA32, false, false);
			byte[] bufferYUV = new byte[width * height*3/2];
			bufferSize = width * height*3/2;
			System.Runtime.InteropServices.Marshal.Copy(pixelBuffer, bufferYUV, 0, bufferSize);
			Color color = new Color ();
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {

					float Yvalue = bufferYUV[y * width + x];
					float Uvalue = bufferYUV[(y / 2) * (width/2) + x/2 + (width * height)];
					float Vvalue = bufferYUV[(y / 2) * (width/ 2) + x / 2 + (width* height)+ (width * height)/4];
					color.r= Yvalue + (float)(1.37705 * (Vvalue-128.0f));
					color.g= Yvalue - (float)(0.698001 * (Vvalue-128.0f)) - (float)(0.337633 * (Uvalue-128.0f));
					color.b= Yvalue + (float)(1.732446 * (Uvalue-128.0f));

					color.r /= 255.0f;
					color.g /= 255.0f;
					color.b /= 255.0f;

					if (color.r < 0.0f)
						color.r = 0.0f;
					if (color.g < 0.0f)
						color.g = 0.0f;
					if (color.b < 0.0f)
						color.b = 0.0f;

					if (color.r > 1.0f)
						color.r = 1.0f;
					if (color.g > 1.0f)
						color.g = 1.0f;
					if (color.b > 1.0f)
						color.b = 1.0f;

					color.a = 1.0f;
					m_TextureRender.SetPixel (width - 1 - x, y, color);      
				}
			}

					
			m_TextureRender.Apply();
			var encodedpng = m_TextureRender.EncodeToPNG ();
			var path = Application.persistentDataPath;
			File.WriteAllBytes (path + "/YUV2RGB.png", encodedpng);
          }

다만 


arcore 에서 


TextureReader 라는 컴포넌트가 있는데 사용시 


DllNotFoundException: arcore_camera_utility 


에러를 뛰운다. 

플러그인을 모두 집어넣어도 결과는 똑같다. 

해당 문제에 대해서 스택 오버 플로우에서는 위와 같은 컬러 이미지 를 받는것을 알려주고 


아마도 TextureReader  는 스마트폰에 GPU가 있어야 문제가 안되는것 같은 느낌이 든다. 


=====================================================================================


일단 댓글에 연구실님 말대로 실제로 모바일에서는 흑백이미지가 뜨는것을 확인 했습니다. 


그래도 일단 PC에서 컬러로 뜨니 위에 소스 코드의 의도는 컬러코드 로 변환 되는 로직은 맞다고 봅니다. 


그래서 아래와 같이 디버깅하고 PC와 모바일에서 차이나는 API를 찾는게 먼저 인것 같습니다. 

 

일단 가장 의심이 되는 부분은 카메라 입력부분입니다. 


1. 일단 모바일에서 입력 부분을 디버깅 해봐야 할듯 합니다. 

    - 일단 모바일 소스 코드가 동일하게 돌아가는지 디버깅 해봐야 할것 같습니다. 

    - PC 에서 System.Runtime.InteropServices.Marshal.Copy(pixelBuffer, bufferYUV, 0, bufferSize); 하고 나온 결과값 bufferYUV

    값을 파일로 저장 합니다. 그리고 width 와 height 는 기억합니다. 

   - 모바일 소스 코드에서는 Frame.CameraImage.AcquireCameraImageBytes(); 값을 사용 하지 않고 

       PC에서 저장한 값을 파일로 읽어서 bufferYUV 을 채우고 width와 height 는 기억해둔 값을 입력 해서 

     소스 코드를 돌려 봅니다. 

   - 만약 컬러 이미지가 나온다면 현소스 코드는 모바일과 PC가 동일하게 돌아가는것이니 카메라 입력 부분의 API를 좀 더 

     확인 해봐야 될것 같습니다. 


    


'ARCore(google)' 카테고리의 다른 글

unity 스탠실 쉐이터  (0) 2019.02.12
Unity C# – Coroutine  (0) 2019.01.25
unity arcore get camera image 관련  (0) 2019.01.22
ARCore Draw 예제  (0) 2018.12.17
Java 에서 Java Script 사용하기  (0) 2018.12.14
Comments