有时希望录一小段unity某个摄像机的画面作为演示demo,虽然OpenCV是图像处理库,但是录一小段视频还是可以实现的,具体过程如下,只需给摄像机贴上一个脚本。
大概有几个需要注意的地方:
1、Texture2D的创建是宽*高,但Mat是高*宽
2、Texture2D是RGB色彩,而需要被VedioWriter使用的是BGR的Mat对象,需要用 Imgproc.cvtColor这个方法转换
3、使用OnPostRender()进行每帧的采集,这个函数是在每帧渲染完成后调用的
4、VedioWriter最好创为fourcc('M', 'J', 'P', 'G'),并且保存为avi格式
5、录制完后一定要release掉VedioWriter,否则视频可能打不开
6、下面给出代码需要自己添加按钮并绑定其中的OnClick()方法
using UnityEngine;
using OpenCVForUnity;
using UnityEngine.UI;
public class lushipin : MonoBehaviour
{
const int maxframecount = 1000; //最大录制帧数,按实际情况修改
int framecount; //当前帧
Texture2D ScreenTexture; //截图的texture2D
Mat FrameRgbMat; //截图的Mat
VideoWriter Writer; //OpenCV的VedioWriter
bool IsRecording; //是否在录制的flag
void Start()
{
Writer = new VideoWriter(@"D:\opencvimage\2.avi", VideoWriter.fourcc('M', 'J', 'P', 'G'), 30, new OpenCVForUnity.Size(Screen.width, Screen.height));
if (!Writer.isOpened())
{
Debug.LogError("writer.isOpened() false");
Writer.release();
return;
}
FrameRgbMat = new Mat(Screen.height, Screen.width, CvType.CV_8UC3);
ScreenTexture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
framecount = 0;
IsRecording = false;
}
public void OnClick() //注意public 与按钮绑定的方法,用于开始或停止录制
{
if (IsRecording == false)
{
IsRecording = true;
Debug.Log("开始录制");
}
else
{
IsRecording = false;
Debug.Log("录制结束");
if (Writer != null)
Writer.release();
}
}
void OnPostRender() //每渲染完一帧后
{
if (IsRecording)
{
if (framecount >= maxframecount ||FrameRgbMat.width() != Screen.width || FrameRgbMat.height() != Screen.height) //达到最大帧数
{
IsRecording = false;
Debug.Log("录制结束");
if(Writer!=null)
Writer.release();
return;
}
framecount++;
ScreenTexture.ReadPixels(new UnityEngine.Rect(0, 0, Screen.width, Screen.height), 0, 0);
ScreenTexture.Apply();
Utils.texture2DToMat(ScreenTexture, FrameRgbMat);
Imgproc.cvtColor(FrameRgbMat, FrameRgbMat, Imgproc.COLOR_RGB2BGR);
Writer.write(FrameRgbMat);
Debug.Log("已录制:" + framecount.ToString()+"帧");
}
}
void OnApplicationQuit()
{
Debug.Log("退出");
}
}
附:绑定按钮触发方法