基於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 或 游戲物體上


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM