zoukankan      html  css  js  c++  java
  • HoloLens开发手记

    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能力
    • 全息图像不能捕获到图片或者视频中
      • 未来的更新会支持捕获全息图像
  • 相关阅读:
    virtual方法和abstract方法的使用(轉載)
    C# 如何寫入cookie
    Literal的一般用法,与Label对比 MSDN上的解释
    With temp as---sql语句用法 转
    GridView __DataKey 使用
    .net里radiobutton 两个怎么才能让他只选择一个
    Server.Transfer()与Response.Redirect()区别
    OnInit 事件
    ajax中Sys.WebForms.PageRequestManager的事件激发顺序
    Linux CentOS 查看某个进程打开的文件(文件描述符)
  • 原文地址:https://www.cnblogs.com/mantgh/p/5667385.html
Copyright © 2011-2022 走看看