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 = ;
float denominator = 1.0f / 255.0f;
List<Color> colorArray = new List<Color>();
for (int i = imageBufferList.Count - ; i >= ; i -= stride)
{
float a = (int)(imageBufferList[i - ]) * denominator;
float r = (int)(imageBufferList[i - ]) * denominator;
float g = (int)(imageBufferList[i - ]) * denominator;
float b = (int)(imageBufferList[i - ]) * 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能力
  • 全息图像不能捕获到图片或者视频中
    • 未来的更新会支持捕获全息图像

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

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

    Unity Technical Preview for HoloLens最新发行版为:Beta 24,发布于 09/07/2016 开始使用Unity开发HoloLens应用之前,确保你已经安装好了必 ...

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

    当你穿戴好HoloLens后,你就会处在全息应用世界的中心.当你的项目开启了"Virtual Reality Support"选项并选中了"Windows Hologra ...

  3. HoloLens开发手记 - Unity之Gaze凝视射线

    凝视是HoloLens首要输入方式,形式功能类似于桌面系统的光标,用于选择操作全息对象.然而在Unity中并没有明确的Gaze API或者组件. 实现Gaze Implementing Gaze 概念 ...

  4. HoloLens开发手记 - Unity之Spatial mapping 空间映射

    本文主要讨论如何在Unity项目中集成空间映射功能.Unity内置了对空间映射功能的支持,通过以下两种方式提供给开发者: HoloToolkit项目中你可以找到空间映射组件,这可以让你便捷快速地开始使 ...

  5. HoloLens开发手记 - Unity之Tracking loss

    当HoloLens设备不能识别到自己在世界中的位置时,应用就会发生tracking loss.默认情况下,Unity会暂停Update更新循环并显示一张闪屏图片给用户.当设备重新能追踪到位置时,闪屏图 ...

  6. HoloLens开发手记 - Unity之Recommended settings 推荐设置

    Unity提供了大量的设置选项来满足全平台的配置,对于HoloLens,Unity可以通过切换一些特定的设置来启用HoloLens特定的行为. Holographic splash screen 闪屏 ...

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

    对于HoloLens,语音输入是三大基本输入方式之一,广泛地运用在各种交互中.HoloLens上语音输入有三种形式,分别是: 语音命令 Voice Command 听写 Diction 语法识别 Gr ...

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

    Persistence 场景保持是HoloLens全息体验的一个关键特性,当用户离开原场景中时,原场景中全息对象会保持在特定位置,当用户回到原场景时,能够准确还原原场景的全息内容.WorldAncho ...

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

    本文主要讲述如何在项目中使用空间声音特性.我们主要讲述必须的插件组件和Unity声音组件和属性的设置来确保空间声音的实现. Enabling Spatial Sound in Unity 在Unity ...

随机推荐

  1. 【MySQL】MySQL忘记root密码解决方案

    转眼间从实习到现在已经快两年了.两年的工作做遇到过很多很多的拦路虎,大部分也通过搜索引擎找到了解决的方案.奈何大脑不是硬盘,偶尔有的问题第二次遇到还是有点抓蒙...所以决定把这些东西记录在博客上.这样 ...

  2. 快速解决mysql Lost connection to MySQL server at 'reading initial communication packet及can't connect to mysql server on 'localhost'

    今天在使用Navicat连一个远程mysql时,总是提示连接不成功,提示Lost connection to MySQL server at 'reading initial communicatio ...

  3. JSON、使用JSON进行数据交换的基础和原理

    1. JSON 1.1. JSON 1.1.1. 什么是JSON JSON即Javascript对象表示法,是一种现在主流的数据交换格式.之所以应用广泛还是由其简单易读所决定的. 简单,只有六种类型的 ...

  4. JS高级程序设计2nd部分知识要点5

    JS Regexp 字面量模式 用\反斜杠转义 构造函数中的字符串 也用\转义正则也用\ RegExp实例属性 global -布尔值  /g ignoreCase -布尔值 /i lastIndex ...

  5. hdu 4848 Wow! Such Conquering! (floyd dfs)

    Wow! Such Conquering! Problem Description There are n Doge Planets in the Doge Space. The conqueror ...

  6. 关于点击空白关闭弹窗的js写法推荐

    $(document).mouseup(function(e){ var _con = $(' 目标区域 '); // 设置目标区域 if(!_con.is(e.target) && ...

  7. sqoop sample code

    本文使用的数据库是mysql的sample database employees. download url:https://launchpad.net/test-db/employees-db-1/ ...

  8. 如何快速开发出一个高质量的APP——创业谈

    [起] 今早,一个技术群里有人想快速做出一个app,然后询问技术方案,大概是这样, 拿到了200w投资,期望花20w两个月先做出一个app,包括iOS,Android, 先,呵呵,一下, 大概预估了一 ...

  9. UVA 10405 Longest Common Subsequence --经典DP

    最长公共子序列,经典问题.算是我的DP开场题吧. dp[i][j]表示到s1的i位置,s2的j位置为止,前面最长公共子序列的长度. 状态转移: dp[i][j] = 0                 ...

  10. Eclipse中的快捷键总结

    Eclipse中10个最有用的快捷键组合 一个Eclipse骨灰级开发者总结了他认为最有用但又不太为人所知的快捷键组合.通过这些组合可以更加容易的浏览源代码,使得整体的开发效率和质量得到提升.     ...