using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System.Drawing;
using System.Diagnostics;
using System.IO;
namespace ISCamRecorder {
struct FrameInfo {
public DateTime FrameTime { get; private set; }
public Mat FrameImage { get; private set; }
public FrameInfo(Mat frame) {
FrameImage = frame;
FrameTime = DateTime.Now;
}
}
internal class CvCamera {
VideoCapture camera = null; // カメラオブジェクト
bool _ExitSignal = false; // 終了シグナル
Bitmap[] _Buffer = new Bitmap[2]; // ダブルバッファ
int _WriteBufferID = 0; // 書き込みバッファ番号
FrameRateCounter _Fps = new FrameRateCounter(10); // フレームレート計測
bool _Recoding = false; // 録画中フラグ
List<FrameInfo> _RecFrames = new List<FrameInfo>(); // 録画画像
float _RecFrameRate = 0; // 録画フレームレート
/// <summary>
/// カメラ接続
/// </summary>
/// <returns></returns>
public bool Open(int id, int frameWidth, int frameHeight) {
camera = new VideoCapture(id);
if (!camera.IsOpened()) {
camera.Dispose();
camera = null;
return false;
}
camera.FrameWidth = frameWidth;
camera.FrameHeight = frameHeight;
return true;
}
/// <summary>
/// 撮影ループ
/// </summary>
public void CameraLoop() {
// 撮影ループ
while (!_ExitSignal) {
using (var frame = new Mat()) {
camera.Read(frame);
if (_Recoding) {
_RecFrames.Add(new FrameInfo(frame.Clone()));
}
_Buffer[_WriteBufferID] = BitmapConverter.ToBitmap(frame);
_WriteBufferID = 1 - _WriteBufferID; // バッファ切り替え
_Fps.Shot();
}
}
// 終了処理(メモリ解放)
if (camera != null) camera.Dispose();
}
public void SaveToFile(string outDir, string imageType, string recTime) {
if (_RecFrames.Count < 1) return;
var CamID = "CvCam";
Debug.WriteLine($"{CamID} starts saving with 0.0fps.");
// 保存先確保
var outDir2 = Path.Combine(outDir, CamID);
Directory.CreateDirectory(outDir2);
// 動画保存準備
var movieFile = Path.Combine(outDir, $"{CamID}_{recTime}.mp4");
var writer = new VideoWriter(movieFile, FourCC.H264,
_RecFrameRate, _RecFrames[0].FrameImage.Size());
for (int i = 0; i < _RecFrames.Count; i++) {
string strSampleTime = _RecFrames[i].FrameTime.ToString(@"HHmmss\.fff");
var fileName = $"{CamID}_{strSampleTime}.{imageType.ToLower()}";
var filePath = Path.Combine(outDir2, fileName);
_RecFrames[i].FrameImage.SaveImage(filePath);
writer.Write(_RecFrames[i].FrameImage);
}
writer.Release();
_RecFrames.Clear();
Debug.WriteLine($"{CamID} ends saving.");
}
/// <summary>
/// 録画開始
/// </summary>
public void StartRecoding() {
if (_RecFrames.Count > 0) _RecFrames.Clear();
_RecFrameRate = _Fps.FrameRate;
_Recoding = true;
}
/// <summary>
/// 録画中断
/// </summary>
public void StopRecoding() {
_Recoding = false;
}
/// <summary>
/// 撮影画像の取得
/// </summary>
/// <returns></returns>
public Bitmap GetImage() {
return _Buffer[1 - _WriteBufferID];
}
/// <summary>
/// 停止
/// </summary>
public void Stop() {
_ExitSignal = true;
}
/// <summary>
/// カメラ情報文字列
/// </summary>
/// <returns></returns>
public string CameraInfo() {
if (camera == null) return "接続中";
return $"{camera.FrameWidth}x{camera.FrameHeight} {_Fps.FrameRate:0.0} fps";
}
/// <summary>
/// 1秒録画に要するメモリ量
/// </summary>
/// <returns></returns>
public float MemoryFor1SecRecoding() {
if (camera == null) return 0;
int frameSize = 3 * camera.FrameWidth * camera.FrameHeight;
int bcs = 1024 * 1024;
return _Fps.FrameRate * frameSize / bcs;
}
}
}