您的位置:首页 > 运维架构

利用Aforge做的摄像监控程序(带视频差异录像)

2014-03-11 11:10 996 查看
作者:穆容

转自:/article/5807132.html

简介:本来想用红外线对射传感器做,苦于最近手头比较紧,就改用摄像头了。

Aforge是一套.NET开发的开源图像,视频处理库,涵盖面广的邪乎,我这里用到的部分只是冰山里的一滴水。

原理: 利用Aforge的图像差异算法,对比每帧图像和它上一帧图像的差异度,如果达到标准,计数器开始计数,当变化量达到一个值的时候,就开始录像,将接下来的每一帧写入一个AVI文件。同理,在开始录像的同时启动一个静止量的计数器。当静止指标达到限量后,停止录像。

主要代码:

public partial class Form1 : Form

{

FilterInfoCollection videoDevices;

private string device;

private float motionAlarmLevel = 0.015f;

private List<float> motionHistory = new List<float>();

MotionDetector detector = new MotionDetector(

new TwoFramesDifferenceDetector(),

new MotionAreaHighlighting());

private int flash = 0;

private bool beginREC = false;

private bool StopREC = true;

private int statCount = 0;

private int MoveCount = 0;

private const int MaxStat = 10;

private AVIWriter writer;

public Form1()

{

Control.CheckForIllegalCrossThreadCalls = false;

InitializeComponent();

#region 初始化设备列表

try

{

// enumerate video devices

videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

if (videoDevices.Count == 0)

throw new ApplicationException();

// add all devices to combo

foreach (FilterInfo device in videoDevices)

{

devicesCombo.Items.Add(device.Name);

}

devicesCombo.Items.Insert(0, "");

}

catch (ApplicationException)

{

devicesCombo.Items.Add("No local capture devices");

devicesCombo.Enabled = false;

}

devicesCombo.SelectedIndex = 0;

#endregion

}

private void devicesCombo_SelectedIndexChanged(object sender, EventArgs e)

{

device = videoDevices[devicesCombo.SelectedIndex].MonikerString;

// create video source

VideoCaptureDevice videoSource = new VideoCaptureDevice(device);

// open it

OpenVideoSource(videoSource);

}

// Open video source

private void OpenVideoSource(IVideoSource source)

{

// set busy cursor

this.Cursor = Cursors.WaitCursor;

// stop current video source

videoSourcePlayer.SignalToStop();

videoSourcePlayer.WaitForStop();

// start new video source

videoSourcePlayer.VideoSource = source;

videoSourcePlayer.Start();

//// reset statistics

//statIndex = statReady = 0;

//// start timer

//timer.Start();

this.Cursor = Cursors.Default;

}

private void videoSourcePlayer_NewFrame(object sender, ref Bitmap image)

{

if (detector != null)

{

float motionLevel = detector.ProcessFrame(image);

//if (motionLevel > motionAlarmLevel)

//{

// // flash for 2 seconds

// flash = (int)(2 * (1000 / alarmTimer.Interval));

//}

//// check objects' count

//if (detector.MotionProcessingAlgorithm is BlobCountingObjectsProcessing)

//{

// BlobCountingObjectsProcessing countingDetector = (BlobCountingObjectsProcessing)detector.MotionProcessingAlgorithm;

// objectsCountLabel.Text = "Objects: " + countingDetector.ObjectsCount.ToString();

//}

//else

//{

// objectsCountLabel.Text = "";

//}

int t1 = (int)(motionAlarmLevel * 500);

int t2 = (int)(0.075 * 500);

if (motionLevel * 500 > t1)

{

if (StopREC)

{

MoveCount++;

}

}

else

{

if (beginREC)

{

statCount++;

}

}

try

{

if (MoveCount == MaxStat)

{

if (StopREC)

{

StopREC = false;

beginREC = true;

writer = new AVIWriter("wmv3");

writer.Open(@"I:\log"+System.DateTime.Now.ToString("yyyyMMddhhmmss")+".avi", 640, 480);

this.listBox1.Items.Insert(0, "REC NOW!");

writer.AddFrame(image);

}

else

{

writer.AddFrame(image);

this.listBox1.Items.Insert(0, "RECING!");

}

}

if (statCount == MaxStat)

{

if (beginREC)

{

StopREC = true;

beginREC = false;

statCount = 0;

MoveCount = 0;

writer.Close();

this.listBox1.Items.Insert(0, "REC STOP!");

}

}

}

catch (Exception ex)

{

this.listBox1.Items.Insert(0, ex.Message);

}

if (motionLevel * 500 > t1)

{

this.listBox1.Items.Insert(0,"t1");

}

if (motionLevel * 500 > t2)

{

this.listBox1.Items.Insert(0, "t2");

}

motionHistory.Add(motionLevel);

//try

//{

// this.listBox1.Items.Insert(0, motionLevel.ToString());

//}

//catch (Exception ex)

//{

//}

if (motionHistory.Count > 300)

{

motionHistory.RemoveAt(0);

}

//if (showMotionHistoryToolStripMenuItem.Checked)

// DrawMotionHistory(image);

}

DrawMotionHistory(image);

}

private void DrawMotionHistory(Bitmap image)

{

Color greenColor = Color.FromArgb(128, 0, 255, 0);

Color yellowColor = Color.FromArgb(128, 255, 255, 0);

Color redColor = Color.FromArgb(128, 255, 0, 0);

BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),

ImageLockMode.ReadWrite, image.PixelFormat);

int t1 = (int)(motionAlarmLevel * 500);

int t2 = (int)(0.075 * 500);

for (int i = 1, n = motionHistory.Count; i <= n; i++)

{

int motionBarLength = (int)(motionHistory[n - i] * 500);

if (motionBarLength == 0)

continue;

if (motionBarLength > 50)

motionBarLength = 50;

Drawing.Line(bitmapData,

new IntPoint(image.Width - i, image.Height - 1),

new IntPoint(image.Width - i, image.Height - 1 - motionBarLength),

greenColor);

if (motionBarLength > t1)

{

Drawing.Line(bitmapData,

new IntPoint(image.Width - i, image.Height - 1 - t1),

new IntPoint(image.Width - i, image.Height - 1 - motionBarLength),

yellowColor);

}

if (motionBarLength > t2)

{

Drawing.Line(bitmapData,

new IntPoint(image.Width - i, image.Height - 1 - t2),

new IntPoint(image.Width - i, image.Height - 1 - motionBarLength),

redColor);

}

}

image.UnlockBits(bitmapData);

}

private void button2_Click(object sender, EventArgs e)

{

StopREC = true;

beginREC = false;

statCount = 0;

MoveCount = 0;

writer.Close();

this.listBox1.Items.Insert(0, "REC STOP!");

this.Close();

}

}

请注意:AForge.Video.VFW.AVIWriter的大部分功能需要使用:Win32.AVIMakeCompressedStream(out streamCompressed, stream, ref options, IntPtr.Zero);但是这个方法在某些电脑上会报错。究其原因,可能是由于缺少directshow,所以我重写了AVIWRITE的部分方法,去掉了视频压缩的部分。如下:

public void Open( string fileName, int width, int height )

{

// close previous file

Close( );

lock ( this )

{

// calculate stride

stride = width * 3;

if ( ( stride % 4 ) != 0 )

stride += ( 4 - stride % 4 );

// create new file

if ( Win32.AVIFileOpen( out file, fileName, Win32.OpenFileMode.Create | Win32.OpenFileMode.Write, IntPtr.Zero ) != 0 )

throw new ApplicationException( "Failed opening file" );

this.width = width;

this.height = height;

// describe new stream

Win32.AVISTREAMINFO info = new Win32.AVISTREAMINFO( );

info.type = Win32.mmioFOURCC( "vids" );

info.handler = Win32.mmioFOURCC( codec );

info.scale = 1;

info.rate = rate;

info.suggestedBufferSize = stride * height;

// create stream

if (Win32.AVIFileCreateStream(file, out stream, ref info) != 0)

throw new ApplicationException("Failed creating stream");

// describe compression options

Win32.AVICOMPRESSOPTIONS options = new Win32.AVICOMPRESSOPTIONS( );

options.handler = Win32.mmioFOURCC( codec );

options.quality = quality;

// uncomment if video settings dialog is required to show

// Win32.AVISaveOptions( stream, ref options );

// create compressed stream

//if (Win32.AVIMakeCompressedStream(out streamCompressed, stream, ref options, IntPtr.Zero) != 0)

// throw new ApplicationException("Failed creating compressed stream");

//Win32.AVIMakeCompressedStream(out streamCompressed, stream, ref options, IntPtr.Zero);

// describe frame format

Win32.BITMAPINFOHEADER bitmapInfoHeader = new Win32.BITMAPINFOHEADER( );

bitmapInfoHeader.size = Marshal.SizeOf( bitmapInfoHeader.GetType( ) );

bitmapInfoHeader.width = width;

bitmapInfoHeader.height = height;

bitmapInfoHeader.planes = 1;

bitmapInfoHeader.bitCount = 24;

bitmapInfoHeader.sizeImage = 0;

bitmapInfoHeader.compression = 0; // BI_RGB

// set frame format

if (Win32.AVIStreamSetFormat(stream, 0, ref bitmapInfoHeader, Marshal.SizeOf(bitmapInfoHeader.GetType())) != 0)

throw new ApplicationException("Failed creating compressed stream");

// alloc unmanaged memory for frame

buffer = Marshal.AllocHGlobal( stride * height );

if ( buffer == IntPtr.Zero )

throw new ApplicationException( "Insufficient memory for internal buffer" );

position = 0;

}

}

public void AddFrame( Bitmap frameImage )

{

lock ( this )

{

// check if AVI file was properly opened

if ( buffer == IntPtr.Zero )

throw new ApplicationException( "AVI file should be successfully opened before writing" );

// check image dimension

//if ((frameImage.Width != width) || (frameImage.Height != height))

// throw new ApplicationException("Invalid image dimension");

// lock bitmap data

BitmapData imageData = frameImage.LockBits(

new Rectangle( 0, 0, width, height ),

ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb );

// copy image data

int srcStride = imageData.Stride;

int dstStride = stride;

int src = imageData.Scan0.ToInt32( ) + srcStride * ( height - 1 );

int dst = buffer.ToInt32( );

for ( int y = 0; y < height; y++ )

{

Win32.memcpy( dst, src, dstStride );

dst += dstStride;

src -= srcStride;

}

// unlock bitmap data

frameImage.UnlockBits( imageData );

// write to stream

if (Win32.AVIStreamWrite(stream, position, 1, buffer,

stride * height, 0, IntPtr.Zero, IntPtr.Zero ) != 0 )

throw new ApplicationException( "Failed adding frame" );

position++;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: