Unity之HoloLens开发手记Locatable camera 使用相机

Unity之HoloLens开发手记Locatable camera 使用相机

    • Enabling the capability for Photo Video Camera 启用相机能力
    • Photo Capture 捕获照片
      • Common Set Up for PhotoCapture 使用PhotoCapture的通用做法
      • Capture a Photo to a File 捕获照片到文件
      • Capture a Photo to a Texture2D 捕获文件到Texture2D对象
      • Capture a Photo and Interact with the Raw bytes 捕获照片并和原始数据交互
    • Video Capture 捕获视频
    • Troubleshooting 问题诊断
  • 原文链接

Enabling the capability for Photo Video Camera 启用相机能力

为了使用摄像头,我们必须启用WebCam能力。

  1. 在Unity中打开Player settings
  2. 展开Windows Store标签页
  3. 在"Publishing Settings > Capabilities"部分勾选WebCam能力
    同一时刻只能执行一次相机操作。为了识别当前相机处在哪种模式下(拍照还是视频),你可以通过UnityEngine.VR.WSA.WebCam.Mode API检查。

Photo Capture 捕获照片

命名空间: UnityEngine.VR.WSA.WebCam
类型: PhotoCapture
PhotoCapture类允许我们使用相机拍摄静态照片。正常的使用模式如下:

  1. 创建PhotoCapture对象
  2. 使用我们想要的设置来创建一个CameraParameters对象
  3. 调用StartPhotoModeAsync()方法开始拍照模式
  4. 拍摄想要的照片
  • (可选项)进一步处理捕获的图像
  1. 关闭拍照模式并释放资源

Common Set Up for PhotoCapture 使用PhotoCapture的通用做法

对于任何拍照方式,开始步骤都是像下面这样:
创建PhotoCapture对象

PhotoCapture photoCaptureObject = null;
void Start()
{
   PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}

存储对象,配置拍摄参数并开始拍照模式

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;
}

完成这些步骤后,你可以挑选使用哪种方式捕获照片。

Capture a Photo to a File 捕获照片到文件

最简单的做法是直接将照片捕获到文件。照片可以被存储为PNG或JPG文件。
如果我们成功开始了拍照模式,需要拍照并将照片存储到磁盘上,做法如下:

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");
   }
}

Capture a Photo to a Texture2D 捕获文件到Texture2D对象

我们可以把捕获的照片保存为Texture2D对象,做法和保存到文件类似。步骤如下:
OnPhotoModeStarted()方法中,捕获一帧图像到内存中。

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

我们需要把得到的结果赋给Texture2D对象,然后清理相机资源

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
   if (result.success)
   {
       // 使用正确分辨率创建Texture2D对象
       Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
       Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
       // 将图像数据拷贝到Texture2D对象中
       photoCaptureFrame.UploadImageDataToTexture(targetTexture);
       // 进一步使用Texture2D对象,比如赋给材质神马的
   }
   // 清理相机
   photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

Capture a Photo and Interact with the Raw bytes 捕获照片并和原始数据交互

为了在内存中操作图像原始数据,需要的步骤和捕获图片到Texture2D类似,不同之处在于,OnCapturedPhotoToMemory()方法里可以获得图像原始数据并操作它们。
在本示例中,我们会创建一个List用来进一步处理或者直接通过SetPixels()方法来应用于Texture2D对象。

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
   if (result.success)
   {
       List<byte> imageBufferList = new List<byte>();
       // 复制原始 IMFMediaBuffer 数据到空的list
       photoCaptureFrame.CopyRawImageDataIntoBuffer(imageBufferList);
       //本例使用 BGRA32 格式捕获照片.
       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));
       }
       // 接下来可以把list用做进一步的处理
   }
   photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

Video Capture 捕获视频

命名空间: UnityEngine.VR.WSA.WebCam
类型: VideoCapture
捕获视频的用法和捕获照片类似,不同的地方在于你必须指定一个帧率(FPS)并且你只能以MP4格式把视频直接存储到磁盘上。步骤如下:

  1. 创建VideoCapture对象
  2. 使用我们想要的设置来创建一个CameraParameters对象
  3. 调用StartVideoModeAsync()方法开始视频捕获模式
  4. 开始录制视频
  5. 停止录制视频
  6. 停止视频捕获模式并释放相机资源
    创建并配置VideoCapture对象
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!");
   }
}

一旦配置完成VideoCapture对象,我们就开始录制视频

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或者行为来确保可以停止视频捕获。在这里我们只输出log

void OnStartedRecordingVideo(VideoCapture.VideoCaptureResult result)
{// 我们将会通过一些方式来停止视频捕获,比如计时器或者点击手势等等
   Debug.Log("Started Recording Video!");
}

最后我们需要停止视频捕获,可以中国定时器或者其他输入方式来实现。

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;
}

Troubleshooting 问题诊断

  • 获取不到分辨率:确保你在项目中启用了WebCam能力
  • 全息图像不能捕获到图片或者视频中:未来的更新会支持捕获全息图像

原文链接

https://www.cnblogs.com/mantgh/p/5667385.html

你可能感兴趣的:(Unity之HoloLens开发手记Locatable camera 使用相机)