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

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. 拍摄想要的照片
    • (可选项)进一步处理捕获的图像
  5. 关闭拍照模式并释放资源

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<Color>用来进一步处理或者直接通过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能力
  • 全息图像不能捕获到图片或者视频中
    • 未来的更新会支持捕获全息图像
时间: 2024-08-08 22:06:59

HoloLens开发手记 - Unity之Locatable camera 使用相机的相关文章

HoloLens开发手记 - Unity development overview 使用Unity开发概述

Unity Technical Preview for HoloLens最新发行版为:Beta 24,发布于 09/07/2016 开始使用Unity开发HoloLens应用之前,确保你已经安装好了必要的工具,包括Unity HoloLens Technical Preview.Unity HoloLens Technical Preview是基于Unity 5.4 Beta版本来构建的,记得定期检查版本更新. 使用Unity是构建HoloLens全息应用最快的方式.推荐你花点时间来学习Unit

HoloLens开发手记 - Unity之摄像头篇

当你穿戴好HoloLens后,你就会处在全息应用世界的中心.当你的项目开启了"Virtual Reality Support"选项并选中了"Windows Holographic"后,Unity的摄像头组件会自动进行立体渲染,也会自动跟随你而移动或者旋转. 尽管如此,为了保证全息体验,以下选项需要你手动为所有摄像头设定: 混合现实渲染 Mixed Reality Rendering 摄像头定位 Positioning the Camera 视锥范围调整 Clip P

HoloLens开发手记 - Unity之语音输入

对于HoloLens,语音输入是三大基本输入方式之一,广泛地运用在各种交互中.HoloLens上语音输入有三种形式,分别是: 语音命令 Voice Command 听写 Diction 语法识别 Grammar Recognition 语音命令 Voice Command 对于做过Windows Phone或许Windows Store应用开发的人来说,语音命令是经常使用到的特性.开发者可以通过为应用设定关键词,和对应的行为,来为用户提供语音命令体验.当用户说出关键词时,预设的动作就会被调用.在

HoloLens开发手记 - Unity之Spatial Sounds 空间声音

本文主要讲述如何在项目中使用空间声音特性.我们主要讲述必须的插件组件和Unity声音组件和属性的设置来确保空间声音的实现. Enabling Spatial Sound in Unity 在Unity中启用空间声音 我们需要在Unity中使用声音插件来实现空间声音.这个插件(audio spatalizer plugin)被打包到了Unity,所以只需要在设置菜单中 Edit > Audio > Spatializer 启用Microsoft HRTF拓展就好.因为微软空间声音组件目前取样频率

HoloLens开发手记 - Unity之场景共享 Shared holographic experiences in Unity

佩戴HoloLens的多个用户可以使用场景共享特性来获取集合视野,并可以与固定在空间中某个位置的同一全息对象进行交互操作.这一切是通过空间锚共享(Anchor Sharing)来实现的. 为了使用共享服务,在AppxManifest文件中必须要启用SpatialPerception能力. Anchor Sharing 空间锚共享 在HoloLens扫描空间环境后,用户可以通过手动或者编程来选择建立一些空间锚.空间锚对象的信息的可以被序列化并传递给其他HoloLens设备,每一个设备都可以反序列化

HoloLens开发手记 - Unity之Persistence 场景保持

Persistence 场景保持是HoloLens全息体验的一个关键特性,当用户离开原场景中时,原场景中全息对象会保持在特定位置,当用户回到原场景时,能够准确还原原场景的全息内容.WorldAnchorStore类是实现此特性的关键API,这保证了用户能够将任何全息对象贴到任何他们想要放置的位置. How to persist holograms across sessions 如何在整个会话中保持全息对象 WorldAnchorStore能够允许你保持场景中空间锚的位置,为了能够真正保持全息对

HoloLens开发手记 - Unity之World Anchor空间锚

World Anchor空间锚提供了一种能够将物体保留在特定位置和旋转状态上的方法.这保证了全息对象的稳定性,同时提供了后续在真实世界中保持全息对象位置的能力.简单地说,你可以为全息物体来添加空间锚点,这样就能在后续步骤中将全息物体准确恢复到它原来的位置. Adding a World Anchor 添加空间锚 命名空间: UnityEngine.VR.WSA 类型: WorldAnchor Unity中添加空间锚的方式很简单,如下: WorldAnchor anchor = gameObjec

HoloLens开发手记 - Unity之Gestures手势识别

手势识别是HoloLens交互的重要输入方法之一.HoloLens提供了底层API和高层API,可以满足不同的手势定制需求.底层API能够获取手的位置和速度信息,高层API则借助手势识别器来识别预设的手势(包括,单击.双击.长按.平移等等). 手势输入 Gesture Input 本部分为高级API使用,通过输入源来识别手势.每个手势对应一个SourceKind输入源,大部分手势事件都是系统预设的事件,有些事件会提供额外的上下文信息. 只需要很少的步骤就能使用GestureRecognizer集

HoloLens开发手记 - HoloLens真机上手简评

千呼万唤始出来,终于今天拿到了HoloLens真机. 设备概览 包装盒 本体 试戴 实际效果 GalaxyExplorer试玩 全息图像贴到现实场景表面 优点 宣传视频中的核心特性均已具备,而且正如前几天发出的<HoloLens开发手记-硬件细节 Hardware Detail>一文内容,HoloLens硬件细节均一致. 硬件性能略有提升,比西雅图时试用的体验机流畅了很多 修复了频繁重启的bug,发热略有降低 场景匹配流畅,准确率高 更多细节仍待发现 缺点 虽然HoloLens开发者版本好用了