zoukankan      html  css  js  c++  java
  • 基于Unity调取摄像头方式的定时抓拍保存图像方法小结

    上一篇《Maxmspjitter实现实时抓取摄像头画面并制成序列图 (定时抓拍)》已讲到了定时抓拍的相关问题解决方案,这一篇继续,采用不同的方法,不同的平台----基于Unity。
    目标明确:相隔一定时间抓拍一张实时图片。

    开始

    参考了thissky博主的文章【Unity 3D之调用摄像头并存储】,设立了一个协程执行的函数,如下:

    IEnumerator OpenCamera()
     {
                //等待用户允许访问
                yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
                //如果用户允许访问,开始获取图像        
                if (Application.HasUserAuthorization(UserAuthorization.WebCam))
                {
                    //先获取设备
                    WebCamDevice[] device = WebCamTexture.devices;
    
                    string deviceName = device[0].name;
                    //然后获取图像
                    tex = new WebCamTexture(deviceName,1920,1080,30); //采集1920*1080分辨率、30帧速率的相机
                    //将获取的图像赋值
                    ma.material.mainTexture = tex;
                    rawImage.texture = tex;
                    //开始实施获取
                    tex.Play();
    
                }
     }
    

    然后在游戏刚开始时开启这个协程任务:

    StartCoroutine(OpenCamera()); //开启一个协程任务
    

    这样得到的结果是在Unity场景中可实时获得摄像头画面。

    接下来

    接下来的任务是要构建保存静帧的方法,如下:

    public class CameraTextureSave : MonoBehaviour
    {
            public static void Save(WebCamTexture t,int frame)
            {
                Texture2D t2d = new Texture2D(t.width, t.height, TextureFormat.ARGB32, true);
                //将WebCamTexture 的像素保存到texture2D中
                t2d.SetPixels(t.GetPixels());
                //t2d.ReadPixels(new Rect(200,200,200,200),0,0,false);
                t2d.Apply();
                //编码
                byte[] imageTytes = t2d.EncodeToJPG();
    
                //存储
                //File.WriteAllBytes(Application.streamingAssetsPath + "/my1/" + Time.time + ".jpg", imageTytes);
                string str =  string.Format("{0:D6}", frame);
                File.WriteAllBytes(Application.streamingAssetsPath + "/my1/" + "image_" + str + ".jpg", imageTytes);
                
            }
    }
    

    最后

    相隔时间调用截图函数,这里就以最基本的基于游戏时间累计的方法来创建计时器,触发相应操作,参考如下:

    timer -= Time.deltaTime;
    if (timer <= 0)
    {
        TakePhoto();
        timer = 2.0f; //相隔两秒触发一次
    }
    
    //抓拍序列图片方法
    private void TakePhoto()
    {
        CameraTextureSave.Save(tex,framecount);
        framecount++;
        print("- saved - ");
    }
    

    完整的代码:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class CameraTest : MonoBehaviour {
        
            //摄像头图像类,继承自texture
            WebCamTexture tex;
            public Image WebCam;
            public RawImage rawImage;
            public MeshRenderer ma;
    
            public float timer = 2.0f; // 定时2秒
            public int framecount = 0; //序列计数
        	void Start()
            {
                //开启协程,获取摄像头图像数据
                StartCoroutine(OpenCamera());
            }
    
            // Update is called once per frame
            void Update()
            {
                timer -= Time.deltaTime;
                if (timer <= 0)
                {
                    TakePhoto();
                    timer = 2.0f;
                }
            }
    
        private void TakePhoto()
        {
            CameraTextureSave.Save(tex,framecount);
            framecount++;
            print("- saved - ");
        }
    
        IEnumerator OpenCamera()
            {
                //等待用户允许访问
                yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
                //如果用户允许访问,开始获取图像        
                if (Application.HasUserAuthorization(UserAuthorization.WebCam))
                {
                    //先获取设备
                    WebCamDevice[] device = WebCamTexture.devices;
    
                    string deviceName = device[0].name;
                    //然后获取图像
                    tex = new WebCamTexture(deviceName,1920,1080,30);
                    //将获取的图像赋值
                    ma.material.mainTexture = tex;
                    rawImage.texture = tex;
                    //开始实施获取
                    tex.Play();
    
                }
            }
    
        public class CameraTextureSave : MonoBehaviour
        {
    
            public static void Save(WebCamTexture t,int frame)
            {
                Texture2D t2d = new Texture2D(t.width, t.height, TextureFormat.ARGB32, true);
                //将WebCamTexture 的像素保存到texture2D中
                t2d.SetPixels(t.GetPixels());
                //t2d.ReadPixels(new Rect(200,200,200,200),0,0,false);
                t2d.Apply();
                //编码
                byte[] imageTytes = t2d.EncodeToJPG();
    
                //存储
                //File.WriteAllBytes(Application.streamingAssetsPath + "/my1/" + Time.time + ".jpg", imageTytes);
                string str =  string.Format("{0:D6}", frame); //定义序列图片命名,如 image_#####.jpg   000001    000002
                File.WriteAllBytes(Application.streamingAssetsPath + "/my1/" + "image_" + str + ".jpg", imageTytes);
                
            }
        }
    
    }
    		
    

    Unity场景中,添加一个Cube,一个RawImage,注意将CameraTest脚本绑在任何一个GameObject上,并赋予marawimage对象,分别对应材质上显示图像和UI上显示图像,如下图:
    image

    结果

    运行起来,在StreamingAssets文件夹下会产生序列图片,即为要的实时抓拍的摄像头画面。
    image



    参考文献

    [1] https://www.cnblogs.com/zhuhongjongy/p/7199308.html Unity 3D之调用摄像头并存储
    [2] https://blog.csdn.net/u014361280/article/details/107374795 Unity 基础 之 WebCamTexture 获取设备摄像头(包括PC和移动端),简单渲染到 UGUI 或 游戏物体上

  • 相关阅读:
    临时表的汇总
    数据仓库逻辑建模
    在Eclipse下搭建Android开发环境教程(1)
    SQL Server数据库锁的引入的缘由
    C#图片处理基本应用(裁剪,缩放,清晰度,水印)(转)
    Default on textbox
    引用 几种绑定DropdownList的方法
    Jquery示例
    MSSql数据库锁
    C# 常用算法
  • 原文地址:https://www.cnblogs.com/sharpeye/p/15330705.html
Copyright © 2011-2022 走看看