從正式工作以來(lái)一直做的都是基于B/S的Web開(kāi)發(fā),已經(jīng)很長(zhǎng)時(shí)間不研究C/S的東西了,但是受朋友的委托,幫他做一下拍照的這么個(gè)小功能。其實(shí)類(lèi)似的代碼網(wǎng)上有很多,但是真的能夠拿來(lái)運(yùn)行的估計(jì)也沒(méi)幾個(gè)。本來(lái)是說(shuō)周末給做的,但是這兩天腦子一直很亂,也沒(méi)靜下來(lái),晚上了,再不做明天有點(diǎn)不好意思啊,只能臨時(shí)做一個(gè)了。在網(wǎng)上找資料自己做的過(guò)程中也發(fā)現(xiàn)了一些問(wèn)題,于是拿到博客上來(lái)分享一下,這樣一來(lái)有需要的朋友可以直接拿來(lái)用,二來(lái)正在研究的遇到這些問(wèn)題了可以迎刃而解。
剛開(kāi)始接觸攝像頭視頻之類(lèi)的是在大二的時(shí)候,那時(shí)候因?yàn)閷?shí)驗(yàn)室有一個(gè)小項(xiàng)目交到我手上,所以那時(shí)候?qū)Σシ乓曨l之類(lèi)的了解了一些。那時(shí)候的需求是對(duì)已經(jīng)錄下來(lái)的監(jiān)控錄像做處理,整個(gè)過(guò)程是已經(jīng)不需要自己再去控制錄像了,所以相對(duì)簡(jiǎn)單一點(diǎn)。而拍照和攝像是自己控制,所以稍微復(fù)雜那么一點(diǎn)點(diǎn)。行了,廢話(huà)說(shuō)到這里,下面進(jìn)入正題。
還是以往的作風(fēng),只實(shí)現(xiàn)功能,對(duì)界面不做過(guò)多的美化,有需要的朋友可以自己動(dòng)手。比較這年頭自己動(dòng)手,豐衣足食嘛。圖1-1是程序的主界面:
圖1-1
操作攝像頭以及實(shí)現(xiàn)拍照功能整個(gè)過(guò)程主要都是通過(guò)一個(gè)第三方的組件實(shí)現(xiàn)的,名字叫做 AForge ,是國(guó)外的組件,所以打開(kāi)起來(lái)有點(diǎn)慢,但是要有耐心啊,目前已經(jīng)更新到2.2.5版本了。如果不愿意從官網(wǎng)上下載,文章末尾處也給出了相應(yīng)的下載地址,需要的話(huà)直接拿來(lái)用就ok了。程序也很簡(jiǎn)單,一個(gè)WinForm頁(yè)面,添加一下對(duì)Aforge的引用就可以了,但是這個(gè)過(guò)程中會(huì)引用一些其他的dll,有些不是太常用,所以在這里對(duì)引用的dll也做了截圖(圖1-2),在自己做的過(guò)程中參照一下即可。
圖1-2
上圖1-1中間部分是用來(lái)實(shí)時(shí)顯示攝像頭開(kāi)啟后獲取到的內(nèi)容,是一個(gè)自定義控件。這里得說(shuō)明一下,將AForge.Controls.dll拖拽到左側(cè)的工具箱區(qū)域,然后就出來(lái)自定義控件了。這里順便說(shuō)明一下,我們平時(shí)自己開(kāi)發(fā)的自定義控件也可以通過(guò)這種方式來(lái)給別人用。前臺(tái)都準(zhǔn)備好了之后我們來(lái)開(kāi)始分析后臺(tái)代碼。
整個(gè)的思路是先找到電腦上的攝像頭設(shè)備,然后選擇我們需要操作的設(shè)備,然后在拍照或者攝像。今天由于時(shí)間關(guān)系僅僅只是實(shí)現(xiàn)拍照,下次再做攝像的功能,實(shí)現(xiàn)之后也會(huì)一樣分享在這里的,希望有需要的朋友關(guān)注。
當(dāng)Form加載的時(shí)候,我們監(jiān)聽(tīng)一下其Load事件,將檢測(cè)到的攝像頭設(shè)備添加到后邊的ComboBox中供用戶(hù)選擇,關(guān)鍵代碼如下:
Private void Form1_Load(object sender, EventArgs e)
{
try
{
// 枚舉所有視頻輸入設(shè)備
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;
}
}
當(dāng)用戶(hù)選擇某一攝像頭設(shè)備再點(diǎn)擊連接的時(shí)候,我們打開(kāi)攝像頭,并對(duì)其進(jìn)行初始化,關(guān)鍵代碼:
//連接攝像頭
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();
}
當(dāng)用戶(hù)關(guān)閉點(diǎn)擊關(guān)閉攝像頭的時(shí)候,我們做關(guān)閉的處理,代碼:
//關(guān)閉攝像頭
private void btnClose_Click(object sender, EventArgs e)
{
videoSourcePlayer.SignalToStop();
videoSourcePlayer.WaitForStop();
}
當(dāng)用戶(hù)點(diǎn)擊拍照的時(shí)候,我們獲取攝像頭當(dāng)前的畫(huà)面,并保存到設(shè)定的路徑下,然后關(guān)閉當(dāng)前窗口。關(guān)鍵代碼:
//拍照
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);
}
//拍照完成后關(guān)攝像頭并刷新同時(shí)關(guān)窗體
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;
}
關(guān)閉之后,在bin目錄下的PersonImg中即可找到保存的圖片,當(dāng)然,在程序中把該圖片展示出來(lái)效果會(huì)更好,但是由于時(shí)間關(guān)系,就不添加了。需要的朋友可以自己實(shí)現(xiàn),有問(wèn)題的歡迎一起交流。
至此,這樣一個(gè)簡(jiǎn)單的拍照功能就完成了,在這里,附上源碼下載地址。