Unity의 사진 비디오 카메라

카메라 액세스 기능 사용

앱이 카메라를 사용하려면 "WebCam" 기능을 선언해야 합니다.

  1. Unity 편집기에서 "프로젝트 설정 플레이어 편집 > " 페이지로 이동하여 플레이어 설정 > 으로 이동합니다.
  2. "Windows 스토어" 탭 선택
  3. "게시 설정 > 기능" 섹션에서 WebCam마이크 기능을 검사.

카메라로 한 번에 하나의 작업만 수행할 수 있습니다. 현재 Unity 2018 및 이전 버전 또는 UnityEngine.Windows.WebCam.Mode Unity 2019 이상에서 카메라가 있는 UnityEngine.XR.WSA.WebCam.Mode 모드를 검사 수 있습니다. 사용 가능한 모드는 사진, 비디오 또는 없음입니다.

사진 캡처

네임스페이스(Unity 2019 이전):UnityEngine.XR.WSA.WebCam
네임스페이스(Unity 2019 이상):UnityEngine.Windows.WebCam
형식:PhotoCapture

PhotoCapture 유형을 사용하면 사진 비디오 카메라로 스틸 사진을 찍을 수 있습니다. PhotoCapture를 사용하여 사진을 찍는 일반적인 패턴은 다음과 같습니다.

  1. PhotoCapture 개체 만들기
  2. 원하는 설정을 사용하여 CameraParameters 개체 만들기
  3. StartPhotoModeAsync를 통해 사진 모드 시작
  4. 원하는 사진 촬영
    • (선택 사항) 해당 그림과 상호 작용
  5. 사진 모드 중지 및 리소스 클린

PhotoCapture에 대한 일반적인 설정

세 가지 용도 모두 위의 동일한 처음 세 단계로 시작합니다.

먼저 PhotoCapture 개체를 만듭니다.

private void Start()
{
    PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}

다음으로, 개체를 저장하고, 매개 변수를 설정하고, 사진 모드를 시작합니다.

private PhotoCapture photoCaptureObject = null;

void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
    photoCaptureObject = captureObject;

    Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

    CameraParameters c = new CameraParameters();
    c.hologramOpacity = 0.0f;
    c.cameraResolutionWidth = cameraResolution.width;
    c.cameraResolutionHeight = cameraResolution.height;
    c.pixelFormat = CapturePixelFormat.BGRA32;

    captureObject.StartPhotoModeAsync(c, false, OnPhotoModeStarted);
}

결국 여기에 표시된 것과 동일한 클린 코드도 사용합니다.

void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
    photoCaptureObject.Dispose();
    photoCaptureObject = null;
}

이 단계 후에는 캡처할 사진 유형을 선택할 수 있습니다.

파일에 사진 캡처

가장 간단한 작업은 파일에 직접 사진을 캡처하는 것입니다. 사진을 JPG 또는 PNG로 저장할 수 있습니다.

사진 모드를 성공적으로 시작한 경우 사진을 찍어 디스크에 저장합니다.

private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        string filename = string.Format(@"CapturedImage{0}_n.jpg", Time.time);
        string filePath = System.IO.Path.Combine(Application.persistentDataPath, filename);

        photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
    }
    else
    {
        Debug.LogError("Unable to start photo mode!");
    }
}

사진을 디스크에 캡처한 후 사진 모드를 종료한 다음 개체를 클린.

void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        Debug.Log("Saved Photo to disk!");
        photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
    }
    else
    {
        Debug.Log("Failed to save Photo to disk");
    }
}

위치가 있는 Texture2D에 사진 캡처

Texture2D로 데이터를 캡처할 때 프로세스는 디스크에 캡처하는 것과 유사합니다.

위의 설정 프로세스를 따릅니다.

OnPhotoModeStarted에서 프레임을 메모리에 캡처합니다.

private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
    }
    else
    {
        Debug.LogError("Unable to start photo mode!");
    }
}

그런 다음 결과를 텍스처에 적용하고 위의 일반적인 클린 코드를 사용합니다.

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    if (result.success)
    {
        // Create our Texture2D for use and set the correct resolution
        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
        // Copy the raw image data into our target texture
        photoCaptureFrame.UploadImageDataToTexture(targetTexture);
        // Do as we wish with the texture such as apply it to a material, etc.
    }
    // Clean up
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

위치를 찾을 수 있는 카메라

이 텍스처를 장면에 배치하고 찾기 가능한 카메라 매트릭스를 사용하여 표시하려면 검사 OnCapturedPhotoToMemoryresult.success 다음 코드를 추가합니다.

if (photoCaptureFrame.hasLocationData)
{
    photoCaptureFrame.TryGetCameraToWorldMatrix(out Matrix4x4 cameraToWorldMatrix);

    Vector3 position = cameraToWorldMatrix.GetColumn(3) - cameraToWorldMatrix.GetColumn(2);
    Quaternion rotation = Quaternion.LookRotation(-cameraToWorldMatrix.GetColumn(2), cameraToWorldMatrix.GetColumn(1));

    photoCaptureFrame.TryGetProjectionMatrix(Camera.main.nearClipPlane, Camera.main.farClipPlane, out Matrix4x4 projectionMatrix);
}

Unity는 포럼의 특정 셰이더에 프로젝션 매트릭스를 적용하기 위한 샘플 코드를 제공했습니다.

사진을 캡처하고 원시 바이트와 상호 작용

메모리 프레임에서 의 원시 바이트와 상호 작용하려면 텍스처2D에 사진을 캡처할 때와 같이 위 및 OnPhotoModeStarted 와 동일한 설정 단계를 수행합니다. 차이점은 원시 바이트를 가져와 상호 작용할 수 있는 OnCapturedPhotoToMemory 입니다.

이 예제에서는 SetPixels()를 통해 텍스처에 추가로 처리하거나 적용할 목록을 만듭니다.

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    if (result.success)
    {
        List<byte> imageBufferList = new List<byte>();
        // Copy the raw IMFMediaBuffer data into our empty byte list.
        photoCaptureFrame.CopyRawImageDataIntoBuffer(imageBufferList);

        // In this example, we captured the image using the BGRA32 format.
        // So our stride will be 4 since we have a byte for each rgba channel.
        // The raw image data will also be flipped so we access our pixel data
        // in the reverse order.
        int stride = 4;
        float denominator = 1.0f / 255.0f;
        List<Color> colorArray = new List<Color>();
        for (int i = imageBufferList.Count - 1; i >= 0; i -= stride)
        {
            float a = (int)(imageBufferList[i - 0]) * denominator;
            float r = (int)(imageBufferList[i - 1]) * denominator;
            float g = (int)(imageBufferList[i - 2]) * denominator;
            float b = (int)(imageBufferList[i - 3]) * denominator;

            colorArray.Add(new Color(r, g, b, a));
        }
        // Now we could do something with the array such as texture.SetPixels() or run image processing on the list
    }
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

비디오 캡처

네임스페이스(Unity 2019 이전):UnityEngine.XR.WSA.WebCam
네임스페이스(Unity 2019 이상):UnityEngine.Windows.WebCam
형식:VideoCapture

VideoCapturePhotoCapture와 유사하게 작동합니다. 두 가지 차이점은 FPS(초당 프레임 수) 값을 지정해야 하며 디스크에 직접 .mp4 파일로만 저장할 수 있다는 것입니다. VideoCapture를 사용하는 단계는 다음과 같습니다.

  1. VideoCapture 개체 만들기
  2. 원하는 설정을 사용하여 CameraParameters 개체 만들기
  3. StartVideoModeAsync를 통해 비디오 모드 시작
  4. 비디오 녹화 시작
  5. 비디오 녹화 중지
  6. 비디오 모드 중지 및 리소스 클린

먼저 VideoCapture 개체 VideoCapture m_VideoCapture = null;

void Start ()
{
    VideoCapture.CreateAsync(false, OnVideoCaptureCreated);
}

다음으로, 녹음/녹화 및 시작에 사용할 매개 변수를 설정합니다.

void OnVideoCaptureCreated(VideoCapture videoCapture)
{
    if (videoCapture != null)
    {
        m_VideoCapture = videoCapture;

        Resolution cameraResolution = VideoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        float cameraFramerate = VideoCapture.GetSupportedFrameRatesForResolution(cameraResolution).OrderByDescending((fps) => fps).First();

        CameraParameters cameraParameters = new CameraParameters();
        cameraParameters.hologramOpacity = 0.0f;
        cameraParameters.frameRate = cameraFramerate;
        cameraParameters.cameraResolutionWidth = cameraResolution.width;
        cameraParameters.cameraResolutionHeight = cameraResolution.height;
        cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;

        m_VideoCapture.StartVideoModeAsync(cameraParameters,
                                            VideoCapture.AudioState.None,
                                            OnStartedVideoCaptureMode);
    }
    else
    {
        Debug.LogError("Failed to create VideoCapture Instance!");
    }
}

시작되면 녹음/녹화를 시작합니다.

void OnStartedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
    if (result.success)
    {
        string filename = string.Format("MyVideo_{0}.mp4", Time.time);
        string filepath = System.IO.Path.Combine(Application.persistentDataPath, filename);

        m_VideoCapture.StartRecordingAsync(filepath, OnStartedRecordingVideo);
    }
}

녹화가 시작된 후 중지를 사용하도록 UI 또는 동작을 업데이트할 수 있습니다. 여기서는 로그하기만 하면 됩니다.

void OnStartedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
    Debug.Log("Started Recording Video!");
    // We will stop the video from recording via other input such as a timer or a tap, etc.
}

나중에 instance 타이머 또는 사용자 입력을 사용하여 녹음/녹화를 중지하려고 합니다.

// The user has indicated to stop recording
void StopRecordingVideo()
{
    m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
}

녹화가 중지되면 비디오 모드를 중지하고 리소스를 클린.

void OnStoppedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
    Debug.Log("Stopped Recording Video!");
    m_VideoCapture.StopVideoModeAsync(OnStoppedVideoCaptureMode);
}

void OnStoppedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
    m_VideoCapture.Dispose();
    m_VideoCapture = null;
}

문제 해결

  • 해결 방법 없음
    • WebCam 기능이 프로젝트에 지정되어 있는지 확인합니다.

다음 개발 검사점

앞에서 설명한 Unity 개발 검사점 여정을 따르는 경우 Mixed Reality 플랫폼 기능 및 API를 탐색하는 중입니다. 여기에서 다음 항목으로 진행할 수 있습니다.

또는 디바이스나 에뮬레이터에서 앱 배포로 직접 이동합니다.

언제든지 Unity 개발 검사점으로 돌아갈 수 있습니다.

참고 항목