您好,登錄后才能下訂單哦!
接到新任務,用來監控3D打印機的攝像頭,需要對其進行控制。之前我沒有做過任何這方面的工作,很是撓頭。不過有腳本和開源兩個強大的工具,我也不是很害怕。
首先有人指明需要用到的庫是OpenCV。CV是指Computer vision, 從名字就能判斷這是專注于視頻處理的庫。很快我就找到了python的調用demo.并且成功的帶動了手邊的攝像頭。http://opencv.org/安裝后,就能在sources/samples/python/demo文件夾下面找到完整的demo程序。
不過這不能解決項目問題。我們的項目要求在.net環境下開發。所以很快,我就找到了成熟的.net平臺下OpenCV解決方案,名叫EMGU;
同樣的,EMGU也完整的demo例程。在EMGU3.1版本的安裝路徑下面\Solution\VS2013-2015文件夾中,就有攝像頭的驅動例子:實現攝像頭實時采樣,只需要幾行代碼:
... private static Capture _cameraCapture; ... void run(){ try { _cameraCapture = new Capture(); } catch (Exception e) { MessageBox.Show(e.Message); return; } Application.Idle += ProcessFrame; ... void ProcessFrame(object sender, EventArgs e) { Mat frame = _cameraCapture.QueryFrame(); }
通過Applicaiton.Idle+= ProcessFrame
的加載事件,非常優雅的實現了攝像頭的驅動。
進一步,EMGU中有Websevice的例子。但是例子中傳輸的是一串字符串,采用的是net.tcp協議。我嘗試傳輸p_w_picpath,結果在旁邊電腦成功訪問了我的攝像頭,但是卡頓非常嚴重。(暫時分析不出來卡頓的原因)
host端代碼:
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.ServiceModel; using System.ServiceModel.Description; using System.Text; using Emgu.CV; namespace Webservice_Host { class Program { static void Main(string[] args) { Uri uri = new Uri("net.tcp://localhost:8082/ImageService"); NetTcpBinding binding = new NetTcpBinding(); binding.Security.Mode = SecurityMode.None; //WSHttpBinding binding = new WSHttpBinding(); binding.MaxReceivedMessageSize = 2147483647; ServiceHost host = new ServiceHost(typeof(ImageService)); ServiceBehaviorAttribute serviceBehavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>(); serviceBehavior.IncludeExceptionDetailInFaults = true; // Create endpoint host.AddServiceEndpoint(typeof(IImageService), binding, uri); host.Open(); Console.WriteLine("Service is ready, press any key to terminate."); Console.ReadKey(); host.Close(); } } }
ImageService.cs using System; using System.Collections.Generic; using System.Text; using System.ServiceModel; using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; namespace Webservice_Host { public class ImageService : IImageService { public Image<Bgr, Byte> GrabFrame() { Capture _capture = new Capture(); Mat frame=new Mat(); //_capture.Retrieve(frame,0); //Image<Bgr, Byte> img = frame.ToImage<Bgr, Byte>(); Image<Bgr, Byte> img = _capture.QueryFrame().ToImage<Bgr, Byte>(); if (_capture != null) _capture.Dispose(); return img; } } }
IImageService.cs using System; using System.Collections.Generic; using System.Text; using Emgu.CV; using Emgu.CV.Structure; using System.ServiceModel; namespace Webservice_Host { [ServiceContract] [XmlSerializerFormat] public interface IImageService { [OperationContract(IsOneWay = false)] Image<Bgr, Byte> GrabFrame(); } }
client端代碼:
//---------------------------------------------------------------------------- // Copyright (C) 2004-2016 by EMGU Corporation. All rights reserved. //---------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.ServiceModel; using System.Threading; using Emgu.CV; namespace Webservice_Client { public partial class Form1 : Form { private bool _started; private Webservice_Host.IImageService _p_w_picpathGrabber; private NetTcpBinding _binding; private static Queue<IImage> p_w_picpathQ; public Form1() { InitializeComponent(); _binding = new NetTcpBinding(); _binding.Security.Mode = SecurityMode.None; _binding.MaxReceivedMessageSize = 2147483647; Queue<IImage> p_w_picpathQ = new Queue<IImage>(); //System.Collections.Queue p_w_picpathQ= new System.Collections.Queue(); _started = false; } public bool Started { get { return _started; } set { _started = value; serviceUrlBox.Enabled = !_started; if (!_started) { //stop grabing frames //Application.Idle -= ProcessImage; // System.Timers.Timer t =new System.Timers.Timer(1); // t.Start(); // t.Elapsed+= ProcessImage; } else { //start to grab frames _p_w_picpathGrabber = new ChannelFactory<Webservice_Host.IImageService>( _binding, new EndpointAddress(serviceUrlBox.Text) ).CreateChannel(); //System.Timers.Timer t =new System.Timers.Timer(50); //t.Start(); ////button2.Click += ProcessImage; //t.Elapsed+= ProcessImage; //// Application.Idle Thread rx_p_w_picpath_thread = new Thread(new ThreadStart(get_p_w_picpath)); Thread show_p_w_picpath_thread = new Thread(new ThreadStart(show_p_w_picpath)); rx_p_w_picpath_thread.Start(); show_p_w_picpath_thread.Start(); } } } private void get_p_w_picpath() { Queue<IImage> p_w_picpathQ = new Queue<IImage>(); while (true) { p_w_picpathQ.Enqueue(_p_w_picpathGrabber.GrabFrame()); } } private void show_p_w_picpath() { while (true) { // if (p_w_picpathQ.Count>0&&p_w_picpathQ!=null) // p_w_picpathBox1.Image=p_w_picpathQ.Dequeue(); } } private void ProcessImage(object sender, EventArgs e) { p_w_picpathBox1.Image = _p_w_picpathGrabber.GrabFrame(); } private void button1_Click(object sender, EventArgs e) { Started = !Started; if (Started == true) button1.Text = "Stop"; else button1.Text = "Start"; } private void ReleaseResource() { Started = false; } private void button2_Click(object sender, EventArgs e) { } } }
IImageService
using System; using System.Collections.Generic; using System.Text; using Emgu.CV; using Emgu.CV.Structure; using System.ServiceModel; namespace Webservice_Host { [ServiceContract] [XmlSerializerFormat] public interface IImageService { [OperationContract(IsOneWay = false)] Image<Bgr, Byte> GrabFrame(); } }
到此為止,我對EMGU帶攝像頭的嘗試就結束了。后面我采用EMGU做了兩件事情,都是和網絡攝像頭有關:一是用ASP.NET用網頁控制遠程web攝像頭拍照并傳過來實時圖像。二是將EMGU截圖封裝成為dll的方法,交給其他工程師使用。
總體而言,也可能是受制于我的編程功力,無法用EMGU來實現更復雜的攝像頭訪問應用。但是EMGU作為OpenCV在.net平臺的封裝,其項目重心用在了圖像識別算法的封裝而不是多媒體應用上:我們可以看到大量的例程進行圖像識別等算法,調用起來非常方便。
而對于將攝像頭轉成流媒體源的工作,我找到了更加有效的框架,即微軟自帶的Media Foudation框架。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。