上一篇《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
上,並賦予ma
、rawimage
對象,分別對應材質上顯示圖像和UI上顯示圖像,如下圖:
結果
運行起來,在StreamingAssets
文件夾下會產生序列圖片,即為要的實時抓拍的攝像頭畫面。
參考文獻
[1] https://www.cnblogs.com/zhuhongjongy/p/7199308.html Unity 3D之調用攝像頭並存儲
[2] https://blog.csdn.net/u014361280/article/details/107374795 Unity 基礎 之 WebCamTexture 獲取設備攝像頭(包括PC和移動端),簡單渲染到 UGUI 或 游戲物體上