Advertisement
Guest User

Capture.cs

a guest
Jul 28th, 2015
474
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.53 KB | None | 0 0
  1. //----------------------------------------------------------------------------
  2. //  Copyright (C) 2004-2013 by EMGU. All rights reserved.      
  3. //----------------------------------------------------------------------------
  4.  
  5. //#define TEST_CAPTURE
  6. using System;
  7. using System.ServiceModel;
  8. using System.Runtime.InteropServices;
  9. using System.Drawing;
  10. using System.Threading;
  11. #if NETFX_CORE
  12. using Windows.System.Threading;
  13. using System.Threading.Tasks;
  14. #endif
  15. using Emgu.Util;
  16. using Emgu.CV.Structure;
  17.  
  18. namespace Emgu.CV
  19. {
  20.    /// <summary>
  21.    /// Capture images from either camera or video file.
  22.    /// </summary>
  23. #if (ANDROID || IOS || NETFX_CORE)
  24. #else
  25.    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
  26. #endif
  27.    public class Capture :
  28.        UnmanagedObject,
  29. #if (ANDROID || IOS || NETFX_CORE)
  30. #else
  31.  IDuplexCapture,
  32. #endif
  33.  ICapture
  34.    {
  35.      
  36.       /// <summary>
  37.       /// the type of flipping
  38.       /// </summary>
  39.       private CvEnum.FLIP _flipType = Emgu.CV.CvEnum.FLIP.NONE;
  40.  
  41.       /// <summary>
  42.       /// The type of capture source
  43.       /// </summary>
  44.       public enum CaptureModuleType
  45.       {
  46.          /// <summary>
  47.          /// Capture from camera
  48.          /// </summary>
  49.          Camera,
  50.          /// <summary>
  51.          /// Capture from file using HighGUI
  52.          /// </summary>
  53.          Highgui,
  54.          /*
  55.          /// <summary>
  56.          /// Capture from file using FFMPEG
  57.          /// </summary>
  58.          FFMPEG,*/
  59.       }
  60.  
  61.       private CaptureModuleType _captureModuleType;
  62.  
  63.       #region Properties
  64.       /// <summary>
  65.       /// Get the type of the capture module
  66.       /// </summary>
  67.       public CaptureModuleType CaptureSource
  68.       {
  69.          get
  70.          {
  71.             return _captureModuleType;
  72.          }
  73.       }
  74.  
  75.       /// <summary>
  76.       /// Get and set the flip type
  77.       /// </summary>
  78.       public CvEnum.FLIP FlipType
  79.       {
  80.          get
  81.          {
  82.             return _flipType;
  83.          }
  84.          set
  85.          {
  86.             _flipType = value;
  87.          }
  88.       }
  89.  
  90.       /// <summary>
  91.       /// Get or Set if the captured image should be flipped horizontally
  92.       /// </summary>
  93.       public bool FlipHorizontal
  94.       {
  95.          get
  96.          {
  97.             return (_flipType & Emgu.CV.CvEnum.FLIP.HORIZONTAL) == Emgu.CV.CvEnum.FLIP.HORIZONTAL;
  98.          }
  99.          set
  100.          {
  101.             if (value != FlipHorizontal)
  102.                _flipType ^= Emgu.CV.CvEnum.FLIP.HORIZONTAL;
  103.          }
  104.       }
  105.  
  106.       /// <summary>
  107.       /// Get or Set if the captured image should be flipped vertically
  108.       /// </summary>
  109.       public bool FlipVertical
  110.       {
  111.          get
  112.          {
  113.             return (_flipType & Emgu.CV.CvEnum.FLIP.VERTICAL) == Emgu.CV.CvEnum.FLIP.VERTICAL;
  114.          }
  115.          set
  116.          {
  117.             if (value != FlipVertical)
  118.                _flipType ^= Emgu.CV.CvEnum.FLIP.VERTICAL;
  119.          }
  120.       }
  121.  
  122.       ///<summary> The width of this capture</summary>
  123.       public int Width
  124.       {
  125.          get
  126.          {
  127.             return Convert.ToInt32(GetCaptureProperty(CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH));
  128.          }
  129.       }
  130.  
  131.       ///<summary> The height of this capture </summary>
  132.       public int Height
  133.       {
  134.          get
  135.          {
  136.             return Convert.ToInt32(GetCaptureProperty(CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT));
  137.          }
  138.       }
  139.       #endregion
  140.  
  141.       #region constructors
  142.       /// <summary>
  143.       /// Create a capture using the specific camera
  144.       /// </summary>
  145.       /// <param name="captureType">The capture type</param>
  146.       public Capture(CvEnum.CaptureType captureType)
  147.          : this((int)captureType)
  148.       {
  149.       }
  150.  
  151.       ///<summary> Create a capture using the default camera </summary>
  152.       public Capture()
  153.          : this(0)
  154.       {
  155.       }
  156.  
  157.       ///<summary> Create a capture using the specific camera</summary>
  158.       ///<param name="camIndex"> The index of the camera to create capture from, starting from 0</param>
  159.       public Capture(int camIndex)
  160.       {
  161.          _captureModuleType = CaptureModuleType.Camera;
  162.  
  163. #if TEST_CAPTURE
  164. #else
  165.          _ptr = CvInvoke.cvCreateCameraCapture(camIndex);
  166.          if (_ptr == IntPtr.Zero)
  167.          {
  168.             throw new NullReferenceException(String.Format("Error: Unable to create capture from camera {0}", camIndex));
  169.          }
  170. #endif
  171.       }
  172.  
  173.       /// <summary>
  174.       /// Create a capture from file or a video stream
  175.       /// </summary>
  176.       /// <param name="fileName">The name of a file, or an url pointed to a stream.</param>
  177.       public Capture(String fileName)
  178.       {
  179.          /*
  180.          if (Util.CvToolbox.HasFFMPEG)
  181.          {
  182.             _captureModuleType = CaptureModuleType.FFMPEG;
  183.             _ptr = CvInvoke.cvCreateFileCapture_FFMPEG(fileName);
  184.          }
  185.          else*/
  186.          {
  187.             _captureModuleType = CaptureModuleType.Highgui;
  188.             _ptr = CvInvoke.cvCreateFileCapture(fileName);
  189.          }
  190.  
  191.          if (_ptr == IntPtr.Zero)
  192.             throw new NullReferenceException(String.Format("Unable to create capture from {0}", fileName));
  193.       }
  194.       #endregion
  195.  
  196.       #region implement UnmanagedObject
  197.       /// <summary>
  198.       /// Release the resource for this capture
  199.       /// </summary>
  200.       protected override void DisposeObject()
  201.       {
  202. #if TEST_CAPTURE
  203. #else
  204.          Stop();
  205.          CvInvoke.cvReleaseCapture(ref _ptr);
  206.          
  207. #endif
  208.       }
  209.       #endregion
  210.  
  211.       /// <summary>
  212.       /// Obtain the capture property
  213.       /// </summary>
  214.       /// <param name="index">The index for the property</param>
  215.       /// <returns>The value of the specific property</returns>
  216.       public double GetCaptureProperty(CvEnum.CAP_PROP index)
  217.       {
  218.          return CvInvoke.cvGetCaptureProperty(_ptr, index);
  219.       }
  220.  
  221.       /// <summary>
  222.       /// Sets the specified property of video capturing
  223.       /// </summary>
  224.       /// <param name="property">Property identifier</param>
  225.       /// <param name="value">Value of the property</param>
  226.       public void SetCaptureProperty(CvEnum.CAP_PROP property, double value)
  227.       {
  228.          CvInvoke.cvSetCaptureProperty(Ptr, property, value);
  229.       }
  230.  
  231.       /// <summary>
  232.       /// Grab a frame
  233.       /// </summary>
  234.       /// <returns>True on success</returns>
  235.       public virtual bool Grab()
  236.       {
  237.          if (_ptr == IntPtr.Zero)
  238.             return false;
  239.  
  240.          bool grabbed = CvInvoke.cvGrabFrame(_ptr);
  241.          if (grabbed && ImageGrabbed != null)
  242.             ImageGrabbed(this, new EventArgs());
  243.          return grabbed;
  244.       }
  245.  
  246.       #region Grab process
  247.       /// <summary>
  248.       /// The event to be called when an image is grabbed
  249.       /// </summary>
  250.       public event EventHandler ImageGrabbed;
  251.  
  252.       private enum GrabState
  253.       {
  254.          Stopped,
  255.          Running,
  256.          Pause,
  257.          Stopping,
  258.       }
  259.  
  260.       private volatile GrabState _grabState = GrabState.Stopped;
  261.  
  262.       private void Run()
  263.       {
  264.          try
  265.          {
  266.             while (_grabState == GrabState.Running || _grabState == GrabState.Pause)
  267.             {
  268.                if (_grabState == GrabState.Pause)
  269.                {
  270.                   Wait(100);
  271.                }
  272.                else if (!Grab())
  273.                {
  274.                   //no more frames to grab, this is the end of the stream. We should stop.
  275.                   _grabState = GrabState.Stopping;
  276.                }
  277.             }
  278.          }
  279.          catch (Exception)
  280.          {
  281.          }
  282.          finally
  283.          {
  284.             _grabState = GrabState.Stopped;
  285.          }
  286.       }
  287.  
  288.       private static void Wait(int millisecond)
  289.       {
  290. #if NETFX_CORE
  291.          Task t = Task.Delay(millisecond);
  292.          t.Wait();
  293. #else
  294.          Thread.Sleep(millisecond);
  295. #endif    
  296.       }
  297.  
  298.       /// <summary>
  299.       /// Start the grab process in a sperate thread. Once started, use the ImageGrabbed event handler and RetrieveGrayFrame/RetrieveBgrFrame to obtain the images.
  300.       /// </summary>
  301.       public void Start()
  302.       {
  303.          if (_grabState != GrabState.Running)
  304.          {
  305.             _grabState = GrabState.Running;
  306. #if NETFX_CORE
  307.             ThreadPool.RunAsync(delegate { Run(); });
  308. #else
  309.             ThreadPool.QueueUserWorkItem(delegate { Run(); });
  310. #endif
  311.          }
  312.       }
  313.  
  314.       /// <summary>
  315.       /// Pause the grab process if it is running.
  316.       /// </summary>
  317.       public void Pause()
  318.       {
  319.          if (_grabState == GrabState.Running)
  320.             _grabState = GrabState.Pause;
  321.       }
  322.  
  323.       /// <summary>
  324.       /// Stop the grabbing thread
  325.       /// </summary>
  326.       public void Stop()
  327.       {
  328.          if ( _grabState != GrabState.Stopped)
  329.          {
  330.             if (_grabState != GrabState.Stopping)
  331.                _grabState = GrabState.Stopping;
  332.          }
  333.       }
  334.       #endregion
  335.  
  336.       /// <summary>
  337.       /// Retrieve a Gray image frame after Grab()
  338.       /// </summary>
  339.       /// <returns> A Gray image frame</returns>
  340.       public virtual Image<Gray, Byte> RetrieveGrayFrame()
  341.       {
  342.          return RetrieveGrayFrame(0);
  343.       }
  344.  
  345.       /// <summary>
  346.       /// Retrieve a Gray image frame after Grab()
  347.       /// </summary>
  348.       /// <param name="streamIndex">Stream index. Use 0 for default.</param>
  349.       /// <returns> A Gray image frame</returns>
  350.       public virtual Image<Gray, Byte> RetrieveGrayFrame(int streamIndex)
  351.       {
  352.          IntPtr img = CvInvoke.cvRetrieveFrame(Ptr, streamIndex);
  353.          if (img == IntPtr.Zero)
  354.             return null;
  355.          MIplImage iplImage = (MIplImage)Marshal.PtrToStructure(img, typeof(MIplImage));
  356.  
  357.          Image<Gray, Byte> res;
  358.          if (iplImage.nChannels == 3)
  359.          {  //if the image captured is Bgr, convert it to Grayscale
  360.             res = new Image<Gray, Byte>(iplImage.width, iplImage.height);
  361.             CvInvoke.cvCvtColor(img, res.Ptr, Emgu.CV.CvEnum.COLOR_CONVERSION.BGR2GRAY);
  362.          }
  363.          else
  364.          {
  365.             res = new Image<Gray, byte>(iplImage.width, iplImage.height, iplImage.widthStep, iplImage.imageData);
  366.          }
  367.  
  368.          //inplace flip the image if necessary
  369.          res._Flip(FlipType);
  370.  
  371.          return res;
  372.       }
  373.  
  374.       /// <summary>
  375.       /// Retrieve a Bgr image frame after Grab()
  376.       /// </summary>
  377.       /// <returns> A Bgr image frame</returns>
  378.       public virtual Image<Bgr, Byte> RetrieveBgrFrame()
  379.       {
  380.          return RetrieveBgrFrame(0);
  381.       }
  382.  
  383.       /// <summary>
  384.       /// Retrieve a Bgr image frame after Grab()
  385.       /// </summary>
  386.       /// <param name="streamIndex">Stream index</param>
  387.       /// <returns> A Bgr image frame</returns>
  388.       public virtual Image<Bgr, Byte> RetrieveBgrFrame(int streamIndex)
  389.       {
  390.          IntPtr img = CvInvoke.cvRetrieveFrame(Ptr, streamIndex);
  391.          if (img == IntPtr.Zero)
  392.             return null;
  393.  
  394.          MIplImage iplImage = (MIplImage)Marshal.PtrToStructure(img, typeof(MIplImage));
  395.  
  396.          Image<Bgr, Byte> res;
  397.          if (iplImage.nChannels == 1)
  398.          {  //if the image captured is Grayscale, convert it to BGR
  399.             res = new Image<Bgr, Byte>(iplImage.width, iplImage.height);
  400.             CvInvoke.cvCvtColor(img, res.Ptr, Emgu.CV.CvEnum.COLOR_CONVERSION.GRAY2BGR);
  401.          }
  402.          else
  403.          {
  404.             res = new Image<Bgr, byte>(iplImage.width, iplImage.height, iplImage.widthStep, iplImage.imageData);
  405.          }
  406.  
  407.          //inplace flip the image if necessary
  408.          res._Flip(FlipType);
  409.  
  410.          return res;
  411.       }
  412.  
  413.       /// <summary>
  414.       /// Capture a Gray image frame
  415.       /// </summary>
  416.       /// <returns> A Gray image frame</returns>
  417.       public virtual Image<Gray, Byte> QueryGrayFrame()
  418.       {
  419.          return Grab() ? RetrieveGrayFrame(0) : null;
  420.       }
  421.  
  422.       #region implement ICapture
  423.       /// <summary>
  424.       /// Capture a Bgr image frame
  425.       /// </summary>
  426.       /// <returns> A Bgr image frame</returns>
  427.       public virtual Image<Bgr, Byte> QueryFrame()
  428.       {
  429.          return Grab() ? RetrieveBgrFrame(0) : null;
  430.       }
  431.  
  432.       ///<summary>
  433.       /// Capture a Bgr image frame that is half width and half height.
  434.       /// Mainly used by WCF when sending image to remote locations in a bandwidth conservative scenario
  435.       ///</summary>
  436.       ///<remarks>Internally, this is a cvQueryFrame operation follow by a cvPyrDown</remarks>
  437.       ///<returns> A Bgr image frame that is half width and half height</returns>
  438.       public virtual Image<Bgr, Byte> QuerySmallFrame()
  439.       {
  440.          using (Image<Bgr, Byte> frame = QueryFrame())
  441.             return frame == null ? null : frame.PyrDown();
  442.       }
  443.       #endregion
  444.  
  445.       /*
  446.         ///<summary> Capture Bgr image frame with timestamp</summary>
  447.         ///<returns> A timestamped Bgr image frame</returns>
  448.         public TimedImage<Bgr, Byte> QueryTimedFrame()
  449.         {
  450.             IntPtr img = CvInvoke.cvQueryFrame(_ptr);
  451.             TimedImage<Bgr, Byte> res = new TimedImage<Bgr, Byte>(Width, Height);
  452.  
  453.             res.Timestamp = System.DateTime.Now;
  454.  
  455.             if (FlipType == Emgu.CV.CvEnum.FLIP.NONE)
  456.             {
  457.                 CvInvoke.cvCopy(img, res.Ptr, IntPtr.Zero);
  458.                 return res;
  459.             }
  460.             else
  461.             {
  462.                 //code = 0 indicates vertical flip only
  463.                 int code = 0;
  464.                 //code = -1 indicates vertical and horizontal flip
  465.                 if (FlipType == (Emgu.CV.CvEnum.FLIP.HORIZONTAL | Emgu.CV.CvEnum.FLIP.VERTICAL)) code = -1;
  466.                 //code = 1 indicates horizontal flip only
  467.                 else if (FlipType == Emgu.CV.CvEnum.FLIP.HORIZONTAL) code = 1;
  468.                 CvInvoke.cvFlip(img, res.Ptr, code);
  469.                 return res;
  470.             }
  471.         }*/
  472.  
  473. #if (ANDROID || IOS || NETFX_CORE)
  474. #else
  475.       /// <summary>
  476.       /// Query a frame duplexly over WCF
  477.       /// </summary>
  478.       public virtual void DuplexQueryFrame()
  479.       {
  480.          IDuplexCaptureCallback callback = OperationContext.Current.GetCallbackChannel<IDuplexCaptureCallback>();
  481.  
  482.          Image<Bgr, Byte> img = QueryFrame();
  483.          callback.ReceiveFrame(img);
  484.       }
  485.  
  486.       /// <summary>
  487.       /// Query a small frame duplexly over WCF
  488.       /// </summary>
  489.       public virtual void DuplexQuerySmallFrame()
  490.       {
  491.          IDuplexCaptureCallback callback = OperationContext.Current.GetCallbackChannel<IDuplexCaptureCallback>();
  492.  
  493.          Image<Bgr, Byte> img = QuerySmallFrame();
  494.          callback.ReceiveFrame(img);
  495.       }
  496. #endif
  497.    }
  498. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement