從正式工作以來一直做的都是基於B/S的Web開發,已經很長時間不研究C/S的東西了,但是受朋友的委托,幫他做一下拍照的這麼個小功能。其實類似的代碼網上有很多,但是真的能夠拿來運行的估計也沒幾個。本來是說周末給做的,但是這兩天腦子一直很亂,也沒靜下來,晚上了,再不做明天有點不好意思啊,只能臨時做一個了。在網上找資料自己做的過程中也發現了一些問題,於是拿到博客上來分享一下,這樣一來有需要的朋友可以直接拿來用,二來正在研究的遇到這些問題了可以迎刃而解。
剛開始接觸攝像頭視頻之類的是在大二的時候,那時候因為實驗室有一個小項目交到我手上,所以那時候對播放視頻之類的了解了一些。那時候的需求是對已經錄下來的監控錄像做處理,整個過程是已經不需要自己再去控制錄像了,所以相對簡單一點。而拍照和攝像是自己控制,所以稍微復雜那麼一點點。行了,廢話說到這裡,下面進入正題。
還是以往的作風,只實現功能,對界面不做過多的美化,有需要的朋友可以自己動手。比較這年頭自己動手,豐衣足食嘛。圖1-1是程序的主界面:
圖1-1
操作攝像頭以及實現拍照功能整個過程主要都是通過一個第三方的組件實現的,名字叫做 AForge ,是國外的組件,所以打開起來有點慢,但是要有耐心啊,目前已經更新到2.2.5版本了。如果不願意從官網上下載,文章末尾處也給出了相應的下載地址,需要的話直接拿來用就ok了。程序也很簡單,一個WinForm頁面,添加一下對Aforge的引用就可以了,但是這個過程中會引用一些其他的dll,有些不是太常用,所以在這裡對引用的dll也做了截圖(圖1-2),在自己做的過程中參照一下即可。
圖1-2
上圖1-1中間部分是用來實時顯示攝像頭開啟後獲取到的內容,是一個自定義控件。這裡得說明一下,將AForge.Controls.dll拖拽到左側的工具箱區域,然後就出來自定義控件了。這裡順便說明一下,我們平時自己開發的自定義控件也可以通過這種方式來給別人用。前台都准備好了之後我們來開始分析後台代碼。
整個的思路是先找到電腦上的攝像頭設備,然後選擇我們需要操作的設備,然後在拍照或者攝像。今天由於時間關系僅僅只是實現拍照,下次再做攝像的功能,實現之後也會一樣分享在這裡的,希望有需要的朋友關注。
當Form加載的時候,我們監聽一下其Load事件,將檢測到的攝像頭設備添加到後邊的ComboBox中供用戶選擇,關鍵代碼如下:
Private void Form1_Load(object sender, EventArgs e)
{
try
{
// 枚舉所有視頻輸入設備
videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (videoDevices.Count == 0)
throw new ApplicationException();
foreach (FilterInfo device in videoDevices)
{
tscbxCameras.Items.Add(device.Name);
}
tscbxCameras.SelectedIndex = 0;
}
catch (ApplicationException)
{
tscbxCameras.Items.Add("No local capture devices");
videoDevices = null;
}
}
當用戶選擇某一攝像頭設備再點擊連接的時候,我們打開攝像頭,並對其進行初始化,關鍵代碼:
//連接攝像頭
private void CameraConn()
{
VideoCaptureDevice videoSource = new VideoCaptureDevice(videoDevices[tscbxCameras.SelectedIndex].MonikerString);
videoSource.DesiredFrameSize = new System.Drawing.Size(320, 240);
videoSource.DesiredFrameRate = 1;
videoSourcePlayer.VideoSource = videoSource;
videoSourcePlayer.Start();
}
當用戶關閉點擊關閉攝像頭的時候,我們做關閉的處理,代碼:
//關閉攝像頭
private void btnClose_Click(object sender, EventArgs e)
{
videoSourcePlayer.SignalToStop();
videoSourcePlayer.WaitForStop();
}
當用戶點擊拍照的時候,我們獲取攝像頭當前的畫面,並保存到設定的路徑下,然後關閉當前窗口。關鍵代碼:
//拍照
private void Photograph_Click(object sender, EventArgs e)
{
try
{
if (videoSourcePlayer.IsRunning)
{
BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
videoSourcePlayer.GetCurrentVideoFrame().GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
PngBitmapEncoder pE = new PngBitmapEncoder();
pE.Frames.Add(BitmapFrame.Create(bitmapSource));
string picName = GetImagePath() + "" + "xiaosy" + ".jpg";
if (File.Exists(picName))
{
File.Delete(picName);
}
using (Stream stream = File.Create(picName))
{
pE.Save(stream);
}
//拍照完成後關攝像頭並刷新同時關窗體
if (videoSourcePlayer != null && videoSourcePlayer.IsRunning)
{
videoSourcePlayer.SignalToStop();
videoSourcePlayer.WaitForStop();
}
this.Close();
}
}
catch (Exception ex)
{
MessageBox.Show("攝像頭異常:" + ex.Message);
}
}
private string GetImagePath()
{
string personImgPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)
+ Path.DirectorySeparatorChar.ToString() + "PersonImg";
if (!Directory.Exists(personImgPath))
{
Directory.CreateDirectory(personImgPath);
}
return personImgPath;
}
關閉之後,在bin目錄下的PersonImg中即可找到保存的圖片,當然,在程序中把該圖片展示出來效果會更好,但是由於時間關系,就不添加了。需要的朋友可以自己實現,有問題的歡迎一起交流。