Unity의 사진 비디오 카메라
카메라 액세스 기능 사용
앱에서 카메라를 사용하려면 "WebCam" 접근 권한 값을 선언해야 합니다.
- Unity 편집기에서 "프로젝트 설정 플레이어 편집 > " 페이지로 이동하여 플레이어 설정 > 으로 이동합니다.
- "Windows 스토어" 탭 선택
- "게시 설정 > 기능" 섹션에서 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를 사용하여 사진을 찍는 일반적인 패턴은 다음과 같습니다.
- PhotoCapture 개체 만들기
- 원하는 설정을 사용하여 CameraParameters 개체 만들기
- StartPhotoModeAsync를 통해 사진 모드 시작
- 원하는 사진 촬영
- (선택 사항) 해당 그림과 상호 작용
- 사진 모드 중지 및 리소스 정리
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);
}
위치를 찾을 수 있는 카메라
이 텍스처를 장면에 배치하고 찾기 가능한 카메라 행렬을 사용하여 표시하려면 검사에서 OnCapturedPhotoToMemory에 result.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
VideoCapture는 PhotoCapture와 유사하게 작동합니다. 단 두 가지 차이점은 FPS(초당 프레임 수) 값을 지정해야 하며 디스크에 직접 .mp4 파일로만 저장할 수 있다는 것입니다. VideoCapture를 사용하는 단계는 다음과 같습니다.
- VideoCapture 개체 만들기
- 원하는 설정을 사용하여 CameraParameters 개체 만들기
- StartVideoModeAsync를 통해 비디오 모드 시작
- 비디오 녹화 시작
- 비디오 녹화 중지
- 비디오 모드 중지 및 리소스 정리
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.
}
나중에 타이머 또는 사용자 입력을 사용하여 기록을 중지하려고 합니다.
// 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 개발 검사점으로 돌아갈 수 있습니다.