protected bool m_triggered = true; /* Indicates that we wish to trigger single shots */

        #endregion Fields

        #region Constructors

        /* Constructor with creation of basic objects. */
        public ImageProvider()
        {
            /* Create a thread for image grabbing. */
            m_grabThread = new Thread(Grab);
            /* Create objects used for buffer handling. */
            m_lockObject = new Object();
            m_buffers = new Dictionary<PYLON_STREAMBUFFER_HANDLE, PylonBuffer<Byte>>();
            m_grabbedBuffers = new List<GrabResult>();
            /* Create handles. */
            m_hGrabber = new PYLON_STREAMGRABBER_HANDLE();
            m_hDevice = new PYLON_DEVICE_HANDLE();
            m_hRemovalCallback = new PYLON_DEVICECALLBACK_HANDLE();
            m_hConverter = new PYLON_FORMAT_CONVERTER_HANDLE();
            /* Create callback handler and attach the method. */
            m_callbackHandler = new DeviceCallbackHandler();
            m_callbackHandler.CallbackEvent += new DeviceCallbackHandler.DeviceCallback(RemovalCallbackHandler);
        }
Esempio n. 2
0
 /* Constructor with creation of basic objects. */
 public ImageProvider()
 {
     /* Create a thread for image grabbing. */
     m_grabThread = new Thread(Grab);
     /* Create objects used for buffer handling. */
     m_lockObject     = new Object();
     m_buffers        = new Dictionary <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> >();
     m_grabbedBuffers = new List <GrabResult>();
     /* Create handles. */
     m_hGrabber         = new PYLON_STREAMGRABBER_HANDLE();
     m_hDevice          = new PYLON_DEVICE_HANDLE();
     m_hRemovalCallback = new PYLON_DEVICECALLBACK_HANDLE();
     m_hConverter       = new PYLON_IMAGE_FORMAT_CONVERTER_HANDLE();
     /* Create callback handler and attach the method. */
     m_callbackHandler = new DeviceCallbackHandler();
     m_callbackHandler.CallbackEvent += new DeviceCallbackHandler.DeviceCallback(RemovalCallbackHandler);
 }
Esempio n. 3
0
        /* Open using device.*/
        public void Open(PYLON_DEVICE_HANDLE device)
        {
            try
            {
                /* Use provided device. */
                m_hDevice = device;

                /* Before using the device, it must be opened. Open it for configuring
                 * parameters and for grabbing images. */
                Pylon.DeviceOpen(m_hDevice, Pylon.cPylonAccessModeControl | Pylon.cPylonAccessModeStream);

                /* Register the callback function. */
                m_hRemovalCallback = Pylon.DeviceRegisterRemovalCallback(m_hDevice, m_callbackHandler);

                /* For GigE cameras, we recommend increasing the packet size for better
                 * performance. When the network adapter supports jumbo frames, set the packet
                 * size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size
                 * to 1500. */
                /* ... Check first to see if the GigE camera packet size parameter is supported and if it is writable. */
                if (Pylon.DeviceFeatureIsWritable(m_hDevice, "GevSCPSPacketSize"))
                {
                    /* ... The device supports the packet size feature. Set a value. */
                    Pylon.DeviceSetIntegerFeature(m_hDevice, "GevSCPSPacketSize", 1500);
                }

                /* The sample does not work in chunk mode. It must be disabled. */
                if (Pylon.DeviceFeatureIsWritable(m_hDevice, "ChunkModeActive"))
                {
                    /* Disable the chunk mode. */
                    Pylon.DeviceSetBooleanFeature(m_hDevice, "ChunkModeActive", false);
                }

                /* Disable acquisition start trigger if available. */
                if (Pylon.DeviceFeatureIsAvailable(m_hDevice, "EnumEntry_TriggerSelector_AcquisitionStart"))
                {
                    Pylon.DeviceFeatureFromString(m_hDevice, "TriggerSelector", "AcquisitionStart");
                    Pylon.DeviceFeatureFromString(m_hDevice, "TriggerMode", "Off");
                }

                /* Disable frame burst start trigger if available */
                if (Pylon.DeviceFeatureIsAvailable(m_hDevice, "EnumEntry_TriggerSelector_FrameBurstStart"))
                {
                    Pylon.DeviceFeatureFromString(m_hDevice, "TriggerSelector", "FrameBurstStart");
                    Pylon.DeviceFeatureFromString(m_hDevice, "TriggerMode", "Off");
                }

                /* Disable frame start trigger if available. */
                if (Pylon.DeviceFeatureIsAvailable(m_hDevice, "EnumEntry_TriggerSelector_FrameStart"))
                {
                    Pylon.DeviceFeatureFromString(m_hDevice, "TriggerSelector", "FrameStart");
                    Pylon.DeviceFeatureFromString(m_hDevice, "TriggerMode", "Off");
                }

                /* Image grabbing is done using a stream grabber.
                 * A device may be able to provide different streams. A separate stream grabber must
                 * be used for each stream. In this sample, we create a stream grabber for the default
                 * stream, i.e., the first stream ( index == 0 ).
                 */

                /* Get the number of streams supported by the device and the transport layer. */
                if (Pylon.DeviceGetNumStreamGrabberChannels(m_hDevice) < 1)
                {
                    throw new Exception("The transport layer doesn't support image streams.");
                }

                /* Create and open a stream grabber for the first channel. */
                m_hGrabber = Pylon.DeviceGetStreamGrabber(m_hDevice, 0);
                Pylon.StreamGrabberOpen(m_hGrabber);

                /* Get a handle for the stream grabber's wait object. The wait object
                 * allows waiting for m_buffers to be filled with grabbed data. */
                m_hWait = Pylon.StreamGrabberGetWaitObject(m_hGrabber);
            }
            catch
            {
                /* Get the last error message here, because it could be overwritten by cleaning up. */
                UpdateLastError();

                try
                {
                    Close(); /* Try to close any open handles. */
                }
                catch
                {
                    /* Another exception cannot be handled. */
                }
                throw;
            }

            /* Notify that the ImageProvider is open and ready for grabbing and configuration. */
            OnDeviceOpenedEvent();
        }
Esempio n. 4
0
        const uint GIGE_PROTOCOL_OVERHEAD = 36;   /* Total number of bytes of protocol overhead. */

        static void Main(string[] args)
        {
            PYLON_DEVICE_HANDLE[] hDev = new PYLON_DEVICE_HANDLE[NUM_DEVICES];        /* Handles for the pylon devices. */
            for (int deviceIndex = 0; deviceIndex < NUM_DEVICES; ++deviceIndex)
            {
                hDev[deviceIndex] = new PYLON_DEVICE_HANDLE();
            }
            try
            {
                uint numDevicesAvail;            /* Number of the available devices. */
                bool isAvail;                    /* Used for checking feature availability. */
                bool isReady;                    /* Used as an output parameter. */
                int  i;                          /* Counter. */
                int  deviceIndex;                /* Index of device used in the following variables. */
                PYLON_WAITOBJECTS_HANDLE wos;    /* Wait objects. */
                int nGrabs;                      /* Counts the number of grab iterations. */
                PYLON_WAITOBJECT_HANDLE woTimer; /* Timer wait object. */

                /* These are camera specific variables: */
                PYLON_STREAMGRABBER_HANDLE[] hGrabber = new PYLON_STREAMGRABBER_HANDLE[NUM_DEVICES];                                                                   /* Handle for the pylon stream grabber. */
                PYLON_WAITOBJECT_HANDLE[]    hWait    = new PYLON_WAITOBJECT_HANDLE[NUM_DEVICES];                                                                      /* Handle used for waiting for a grab to be finished. */
                uint[] payloadSize             = new uint[NUM_DEVICES];                                                                                                /* Size of an image frame in bytes. */
                PylonGrabResult_t[] grabResult = new PylonGrabResult_t[NUM_DEVICES];                                                                                   /* Stores the result of a grab operation. */
                uint[] nStreams = new uint[NUM_DEVICES];                                                                                                               /* The number of streams provided by the device. */
                Dictionary <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> >[] buffers = new Dictionary <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> > [NUM_DEVICES]; /* Holds handles and buffers used for grabbing. */

#if DEBUG
                /* This is a special debug setting needed only for GigE cameras.
                 * See 'Building Applications with pylon' in the Programmer's Guide. */
                Environment.SetEnvironmentVariable("PYLON_GIGE_HEARTBEAT", "300000" /*ms*/);
#endif

                /* Before using any pylon methods, the pylon runtime must be initialized. */
                Pylon.Initialize();

                /* Enumerate all camera devices. You must call
                 * PylonEnumerateDevices() before creating a device. */
                numDevicesAvail = Pylon.EnumerateDevices();

                if (numDevicesAvail < NUM_DEVICES)
                {
                    Console.Error.WriteLine("Found {0} devices. At least {1} devices needed to run this sample.", numDevicesAvail, NUM_DEVICES);
                    throw new Exception("Not enough devices found.");
                }

                /* Create wait objects. This must be done outside of the loop. */
                wos = Pylon.WaitObjectsCreate();

                /* In this sample, we want to grab for a given amount of time, then stop.
                 * Create a timer that tiggers an AutoResetEvent, wrap the AutoResetEvent in a pylon C.NET wait object, and add it to
                 * the wait object set. */
                AutoResetEvent       timoutEvent          = new AutoResetEvent(false);             /* The timeout event to wait for. */
                TimerCallbackWrapper timerCallbackWrapper = new TimerCallbackWrapper(timoutEvent); /* Receives the timer callback and sets the timeout event. */
                Timer timer = new Timer(timerCallbackWrapper.TimerCallback);                       /* The timeout timer. */

                woTimer = Pylon.WaitObjectFromW32(timoutEvent.SafeWaitHandle, true);

                Pylon.WaitObjectsAdd(wos, woTimer);

                /* Open cameras and set parameters. */
                for (deviceIndex = 0; deviceIndex < NUM_DEVICES; ++deviceIndex)
                {
                    /* Get handles for the devices. */
                    hDev[deviceIndex] = Pylon.CreateDeviceByIndex((uint)deviceIndex);

                    /* Before using the device, it must be opened. Open it for configuring
                     * parameters and for grabbing images. */
                    Pylon.DeviceOpen(hDev[deviceIndex], Pylon.cPylonAccessModeControl | Pylon.cPylonAccessModeStream);

                    /* Print out the name of the camera we are using. */
                    {
                        bool isReadable = Pylon.DeviceFeatureIsReadable(hDev[deviceIndex], "DeviceModelName");
                        if (isReadable)
                        {
                            string name = Pylon.DeviceFeatureToString(hDev[deviceIndex], "DeviceModelName");
                            Console.WriteLine("Using camera '{0}'", name);
                        }
                    }

                    /* Set the pixel format to Mono8, where gray values will be output as 8 bit values for each pixel. */
                    /* ... Check first to see if the device supports the Mono8 format. */
                    isAvail = Pylon.DeviceFeatureIsAvailable(hDev[deviceIndex], "EnumEntry_PixelFormat_Mono8");
                    if (!isAvail)
                    {
                        /* Feature is not available. */
                        throw new Exception("Device doesn't support the Mono8 pixel format.");
                    }

                    /* ... Set the pixel format to Mono8. */
                    Pylon.DeviceFeatureFromString(hDev[deviceIndex], "PixelFormat", "Mono8");


                    /* Disable acquisition start trigger if available */
                    isAvail = Pylon.DeviceFeatureIsAvailable(hDev[deviceIndex], "EnumEntry_TriggerSelector_AcquisitionStart");
                    if (isAvail)
                    {
                        Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerSelector", "AcquisitionStart");
                        Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerMode", "Off");
                    }

                    /* Disable frame burst start trigger if available */
                    isAvail = Pylon.DeviceFeatureIsAvailable(hDev[deviceIndex], "EnumEntry_TriggerSelector_FrameBurstStart");
                    if (isAvail)
                    {
                        Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerSelector", "FrameBurstStart");
                        Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerMode", "Off");
                    }

                    /* Disable frame start trigger if available */
                    isAvail = Pylon.DeviceFeatureIsAvailable(hDev[deviceIndex], "EnumEntry_TriggerSelector_FrameStart");
                    if (isAvail)
                    {
                        Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerSelector", "FrameStart");
                        Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerMode", "Off");
                    }

                    /* We will use the Continuous frame mode, i.e., the camera delivers
                     * images continuously. */
                    Pylon.DeviceFeatureFromString(hDev[deviceIndex], "AcquisitionMode", "Continuous");

                    PYLON_DEVICE_INFO_HANDLE hDi = Pylon.GetDeviceInfoHandle((uint)deviceIndex);
                    string deviceClass           = Pylon.DeviceInfoGetPropertyValueByName(hDi, Pylon.cPylonDeviceInfoDeviceClassKey);
                    if (deviceClass == "BaslerGigE")
                    {
                        /* For GigE cameras, we recommend increasing the packet size for better
                         * performance. When the network adapter supports jumbo frames, set the packet
                         * size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size
                         * to 1500.
                         *
                         * We also set the Inter-Packet and the Frame Transmission delay
                         * so the switch can line up packets better.
                         */

                        Pylon.DeviceSetIntegerFeature(hDev[deviceIndex], "GevSCPSPacketSize", GIGE_PACKET_SIZE);
                        Pylon.DeviceSetIntegerFeature(hDev[deviceIndex], "GevSCPD", (GIGE_PACKET_SIZE + GIGE_PROTOCOL_OVERHEAD) * (NUM_DEVICES - 1));
                        Pylon.DeviceSetIntegerFeature(hDev[deviceIndex], "GevSCFTD", (GIGE_PACKET_SIZE + GIGE_PROTOCOL_OVERHEAD) * deviceIndex);
                    }
                    else if (deviceClass == "Basler1394")
                    {
                        /* For FireWire we just set the PacketSize node to limit the bandwidth we're using. */

                        /* We first divide the available bandwidth (4915 for FW400, 9830 for FW800)
                         * by the number of devices we are using. */
                        long newPacketSize         = 4915 / NUM_DEVICES;
                        long recommendedPacketSize = 0;

                        /* Get the recommended packet size from the camera. */
                        recommendedPacketSize = Pylon.DeviceGetIntegerFeature(hDev[deviceIndex], "RecommendedPacketSize");

                        if (newPacketSize < recommendedPacketSize)
                        {
                            /* Get the increment value for the packet size.
                             * We must make sure that the new value we're setting is divisible by the increment of that feature. */
                            long packetSizeInc = 0;
                            packetSizeInc = Pylon.DeviceGetIntegerFeatureInc(hDev[deviceIndex], "PacketSize");

                            /* Adjust the new packet size so is divisible by its increment. */
                            newPacketSize -= newPacketSize % packetSizeInc;
                        }
                        else
                        {
                            /* The recommended packet size should always be valid. No need to check against the increment. */
                            newPacketSize = recommendedPacketSize;
                        }

                        /* Set the new packet size. */
                        Pylon.DeviceSetIntegerFeature(hDev[deviceIndex], "PacketSize", newPacketSize);
                        Console.WriteLine("Using packetsize: {0}", newPacketSize);
                    }
                }


                /* Allocate and register buffers for grab. */
                for (deviceIndex = 0; deviceIndex < NUM_DEVICES; ++deviceIndex)
                {
                    /* Determine the required size for the grab buffer. */
                    payloadSize[deviceIndex] = checked ((uint)Pylon.DeviceGetIntegerFeature(hDev[deviceIndex], "PayloadSize"));

                    /* Image grabbing is done using a stream grabber.
                     * A device may be able to provide different streams. A separate stream grabber must
                     * be used for each stream. In this sample, we create a stream grabber for the default
                     * stream, i.e., the first stream ( index == 0 ).
                     */

                    /* Get the number of streams supported by the device and the transport layer. */
                    nStreams[deviceIndex] = Pylon.DeviceGetNumStreamGrabberChannels(hDev[deviceIndex]);

                    if (nStreams[deviceIndex] < 1)
                    {
                        throw new Exception("The transport layer doesn't support image streams.");
                    }

                    /* Create and open a stream grabber for the first channel. */
                    hGrabber[deviceIndex] = Pylon.DeviceGetStreamGrabber(hDev[deviceIndex], 0);

                    Pylon.StreamGrabberOpen(hGrabber[deviceIndex]);


                    /* Get a handle for the stream grabber's wait object. The wait object
                     * allows waiting for buffers to be filled with grabbed data. */
                    hWait[deviceIndex] = Pylon.StreamGrabberGetWaitObject(hGrabber[deviceIndex]);

                    /* Add the stream grabber's wait object to our wait objects.
                     * This is needed to be able to wait until all cameras have
                     * grabbed an image in our grab loop below. */
                    Pylon.WaitObjectsAdd(wos, hWait[deviceIndex]);

                    /* We must tell the stream grabber the number and size of the buffers
                     *  we are using. */
                    /* .. We will not use more than NUM_BUFFERS for grabbing. */
                    Pylon.StreamGrabberSetMaxNumBuffer(hGrabber[deviceIndex], NUM_BUFFERS);

                    /* .. We will not use buffers bigger than payloadSize bytes. */
                    Pylon.StreamGrabberSetMaxBufferSize(hGrabber[deviceIndex], payloadSize[deviceIndex]);

                    /*  Allocate the resources required for grabbing. After this, critical parameters
                    *   that impact the payload size must not be changed until FinishGrab() is called. */
                    Pylon.StreamGrabberPrepareGrab(hGrabber[deviceIndex]);

                    /* Before using the buffers for grabbing, they must be registered at
                     * the stream grabber. For each registered buffer, a buffer handle
                     * is returned. After registering, these handles are used instead of the
                     * buffer objects pointers. The buffer objects are held in a dictionary,
                     * that provides access to the buffer using a handle as key.
                     */
                    buffers[deviceIndex] = new Dictionary <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> >();
                    for (i = 0; i < NUM_BUFFERS; ++i)
                    {
                        PylonBuffer <Byte>        buffer = new PylonBuffer <byte>(payloadSize[deviceIndex], true);
                        PYLON_STREAMBUFFER_HANDLE handle = Pylon.StreamGrabberRegisterBuffer(hGrabber[deviceIndex], ref buffer);
                        buffers[deviceIndex].Add(handle, buffer);
                    }

                    /* Feed the buffers into the stream grabber's input queue. For each buffer, the API
                     * allows passing in an integer as additional context information. This integer
                     * will be returned unchanged when the grab is finished. In our example, we use the index of the
                     * buffer as context information. */
                    i = 0;
                    foreach (KeyValuePair <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> > pair in buffers[deviceIndex])
                    {
                        Pylon.StreamGrabberQueueBuffer(hGrabber[deviceIndex], pair.Key, i++);
                    }
                }

                /* The stream grabber is now prepared. As soon the camera starts acquiring images,
                 * the image data will be grabbed into the provided buffers.  */
                for (deviceIndex = 0; deviceIndex < NUM_DEVICES; ++deviceIndex)
                {
                    /* Let the camera acquire images. */
                    Pylon.DeviceExecuteCommandFeature(hDev[deviceIndex], "AcquisitionStart");
                }

                /* Set the timer to 5 s and start it. */
                timer.Change(5000, Timeout.Infinite);

                /* Counts the number of grabbed images. */
                nGrabs = 0;

                /* Grab until the timer expires. */
                for (;;)
                {
                    int  bufferIndex; /* Index of the buffer. */
                    Byte min, max;
                    uint woIndex;

                    /* Wait for the next buffer to be filled. Wait up to 1000 ms. */
                    isReady = Pylon.WaitObjectsWaitForAny(wos, 1000, out woIndex);

                    if (!isReady)
                    {
                        /* Timeout occurred. */
                        throw new Exception("Grab timeout occurred.");
                    }

                    /* If the timer has expired, exit the grab loop. */
                    if (woIndex == 0)
                    {
                        Console.Error.WriteLine("Grabbing completed successfully.");
                        break;  /* Timer expired. */
                    }

                    /* Account for the timer. */
                    --woIndex;

                    /* Since the wait operation was successful, the result of at least one grab
                     * operation is available. Retrieve it. */
                    isReady = Pylon.StreamGrabberRetrieveResult(hGrabber[woIndex], out grabResult[woIndex]);

                    if (!isReady)
                    {
                        /* Oops. No grab result available? We should never have reached this point.
                         * Since the wait operation above returned without a timeout, a grab result
                         * should be available. */
                        throw new Exception("Failed to retrieve a grab result.");
                    }

                    /* Get the buffer index from the context information. */
                    bufferIndex = grabResult[woIndex].Context;

                    /* Check to see if the image was grabbed successfully. */
                    if (grabResult[woIndex].Status == EPylonGrabStatus.Grabbed)
                    {
                        /*  Success. Perform image processing. Since we passed more than one buffer
                         * to the stream grabber, the remaining buffers are filled in the background while
                         * we do the image processing. The processed buffer won't be touched by
                         * the stream grabber until we pass it back to the stream grabber. */

                        PylonBuffer <Byte> buffer;        /* Reference to the buffer attached to the grab result. */

                        /* Get the buffer from the dictionary. Since we also got the buffer index,
                         * we could alternatively use an array, e.g. buffers[bufferIndex]. */
                        if (!buffers[woIndex].TryGetValue(grabResult[woIndex].hBuffer, out buffer))
                        {
                            /* Oops. No buffer available? We should never have reached this point. Since all buffers are
                             * in the dictionary. */
                            throw new Exception("Failed to find the buffer associated with the handle returned in grab result.");
                        }

                        /* Perform processing. */
                        getMinMax(buffer.Array, grabResult[woIndex].SizeX, grabResult[woIndex].SizeY, out min, out max);
                        Console.WriteLine("Grabbed frame {0} from camera {1} into buffer {2}. Min. val={3}, Max. val={4}",
                                          nGrabs, woIndex, bufferIndex, min, max);

                        /* Display image */
                        Pylon.ImageWindowDisplayImage <Byte>(woIndex, buffer, grabResult[woIndex]);
                    }
                    else if (grabResult[woIndex].Status == EPylonGrabStatus.Failed)
                    {
                        Console.Error.WriteLine("Frame {0} wasn't grabbed successfully.  Error code = {1}",
                                                nGrabs, grabResult[woIndex].ErrorCode);
                    }

                    /* Once finished with the processing, requeue the buffer to be filled again. */
                    Pylon.StreamGrabberQueueBuffer(hGrabber[woIndex], grabResult[woIndex].hBuffer, bufferIndex);

                    nGrabs++;
                }

                /* Clean up. */
                /* Stop the image aquisition on the cameras. */
                for (deviceIndex = 0; deviceIndex < NUM_DEVICES; ++deviceIndex)
                {
                    /*  ... Stop the camera. */
                    Pylon.DeviceExecuteCommandFeature(hDev[deviceIndex], "AcquisitionStop");
                }

                // Remove all wait objects from WaitObjects.
                Pylon.WaitObjectsRemoveAll(wos);
                Pylon.WaitObjectDestroy(woTimer);
                Pylon.WaitObjectsDestroy(wos);

                for (deviceIndex = 0; deviceIndex < NUM_DEVICES; ++deviceIndex)
                {
                    /* ... We must issue a cancel call to ensure that all pending buffers are put into the
                     * stream grabber's output queue. */
                    Pylon.StreamGrabberCancelGrab(hGrabber[deviceIndex]);

                    /* ... The buffers can now be retrieved from the stream grabber. */
                    do
                    {
                        isReady = Pylon.StreamGrabberRetrieveResult(hGrabber[deviceIndex], out grabResult[deviceIndex]);
                    } while (isReady);

                    /* ... When all buffers are retrieved from the stream grabber, they can be deregistered.
                     *     After deregistering the buffers, it is safe to free the memory. */

                    foreach (KeyValuePair <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> > pair in buffers[deviceIndex])
                    {
                        Pylon.StreamGrabberDeregisterBuffer(hGrabber[deviceIndex], pair.Key);
                        pair.Value.Dispose();
                    }
                    buffers[deviceIndex] = null;

                    /* ... Release grabbing related resources. */
                    Pylon.StreamGrabberFinishGrab(hGrabber[deviceIndex]);

                    /* After calling PylonStreamGrabberFinishGrab(), parameters that impact the payload size (e.g.,
                     * the AOI width and height parameters) are unlocked and can be modified again. */

                    /* ... Close the stream grabber. */
                    Pylon.StreamGrabberClose(hGrabber[deviceIndex]);

                    /* ... Close and release the pylon device. The stream grabber becomes invalid
                     * after closing the pylon device. Don't call stream grabber related methods after
                     * closing or releasing the device. */
                    Pylon.DeviceClose(hDev[deviceIndex]);
                    Pylon.DestroyDevice(hDev[deviceIndex]);
                }

                /* Dispose timer and event. */
                timer.Dispose();
                timoutEvent.Close();

                Console.Error.WriteLine("\nPress enter to exit.");
                Console.ReadLine();

                /* ... Shut down the pylon runtime system. Don't call any pylon function after
                 * calling PylonTerminate(). */
                Pylon.Terminate();
            }
            catch (Exception e)
            {
                /* Retrieve the error message. */
                string msg = GenApi.GetLastErrorMessage() + "\n" + GenApi.GetLastErrorDetail();
                Console.Error.WriteLine("Exception caught:");
                Console.Error.WriteLine(e.Message);
                if (msg != "\n")
                {
                    Console.Error.WriteLine("Last error message:");
                    Console.Error.WriteLine(msg);
                }

                for (uint deviceIndex = 0; deviceIndex < NUM_DEVICES; ++deviceIndex)
                {
                    try
                    {
                        if (hDev[deviceIndex].IsValid)
                        {
                            /* ... Close and release the pylon device. */
                            if (Pylon.DeviceIsOpen(hDev[deviceIndex]))
                            {
                                Pylon.DeviceClose(hDev[deviceIndex]);
                            }
                            Pylon.DestroyDevice(hDev[deviceIndex]);
                        }
                    }
                    catch (Exception)
                    {
                        /*No further handling here.*/
                    }
                }
                Pylon.Terminate();  /* Releases all pylon resources. */

                Console.Error.WriteLine("\nPress enter to exit.");
                Console.ReadLine();

                Environment.Exit(1);
            }
        }
        private void setStreamGrabber()
        {
            /* Image grabbing is done using a stream grabber.
                       A device may be able to provide different streams. A separate stream grabber must
                       be used for each stream. In this sample, we create a stream grabber for the default
                       stream, i.e., the first stream ( index == 0 ).
                       */

            /* Get the number of streams supported by the device and the transport layer. */
            nStreams = Pylon.DeviceGetNumStreamGrabberChannels(_hDev);

            if (nStreams < 1)
            {
                throw new Exception("The transport layer doesn't support image streams.");
            }

            /* Create and open a stream grabber for the first channel. */
            _hGrabber = Pylon.DeviceGetStreamGrabber(_hDev, 0);
            Pylon.StreamGrabberOpen(_hGrabber);

            /* Get a handle for the stream grabber's wait object. The wait object
               allows waiting for buffers to be filled with grabbed data. */
            _hWait = Pylon.StreamGrabberGetWaitObject(_hGrabber);

            /* Determine the required size of the grab buffer. Since activating chunks will increase the
               payload size and thus the required buffer size, do this after enabling the chunks. */
            _payloadSize = checked((uint)Pylon.DeviceGetIntegerFeature(_hDev, "PayloadSize"));
            /* We must tell the stream grabber the number and size of the buffers
                we are using. */
            /* .. We will not use more than NUM_BUFFERS for grabbing. */
            Pylon.StreamGrabberSetMaxNumBuffer(_hGrabber, NUM_BUFFERS);

            /* .. We will not use buffers bigger than payloadSize bytes. */
            Pylon.StreamGrabberSetMaxBufferSize(_hGrabber, _payloadSize);
        }
Esempio n. 6
0
        int i;                                                               /* Counter. */


        public void PylonC_Open()
        {
#if Local_Variables
            PYLON_DEVICE_HANDLE hDev = new PYLON_DEVICE_HANDLE();             /* Handle for the pylon device. */
#endif
            try
            {
#if Local_Variables
                uint numDevices;                                                     /* Number of available devices. */
                PYLON_STREAMGRABBER_HANDLE hGrabber;                                 /* Handle for the pylon stream grabber. */
                PYLON_WAITOBJECT_HANDLE    hWait;                                    /* Handle used for waiting for a grab to be finished. */
                uint payloadSize;                                                    /* Size of an image frame in bytes. */
                Dictionary <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> > buffers; /* Holds handles and buffers used for grabbing. */
                PylonGrabResult_t grabResult;                                        /* Stores the result of a grab operation. */
                int  nGrabs;                                                         /* Counts the number of buffers grabbed. */
                uint nStreams;                                                       /* The number of streams provides by the device.  */
                bool isAvail;                                                        /* Used for checking feature availability. */
                bool isReady;                                                        /* Used as an output parameter. */
                int  i;                                                              /* Counter. */
#endif

#if DEBUG
                /* This is a special debug setting needed only for GigE cameras.
                 * See 'Building Applications with pylon' in the programmer's guide. */
                Environment.SetEnvironmentVariable("PYLON_GIGE_HEARTBEAT", "300000" /*ms*/);
#endif

                /* Before using any pylon methods, the pylon runtime must be initialized. */
                Pylon.Initialize();

                /* Enumerate all camera devices. You must call
                 * PylonEnumerateDevices() before creating a device. */
                numDevices = Pylon.EnumerateDevices();

                if (0 == numDevices)
                {
                    throw new Exception("No devices found.");
                }

                /* Get a handle for the first device found.  */
                hDev = Pylon.CreateDeviceByIndex(0);

                /* Before using the device, it must be opened. Open it for configuring
                 * parameters and for grabbing images. */
                Pylon.DeviceOpen(hDev, Pylon.cPylonAccessModeControl | Pylon.cPylonAccessModeStream);

                /* Print out the name of the camera we are using. */
                {
                    bool isReadable = Pylon.DeviceFeatureIsReadable(hDev, "DeviceModelName");
                    if (isReadable)
                    {
                        string name = Pylon.DeviceFeatureToString(hDev, "DeviceModelName");
                        Console.WriteLine("Using camera {0}.", name);
                    }
                }

                /* Set the pixel format to Mono8, where gray values will be output as 8 bit values for each pixel. */
                /* ... Check first to see if the device supports the Mono8 format. */
                isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "EnumEntry_PixelFormat_YUV422Packed");

                if (!isAvail)
                {
                    /* Feature is not available. */
                    throw new Exception("Device doesn't support the Mono8/YUV422Packed pixel format.");
                }
                /* ... Set the pixel format to Mono8. */
                Pylon.DeviceFeatureFromString(hDev, "PixelFormat", "YUV422Packed");

                /* Disable acquisition start trigger if available */
                isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "EnumEntry_TriggerSelector_AcquisitionStart");
                if (isAvail)
                {
                    Pylon.DeviceFeatureFromString(hDev, "TriggerSelector", "AcquisitionStart");
                    Pylon.DeviceFeatureFromString(hDev, "TriggerMode", "Off");
                }

                /* Disable frame burst start trigger if available */
                isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "EnumEntry_TriggerSelector_FrameBurstStart");
                if (isAvail)
                {
                    Pylon.DeviceFeatureFromString(hDev, "TriggerSelector", "FrameBurstStart");
                    Pylon.DeviceFeatureFromString(hDev, "TriggerMode", "Off");
                }

                /* Disable frame start trigger if available */
                isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "EnumEntry_TriggerSelector_FrameStart");
                if (isAvail)
                {
                    Pylon.DeviceFeatureFromString(hDev, "TriggerSelector", "FrameStart");
                    Pylon.DeviceFeatureFromString(hDev, "TriggerMode", "Off");
                }

                /* We will use the Continuous frame mode, i.e., the camera delivers
                 * images continuously. */
                Pylon.DeviceFeatureFromString(hDev, "AcquisitionMode", "Continuous");

                /* For GigE cameras, we recommend increasing the packet size for better
                 * performance. When the network adapter supports jumbo frames, set the packet
                 * size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size
                 * to 1500. */
                /* ... Check first to see if the GigE camera packet size parameter is supported and if it is writable. */
                isAvail = Pylon.DeviceFeatureIsWritable(hDev, "GevSCPSPacketSize");
                if (isAvail)
                {
                    /* ... The device supports the packet size feature. Set a value. */
                    Pylon.DeviceSetIntegerFeature(hDev, "GevSCPSPacketSize", 1500);
                }

                /* Determine the required size of the grab buffer. */
                payloadSize = checked ((uint)Pylon.DeviceGetIntegerFeature(hDev, "PayloadSize"));

                /* Image grabbing is done using a stream grabber.
                 * A device may be able to provide different streams. A separate stream grabber must
                 * be used for each stream. In this sample, we create a stream grabber for the default
                 * stream, i.e., the first stream ( index == 0 ).
                 */

                /* Get the number of streams supported by the device and the transport layer. */
                nStreams = Pylon.DeviceGetNumStreamGrabberChannels(hDev);

                if (nStreams < 1)
                {
                    throw new Exception("The transport layer doesn't support image streams.");
                }

                /* Create and open a stream grabber for the first channel. */
                hGrabber = Pylon.DeviceGetStreamGrabber(hDev, 0);
                Pylon.StreamGrabberOpen(hGrabber);

                /* Get a handle for the stream grabber's wait object. The wait object
                 * allows waiting for buffers to be filled with grabbed data. */
                hWait = Pylon.StreamGrabberGetWaitObject(hGrabber);

                /* We must tell the stream grabber the number and size of the buffers
                 * we are using. */
                /* .. We will not use more than NUM_BUFFERS for grabbing. */
                Pylon.StreamGrabberSetMaxNumBuffer(hGrabber, NUM_BUFFERS);

                /* .. We will not use buffers bigger than payloadSize bytes. */
                Pylon.StreamGrabberSetMaxBufferSize(hGrabber, payloadSize);

                /*  Allocate the resources required for grabbing. After this, critical parameters
                *  that impact the payload size must not be changed until FinishGrab() is called. */
                Pylon.StreamGrabberPrepareGrab(hGrabber);

                /* Before using the buffers for grabbing, they must be registered at
                 * the stream grabber. For each registered buffer, a buffer handle
                 * is returned. After registering, these handles are used instead of the
                 * buffer objects pointers. The buffer objects are held in a dictionary,
                 * that provides access to the buffer using a handle as key.
                 */
                buffers = new Dictionary <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> >();
                for (i = 0; i < NUM_BUFFERS; ++i)
                {
                    PylonBuffer <Byte>        buffer = new PylonBuffer <byte>(payloadSize, true);
                    PYLON_STREAMBUFFER_HANDLE handle = Pylon.StreamGrabberRegisterBuffer(hGrabber, ref buffer);
                    buffers.Add(handle, buffer);
                }

                /* Feed the buffers into the stream grabber's input queue. For each buffer, the API
                 * allows passing in an integer as additional context information. This integer
                 * will be returned unchanged when the grab is finished. In our example, we use the index of the
                 * buffer as context information. */
                i = 0;
                foreach (KeyValuePair <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> > pair in buffers)
                {
                    Pylon.StreamGrabberQueueBuffer(hGrabber, pair.Key, i++);
                }

                /* The stream grabber is now prepared. As soon the camera starts acquiring images,
                 * the image data will be grabbed into the provided buffers.  */

                /* Let the camera acquire images. */
                Pylon.DeviceExecuteCommandFeature(hDev, "AcquisitionStart");

                /* Grab NUM_GRABS images */
                nGrabs = 0;                                         /* Counts the number of grabbed images. */
                //while (nGrabs < NUM_GRABS)
                while (nGrabs < NUM_GRABS)
                {
                    int  bufferIndex;                                   /* Index of the buffer. */
                    Byte min, max;
                    /* Wait for the next buffer to be filled. Wait up to 1000 ms. */
                    isReady = Pylon.WaitObjectWait(hWait, 1000);

                    if (!isReady)
                    {
                        /* Timeout occurred. */
                        throw new Exception("Grab timeout occurred.");
                    }

                    /* Since the wait operation was successful, the result of at least one grab
                     * operation is available. Retrieve it. */
                    isReady = Pylon.StreamGrabberRetrieveResult(hGrabber, out grabResult);

                    if (!isReady)
                    {
                        /* Oops. No grab result available? We should never have reached this point.
                         * Since the wait operation above returned without a timeout, a grab result
                         * should be available. */
                        throw new Exception("Failed to retrieve a grab result");
                    }

                    nGrabs++;

                    /* Get the buffer index from the context information. */
                    bufferIndex = (int)grabResult.Context;

                    /* Check to see if the image was grabbed successfully. */
                    if (grabResult.Status == EPylonGrabStatus.Grabbed)
                    {
                        /*  Success. Perform image processing. Since we passed more than one buffer
                         * to the stream grabber, the remaining buffers are filled in the background while
                         * we do the image processing. The processed buffer won't be touched by
                         * the stream grabber until we pass it back to the stream grabber. */

                        PylonBuffer <Byte> buffer;                               /* Reference to the buffer attached to the grab result. */

                        /* Get the buffer from the dictionary. Since we also got the buffer index,
                         * we could alternatively use an array, e.g. buffers[bufferIndex]. */
                        if (!buffers.TryGetValue(grabResult.hBuffer, out buffer))
                        {
                            /* Oops. No buffer available? We should never have reached this point. Since all buffers are
                             * in the dictionary. */
                            throw new Exception("Failed to find the buffer associated with the handle returned in grab result.");
                        }

                        /* Perform processing. */
                        getMinMax(buffer.Array, grabResult.SizeX, grabResult.SizeY, out min, out max);
                        Console.WriteLine("Grabbed frame {0} into buffer {1}. Min. gray value = {2}, Max. gray value = {3}",
                                          nGrabs, bufferIndex, min, max);

                        /* Display image */                        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////

                        WpfApp5.MainWindow.Pylon_Buffer = buffer;
                        WpfApp5.MainWindow.GrabResult   = grabResult;
                        Console.WriteLine("the contents of buffer: [{0, 10}] in OverlappedGrab Class.", buffer.Array[0]);
                        Console.WriteLine("the contents of buffer: [{0, 10}] in WpfApp3.MainWindow.Pylon_Buffer.", WpfApp5.MainWindow.Pylon_Buffer.Array[0]);

                        Pylon.ImageWindowDisplayImage <Byte>(0, buffer, grabResult);
                        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    }
                    else if (grabResult.Status == EPylonGrabStatus.Failed)
                    {
                        Console.Error.WriteLine("Frame {0} wasn't grabbed successfully.  Error code = {1}",
                                                nGrabs, grabResult.ErrorCode);
                    }

                    /* Once finished with the processing, requeue the buffer to be filled again. */
                    Pylon.StreamGrabberQueueBuffer(hGrabber, grabResult.hBuffer, bufferIndex);
                }

                /* Clean up. */

#if DONT_COMPILE_THESE_CODE
                /*  ... Stop the camera. */
                Pylon.DeviceExecuteCommandFeature(hDev, "AcquisitionStop");

                /* ... We must issue a cancel call to ensure that all pending buffers are put into the
                 * stream grabber's output queue. */
                Pylon.StreamGrabberCancelGrab(hGrabber);

                /* ... The buffers can now be retrieved from the stream grabber. */
                do
                {
                    isReady = Pylon.StreamGrabberRetrieveResult(hGrabber, out grabResult);
                } while (isReady);

                /* ... When all buffers are retrieved from the stream grabber, they can be deregistered.
                 *         After deregistering the buffers, it is safe to free the memory. */

                foreach (KeyValuePair <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> > pair in buffers)
                {
                    Pylon.StreamGrabberDeregisterBuffer(hGrabber, pair.Key);
                    pair.Value.Dispose();
                }
                buffers = null;

                /* ... Release grabbing related resources. */
                Pylon.StreamGrabberFinishGrab(hGrabber);

                /* After calling PylonStreamGrabberFinishGrab(), parameters that impact the payload size (e.g.,
                 * the AOI width and height parameters) are unlocked and can be modified again. */

                /* ... Close the stream grabber. */
                Pylon.StreamGrabberClose(hGrabber);

                /* ... Close and release the pylon device. The stream grabber becomes invalid
                 * after closing the pylon device. Don't call stream grabber related methods after
                 * closing or releasing the device. */
                Pylon.DeviceClose(hDev);
                Pylon.DestroyDevice(hDev);

                Console.Error.WriteLine("\nPress enter to exit.");
                Console.ReadLine();

                /* ... Shut down the pylon runtime system. Don't call any pylon method after
                 * calling Pylon.Terminate(). */
                Pylon.Terminate();
#endif
            }
            catch (Exception e)
            {
                /* Retrieve the error message. */
                string msg = GenApi.GetLastErrorMessage() + "\n" + GenApi.GetLastErrorDetail();
                Console.Error.WriteLine("Exception caught:");
                Console.Error.WriteLine(e.Message);
                if (msg != "\n")
                {
                    Console.Error.WriteLine("Last error message:");
                    Console.Error.WriteLine(msg);
                }

                try
                {
                    if (hDev.IsValid)
                    {
                        /* ... Close and release the pylon device. */
                        if (Pylon.DeviceIsOpen(hDev))
                        {
                            Pylon.DeviceClose(hDev);
                        }
                        Pylon.DestroyDevice(hDev);
                    }
                }
                catch (Exception)
                {
                    /*No further handling here.*/
                }

                Pylon.Terminate();                  /* Releases all pylon resources. */

                Console.Error.WriteLine("\nPress enter to exit.");
                Console.ReadLine();

                Environment.Exit(1);
            }
        }
Esempio n. 7
0
        private void initStreamMode(uint NUM_BUFFERS, out PYLON_STREAMGRABBER_HANDLE hGrabber, out PYLON_WAITOBJECT_HANDLE hWait, out Dictionary <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> > buffers)
        {
            uint numDevices;                           /* Number of available devices. */
            /* Handle for the pylon stream grabber. */
            /* Handle used for waiting for a grab to be finished. */
            uint payloadSize;                          /* Size of an image frame in bytes. */
            /* Holds handles and buffers used for grabbing. */
            /* Stores the result of a grab operation. */
            /* Counts the number of buffers grabbed. */
            uint nStreams;                            /* The number of streams provides by the device.  */
            bool isAvail;                             /* Used for checking feature availability. */
            /* Used as an output parameter. */
            int i;                                    /* Counter. */

#if DEBUG
            /* This is a special debug setting needed only for GigE cameras.
             * See 'Building Applications with pylon' in the programmer's guide. */
            Environment.SetEnvironmentVariable("PYLON_GIGE_HEARTBEAT", "300000" /*ms*/);
#endif


            isAvail = setStreamModeFeature();

            //*******************************設定 Stream 參數 Start *****************************************************************************
            /* Determine the required size of the grab buffer. */
            payloadSize = checked ((uint)Pylon.DeviceGetIntegerFeature(_pylonDevHandle, "PayloadSize"));



            /* Get the number of streams supported by the device and the transport layer. */
            nStreams = Pylon.DeviceGetNumStreamGrabberChannels(_pylonDevHandle);

            if (nStreams < 1)
            {
                throw new Exception("The transport layer doesn't support image streams.");
            }

            /* Create and open a stream grabber for the first channel. */
            hGrabber = Pylon.DeviceGetStreamGrabber(_pylonDevHandle, 0);
            Pylon.StreamGrabberOpen(hGrabber);

            /* Get a handle for the stream grabber's wait object. The wait object
             * allows waiting for buffers to be filled with grabbed data. */
            hWait = Pylon.StreamGrabberGetWaitObject(hGrabber);

            /* We must tell the stream grabber the number and size of the buffers
             *      we are using. */
            /* .. We will not use more than NUM_BUFFERS for grabbing. */
            Pylon.StreamGrabberSetMaxNumBuffer(hGrabber, NUM_BUFFERS);

            /* .. We will not use buffers bigger than payloadSize bytes. */
            Pylon.StreamGrabberSetMaxBufferSize(hGrabber, payloadSize);

            /*  Allocate the resources required for grabbing. After this, critical parameters
            *       that impact the payload size must not be changed until FinishGrab() is called. */
            Pylon.StreamGrabberPrepareGrab(hGrabber);

            /* Before using the buffers for grabbing, they must be registered at
             * the stream grabber. For each registered buffer, a buffer handle
             * is returned. After registering, these handles are used instead of the
             * buffer objects pointers. The buffer objects are held in a dictionary,
             * that provides access to the buffer using a handle as key.
             */
            buffers = new Dictionary <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> >();
            for (i = 0; i < NUM_BUFFERS; ++i)
            {
                PylonBuffer <Byte>        buffer = new PylonBuffer <byte>(payloadSize, true);
                PYLON_STREAMBUFFER_HANDLE handle = Pylon.StreamGrabberRegisterBuffer(hGrabber, ref buffer);
                buffers.Add(handle, buffer);
            }

            /* Feed the buffers into the stream grabber's input queue. For each buffer, the API
             * allows passing in an integer as additional context information. This integer
             * will be returned unchanged when the grab is finished. In our example, we use the index of the
             * buffer as context information. */
            i = 0;
            foreach (KeyValuePair <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> > pair in buffers)
            {
                Pylon.StreamGrabberQueueBuffer(hGrabber, pair.Key, i++);
            }
        }
Esempio n. 8
0
        private void chunkGrabImageMethod()
        {
            string triggerSelectorValue = "FrameStart";             /* Preselect the trigger for image acquisition */

            /* Check the available camera trigger mode(s) to select the appropriate one:
             * acquisition start trigger mode (used by previous cameras;
             * do not confuse with acquisition start command) or
             * frame start trigger mode (equivalent to previous acquisition start trigger mode). */


            bool isAvailAcquisitionStart = Pylon.DeviceFeatureIsAvailable(_pylonDevHandle, "EnumEntry_TriggerSelector_AcquisitionStart");
            bool isAvailFrameStart       = Pylon.DeviceFeatureIsAvailable(_pylonDevHandle, "EnumEntry_TriggerSelector_FrameStart");

            /* Check to see if the camera implements the acquisition start trigger mode only. */
            bool isAcqStartTriggerModeOnly = (isAvailAcquisitionStart && !isAvailFrameStart);

            if (isAcqStartTriggerModeOnly)
            {
                /* Camera uses the acquisition start trigger as the only trigger mode. */
                Pylon.DeviceFeatureFromString(_pylonDevHandle, "TriggerSelector", "AcquisitionStart");
                Pylon.DeviceFeatureFromString(_pylonDevHandle, "TriggerMode", "On");
                triggerSelectorValue = "AcquisitionStart";
            }
            else
            {
                /* Camera may have the acquisition start trigger mode and the frame start trigger mode implemented.
                 * In this case, the acquisition trigger mode must be switched off. */
                if (isAvailAcquisitionStart)
                {
                    Pylon.DeviceFeatureFromString(_pylonDevHandle, "TriggerSelector", "AcquisitionStart");
                    Pylon.DeviceFeatureFromString(_pylonDevHandle, "TriggerMode", "Off");
                }
                /* To trigger each single frame by software or external hardware trigger: Enable the frame start trigger mode. */
                Pylon.DeviceFeatureFromString(_pylonDevHandle, "TriggerSelector", "FrameStart");
                Pylon.DeviceFeatureFromString(_pylonDevHandle, "TriggerMode", "On");
            }

            /* Note: the trigger selector must be set to the appropriate trigger mode
             * before setting the trigger source or issuing software triggers.
             * Frame start trigger mode for newer cameras, acquisition start trigger mode for previous cameras. */
            Pylon.DeviceFeatureFromString(_pylonDevHandle, "TriggerSelector", triggerSelectorValue);

            /* Enable software triggering. */
            /* ... Select the software trigger as the trigger source. */
            Pylon.DeviceFeatureFromString(_pylonDevHandle, "TriggerSource", "Software");

            /* When using software triggering, the Continuous frame mode should be used. Once
             * acquisition is started, the camera sends one image each time a software trigger is
             * issued. */
            Pylon.DeviceFeatureFromString(_pylonDevHandle, "AcquisitionMode", "Continuous");


            //********************************************************************************************************
            setChunkModeFeatures();

            /* The data block containing the image chunk and the other chunks has a self-descriptive layout.
             * A chunk parser is used to extract the appended chunk data from the grabbed image frame.
             * Create a chunk parser. */
            PYLON_CHUNKPARSER_HANDLE hChunkParser = Pylon.DeviceCreateChunkParser(_pylonDevHandle);

            if (!hChunkParser.IsValid)
            {
                /* The transport layer doesn't provide a chunk parser. */
                throw new Exception("No chunk parser available.");
            }


            /* Image grabbing is done using a stream grabber.
             * A device may be able to provide different streams. A separate stream grabber must
             * be used for each stream. In this sample, we create a stream grabber for the default
             * stream, i.e., the first stream ( index == 0 ).
             */

            /* Get the number of streams supported by the device and the transport layer. */
            var nStreams = Pylon.DeviceGetNumStreamGrabberChannels(_pylonDevHandle);

            if (nStreams < 1)
            {
                throw new Exception("The transport layer doesn't support image streams.");
            }

            /* Create and open a stream grabber for the first channel. */
            uint firstChannel = 0;
            PYLON_STREAMGRABBER_HANDLE hGrabber = Pylon.DeviceGetStreamGrabber(_pylonDevHandle, firstChannel);

            Pylon.StreamGrabberOpen(hGrabber);

            /* Get a handle for the stream grabber's wait object. The wait object
             * allows waiting for buffers to be filled with grabbed data. */
            PYLON_WAITOBJECT_HANDLE hWait = Pylon.StreamGrabberGetWaitObject(hGrabber);

            /* Determine the required size of the grab buffer. Since activating chunks will increase the
             * payload size and thus the required buffer size, do this after enabling the chunks. */
            uint payloadSize = checked ((uint)Pylon.DeviceGetIntegerFeature(_pylonDevHandle, "PayloadSize"));

            /* We must tell the stream grabber the number and size of the buffers
             *      we are using. */
            /* .. We will not use more than NUM_BUFFERS for grabbing. */
            uint NUM_BUFFERS = 2;

            Pylon.StreamGrabberSetMaxNumBuffer(hGrabber, NUM_BUFFERS);

            /* .. We will not use buffers bigger than payloadSize bytes. */
            Pylon.StreamGrabberSetMaxBufferSize(hGrabber, payloadSize);

            /*  Allocate the resources required for grabbing. After this, critical parameters
            *       that impact the payload size must not be changed until FinishGrab() is called. */
            Pylon.StreamGrabberPrepareGrab(hGrabber);

            /* Before using the buffers for grabbing, they must be registered at
             * the stream grabber. For each registered buffer, a buffer handle
             * is returned. After registering, these handles are used instead of the
             * buffer objects pointers. The buffer objects are held in a dictionary,
             * that provides access to the buffer using a handle as key.
             */
            var buffers = new Dictionary <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> >();

            for (int i = 0; i < NUM_BUFFERS; ++i)
            {
                PylonBuffer <Byte>        buffer = new PylonBuffer <byte>(payloadSize, true);
                PYLON_STREAMBUFFER_HANDLE handle = Pylon.StreamGrabberRegisterBuffer(hGrabber, ref buffer);
                buffers.Add(handle, buffer);
            }

            /* Feed the buffers into the stream grabber's input queue. For each buffer, the API
             * allows passing in an integer as additional context information. This integer
             * will be returned unchanged when the grab is finished. In our example, we use the index of the
             * buffer as context information. */
            var index = 0;

            foreach (KeyValuePair <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> > pair in buffers)
            {
                Pylon.StreamGrabberQueueBuffer(hGrabber, pair.Key, index++);
            }

            /* Issue an acquisition start command. Because the trigger mode is enabled, issuing the start command
             * itself will not trigger any image acquisitions. Issuing the start command simply prepares the camera.
             * Once the camera is prepared it will acquire one image for every trigger it receives. */
            Pylon.DeviceExecuteCommandFeature(_pylonDevHandle, "AcquisitionStart");

            /* Trigger the first image. */
            Pylon.DeviceExecuteCommandFeature(_pylonDevHandle, "TriggerSoftware");

            /* Grab NUM_GRABS images. */
            PylonGrabResult_t grabResult;
            int NUM_GRABS = 1;
            int nGrabs    = 0;                                    /* Counts the number of images grabbed. */

            while (nGrabs < NUM_GRABS)
            {
                int bufferIndex;                              /* Index of the buffer. */

                /* Wait for the next buffer to be filled. Wait up to 1000 ms. */
                bool isReady = Pylon.WaitObjectWait(hWait, 1000);

                if (!isReady)
                {
                    /* Timeout occurred. */
                    throw new Exception("Grab timeout occurred.\n");
                }

                /* Since the wait operation was successful, the result of at least one grab
                 * operation is available. Retrieve it. */
                isReady = Pylon.StreamGrabberRetrieveResult(hGrabber, out grabResult);

                if (!isReady)
                {
                    /* Oops. No grab result available? We should never have reached this point.
                     * Since the wait operation above returned without a timeout, a grab result
                     * should be available. */
                    throw new Exception("Failed to retrieve a grab result.\n");
                }

                nGrabs++;

                /* Trigger the next image. Since we passed more than one buffer to the stream grabber,
                 * the triggered image will be grabbed while the image processing is performed.  */
                Pylon.DeviceExecuteCommandFeature(_pylonDevHandle, "TriggerSoftware");

                /* Get the buffer index from the context information. */
                bufferIndex = (int)grabResult.Context;

                /* Check to see if the image was grabbed successfully. */

                if (grabResult.Status == EPylonGrabStatus.Grabbed)
                {
                    /*  The grab is successful.  */

                    PylonBuffer <Byte> buffer;                           /* Reference to the buffer attached to the grab result. */

                    /* Get the buffer from the dictionary. Since we also got the buffer index,
                     * we could alternatively use an array, e.g. buffers[bufferIndex]. */
                    if (!buffers.TryGetValue(grabResult.hBuffer, out buffer))
                    {
                        /* Oops. No buffer available? We should never have reached this point. Since all buffers are
                         * in the dictionary. */
                        throw new Exception("Failed to find the buffer associated with the handle returned in grab result.");
                    }

                    //Console.WriteLine("Grabbed frame {0} into buffer {1}.", nGrabs, bufferIndex);



                    /* Check to see if we really got image data plus chunk data. */
                    if (grabResult.PayloadType != EPylonPayloadType.PayloadType_ChunkData)
                    {
                        Console.WriteLine("Received a buffer not containing chunk data?");
                    }
                    else
                    {
                        /* Process the chunk data. This is done by passing the grabbed image buffer
                         * to the chunk parser. When the chunk parser has processed the buffer, the chunk
                         * data can be accessed in the same manner as "normal" camera parameters.
                         * The only exception is the CRC checksum feature. There are dedicated functions for
                         * checking the CRC checksum. */

                        bool hasCRC;

                        /* Let the parser extract the data. */
                        Pylon.ChunkParserAttachBuffer(hChunkParser, buffer);


                        /* Check the CRC checksum. */
                        hasCRC = Pylon.ChunkParserHasCRC(hChunkParser);
                        bool isOk = (hasCRC) ? Pylon.ChunkParserCheckCRC(hChunkParser) : true;

                        bool isAvail = Pylon.DeviceFeatureIsAvailable(_pylonDevHandle, "ChunkWidth");
                        long chunkWidth = 0, chunkHeight = 0;
                        //Console.WriteLine("Frame {0} {1} a frame width chunk.", nGrabs, isAvail ? "contains" : "doesn't contain");
                        if (isAvail)
                        {
                            /* ... Get the value. */
                            chunkWidth = Pylon.DeviceGetIntegerFeature(_pylonDevHandle, "ChunkWidth");

                            //Console.WriteLine("Width of frame {0}: {1}.", nGrabs, chunkWidth);
                        }

                        /* Retrieve the chunk height value. */
                        /* ... Check the availability. */
                        isAvail = Pylon.DeviceFeatureIsAvailable(_pylonDevHandle, "ChunkHeight");

                        Console.WriteLine("Frame {0} {1} a frame height chunk.", nGrabs, isAvail ? "contains" : "doesn't contain");
                        if (isAvail)
                        {
                            /* ... Get the value. */
                            chunkHeight = Pylon.DeviceGetIntegerFeature(_pylonDevHandle, "ChunkHeight");

                            //Console.WriteLine("Height of frame {0}: {1}.", nGrabs, chunkHeight);
                        }

                        if (isOk)
                        {
                            _latestImage = new HImage("byte", (int)chunkWidth, (int)chunkHeight, buffer.Pointer);
                        }
                    }
                    /* Before requeueing the buffer, you should detach it from the chunk parser. */
                    Pylon.ChunkParserDetachBuffer(hChunkParser);                      /* Now the chunk data in the buffer is no longer accessible. */
                }
                else if (grabResult.Status == EPylonGrabStatus.Failed)
                {
                    Console.Error.WriteLine("Frame {0} wasn't grabbed successfully.  Error code = {1}", nGrabs, grabResult.ErrorCode);
                }

                /* Once finished with the processing, requeue the buffer to be filled again. */
                Pylon.StreamGrabberQueueBuffer(hGrabber, grabResult.hBuffer, bufferIndex);
            }
        }
Esempio n. 9
0
        private void ContinuousGrab()
        {
            try
            {
                lock (dev)
                {
                    // prepare grabbing, see pylon C.NET docs
                    Pylon.DeviceOpen(dev, Pylon.cPylonAccessModeControl | Pylon.cPylonAccessModeStream);
                    Pylon.DeviceFeatureFromString(dev, "AcquisitionMode", "Continuous");
                    uint payloadSize = checked((uint)Pylon.DeviceGetIntegerFeature(dev, "PayloadSize"));
                    uint nStreams = Pylon.DeviceGetNumStreamGrabberChannels(dev);
                    hGrabber = Pylon.DeviceGetStreamGrabber(dev, 0);
                    Pylon.StreamGrabberOpen(hGrabber);
                    hWait = Pylon.StreamGrabberGetWaitObject(hGrabber);
                    Pylon.StreamGrabberSetMaxNumBuffer(hGrabber, NUM_BUFFERS);
                    Pylon.StreamGrabberSetMaxBufferSize(hGrabber, payloadSize);
                    Pylon.StreamGrabberPrepareGrab(hGrabber);
                    var buffers = new PylonBuffer<Byte>[NUM_BUFFERS];
                    var handles = new PYLON_STREAMBUFFER_HANDLE[NUM_BUFFERS];
                    for (int i = 0; i < NUM_BUFFERS; i++)
                    {
                        PylonBuffer<Byte> buffer = new PylonBuffer<byte>(payloadSize, true);
                        PYLON_STREAMBUFFER_HANDLE handle = Pylon.StreamGrabberRegisterBuffer(hGrabber, ref buffer);
                        Pylon.StreamGrabberQueueBuffer(hGrabber, handle, i);
                        handles[i] = handle;
                        buffers[i] = buffer;
                    }

                    Pylon.DeviceExecuteCommandFeature(dev, "AcquisitionStart");

                    PylonGrabResult_t grabResult;
                    bool isReady;

                    while (grabbing)
                    {
                        int bufferIndex;
                        isReady = Pylon.WaitObjectWait(hWait, 1000);

                        if (!isReady)
                        {
                            throw new Exception("Grab timeout");
                        }
                        //

                        isReady = Pylon.StreamGrabberRetrieveResult(hGrabber, out grabResult);

                        if (!isReady)
                        {
                            throw new Exception("Failed to retrieve a grab result");
                        }

                        bufferIndex = (int)grabResult.Context;

                        if (grabResult.Status == EPylonGrabStatus.Grabbed)
                        {
                            PylonBuffer<Byte> buffer = buffers[bufferIndex];
                            OnGrabAndDispose(GrabResultToImage(grabResult, buffer));
                            //Thread.Sleep(10);
                        }
                        else if (grabResult.Status == EPylonGrabStatus.Failed)
                        {
                            Console.Error.WriteLine("Error grabbing. Error Code = {0}", grabResult.ErrorCode);
                        }

                        Pylon.StreamGrabberQueueBuffer(hGrabber, grabResult.hBuffer, bufferIndex);

                    }
                    Pylon.DeviceExecuteCommandFeature(dev, "AcquisitionStop");
                    Pylon.StreamGrabberCancelGrab(hGrabber);
                    do
                    {
                        isReady = Pylon.StreamGrabberRetrieveResult(hGrabber, out grabResult);
                    } while (isReady);
                    for (int i = 0; i < NUM_BUFFERS; i++)
                    {
                        Pylon.StreamGrabberDeregisterBuffer(hGrabber, handles[i]);
                        buffers[i].Dispose();
                    }
                    Pylon.StreamGrabberFinishGrab(hGrabber);
                    Pylon.StreamGrabberClose(hGrabber);
                    Pylon.DeviceClose(dev);
                }
            }
            catch
            {
                Console.WriteLine(GenApi.GetLastErrorDetail());
            }
        }
        private void initStreamMode()
        {
            _width = (int)Pylon.DeviceGetIntegerFeature(hDev, "Width");
            _height = (int)Pylon.DeviceGetIntegerFeature(hDev, "Height");
            /* Print out the name of the camera we are using. */
            bool isReadable = Pylon.DeviceFeatureIsReadable(hDev, "DeviceModelName");
            if (isReadable)
            {
                string name = Pylon.DeviceFeatureToString(hDev, "DeviceModelName");
                Console.WriteLine("Using camera {0}.", name);
            }

            /* Set the pixel format to Mono8, where gray values will be output as 8 bit values for each pixel. */
            /* ... Check first to see if the device supports the Mono8 format. */
            isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "EnumEntry_PixelFormat_Mono8");

            if (!isAvail)
            {
                /* Feature is not available. */
                throw new Exception("Device doesn't support the Mono8 pixel format.");
            }
            /* ... Set the pixel format to Mono8. */
            bool isWritable = Pylon.DeviceFeatureIsWritable(hDev, "PixelFormat");
            if (isWritable)
                Pylon.DeviceFeatureFromString(hDev, "PixelFormat", "Mono8");

            /* Disable acquisition start trigger if available */
            isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "EnumEntry_TriggerSelector_AcquisitionStart");
            if (isAvail)
            {
                isWritable = Pylon.DeviceFeatureIsWritable(hDev, "TriggerSelector");
                if (isWritable)
                    Pylon.DeviceFeatureFromString(hDev, "TriggerSelector", "AcquisitionStart");

                isWritable = Pylon.DeviceFeatureIsWritable(hDev, "TriggerMode");
                if (isWritable)
                    Pylon.DeviceFeatureFromString(hDev, "TriggerMode", "Off");
            }

            /* Disable frame start trigger if available */
            isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "EnumEntry_TriggerSelector_FrameStart");
            if (isAvail)
            {
                isWritable = Pylon.DeviceFeatureIsWritable(hDev, "TriggerSelector");
                if (isWritable)
                    Pylon.DeviceFeatureFromString(hDev, "TriggerSelector", "FrameStart");

                isWritable = Pylon.DeviceFeatureIsWritable(hDev, "TriggerMode");
                if (isWritable)
                    Pylon.DeviceFeatureFromString(hDev, "TriggerMode", "Off");
            }

            /* We will use the Continuous frame mode, i.e., the camera delivers
            images continuously. */
            isWritable = Pylon.DeviceFeatureIsWritable(hDev, "AcquisitionMode");
            if (isWritable)
                Pylon.DeviceFeatureFromString(hDev, "AcquisitionMode", "Continuous");

            /* For GigE cameras, we recommend increasing the packet size for better
               performance. When the network adapter supports jumbo frames, set the packet
               size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size
               to 1500. */
            /* ... Check first to see if the GigE camera packet size parameter is supported and if it is writable. */
            isAvail = Pylon.DeviceFeatureIsWritable(hDev, "GevSCPSPacketSize");
            if (isAvail)
            {
                /* ... The device supports the packet size feature. Set a value. */
                isWritable = Pylon.DeviceFeatureIsWritable(hDev, "GevSCPSPacketSize");
                if (isWritable)
                    Pylon.DeviceSetIntegerFeature(hDev, "GevSCPSPacketSize", GevSCPSPacketSize);
            }
            _isModelValid = isAvail;
            /* Determine the required size of the grab buffer. */
            payloadSize = checked((uint)Pylon.DeviceGetIntegerFeature(hDev, "PayloadSize"));

            /* Image grabbing is done using a stream grabber.
              A device may be able to provide different streams. A separate stream grabber must
              be used for each stream. In this sample, we create a stream grabber for the default
              stream, i.e., the first stream ( index == 0 ).
              */

            /* Get the number of streams supported by the device and the transport layer. */
            nStreams = Pylon.DeviceGetNumStreamGrabberChannels(hDev);

            if (nStreams < 1)
            {
                throw new Exception("The transport layer doesn't support image streams.");
            }

            /* Create and open a stream grabber for the first channel. */
            hGrabber = Pylon.DeviceGetStreamGrabber(hDev, 0);
            Pylon.StreamGrabberOpen(hGrabber);

            /* Get a handle for the stream grabber's wait object. The wait object
               allows waiting for buffers to be filled with grabbed data. */
            hWait = Pylon.StreamGrabberGetWaitObject(hGrabber);

            /* We must tell the stream grabber the number and size of the buffers
                we are using. */
            /* .. We will not use more than NUM_BUFFERS for grabbing. */
            Pylon.StreamGrabberSetMaxNumBuffer(hGrabber, NUM_BUFFERS);

            /* .. We will not use buffers bigger than payloadSize bytes. */
            Pylon.StreamGrabberSetMaxBufferSize(hGrabber, payloadSize);

            /*  Allocate the resources required for grabbing. After this, critical parameters
                that impact the payload size must not be changed until FinishGrab() is called. */
            Pylon.StreamGrabberPrepareGrab(hGrabber);

            /* Before using the buffers for grabbing, they must be registered at
               the stream grabber. For each registered buffer, a buffer handle
               is returned. After registering, these handles are used instead of the
               buffer objects pointers. The buffer objects are held in a dictionary,
               that provides access to the buffer using a handle as key.
             */
            buffers = new Dictionary<PYLON_STREAMBUFFER_HANDLE, PylonBuffer<Byte>>();
            int i;
            for (i = 0; i < NUM_BUFFERS; ++i)
            {
                PylonBuffer<Byte> buffer = new PylonBuffer<byte>(payloadSize, true);
                PYLON_STREAMBUFFER_HANDLE handle = Pylon.StreamGrabberRegisterBuffer(hGrabber, ref buffer);
                buffers.Add(handle, buffer);
            }

            /* Feed the buffers into the stream grabber's input queue. For each buffer, the API
               allows passing in an integer as additional context information. This integer
               will be returned unchanged when the grab is finished. In our example, we use the index of the
               buffer as context information. */
            i = 0;
            foreach (KeyValuePair<PYLON_STREAMBUFFER_HANDLE, PylonBuffer<Byte>> pair in buffers)
            {
                Pylon.StreamGrabberQueueBuffer(hGrabber, pair.Key, i++);
            }
        }
Esempio n. 11
0
        private void ContinuousGrab()
        {
            try
            {
                lock (dev)
                {
                    // prepare grabbing, see pylon C.NET docs
                    Pylon.DeviceOpen(dev, Pylon.cPylonAccessModeControl | Pylon.cPylonAccessModeStream);
                    Pylon.DeviceFeatureFromString(dev, "AcquisitionMode", "Continuous");
                    uint payloadSize = checked ((uint)Pylon.DeviceGetIntegerFeature(dev, "PayloadSize"));
                    uint nStreams    = Pylon.DeviceGetNumStreamGrabberChannels(dev);
                    hGrabber = Pylon.DeviceGetStreamGrabber(dev, 0);
                    Pylon.StreamGrabberOpen(hGrabber);
                    hWait = Pylon.StreamGrabberGetWaitObject(hGrabber);
                    Pylon.StreamGrabberSetMaxNumBuffer(hGrabber, NUM_BUFFERS);
                    Pylon.StreamGrabberSetMaxBufferSize(hGrabber, payloadSize);
                    Pylon.StreamGrabberPrepareGrab(hGrabber);
                    var buffers = new PylonBuffer <Byte> [NUM_BUFFERS];
                    var handles = new PYLON_STREAMBUFFER_HANDLE[NUM_BUFFERS];
                    for (int i = 0; i < NUM_BUFFERS; i++)
                    {
                        PylonBuffer <Byte>        buffer = new PylonBuffer <byte>(payloadSize, true);
                        PYLON_STREAMBUFFER_HANDLE handle = Pylon.StreamGrabberRegisterBuffer(hGrabber, ref buffer);
                        Pylon.StreamGrabberQueueBuffer(hGrabber, handle, i);
                        handles[i] = handle;
                        buffers[i] = buffer;
                    }

                    Pylon.DeviceExecuteCommandFeature(dev, "AcquisitionStart");

                    PylonGrabResult_t grabResult;
                    bool isReady;

                    while (grabbing)
                    {
                        int bufferIndex;
                        isReady = Pylon.WaitObjectWait(hWait, 1000);

                        if (!isReady)
                        {
                            throw new Exception("Grab timeout");
                        }
                        //

                        isReady = Pylon.StreamGrabberRetrieveResult(hGrabber, out grabResult);

                        if (!isReady)
                        {
                            throw new Exception("Failed to retrieve a grab result");
                        }

                        bufferIndex = (int)grabResult.Context;

                        if (grabResult.Status == EPylonGrabStatus.Grabbed)
                        {
                            PylonBuffer <Byte> buffer = buffers[bufferIndex];
                            OnGrabAndDispose(GrabResultToImage(grabResult, buffer));
                            //Thread.Sleep(10);
                        }
                        else if (grabResult.Status == EPylonGrabStatus.Failed)
                        {
                            Console.Error.WriteLine("Error grabbing. Error Code = {0}", grabResult.ErrorCode);
                        }

                        Pylon.StreamGrabberQueueBuffer(hGrabber, grabResult.hBuffer, bufferIndex);
                    }
                    Pylon.DeviceExecuteCommandFeature(dev, "AcquisitionStop");
                    Pylon.StreamGrabberCancelGrab(hGrabber);
                    do
                    {
                        isReady = Pylon.StreamGrabberRetrieveResult(hGrabber, out grabResult);
                    } while (isReady);
                    for (int i = 0; i < NUM_BUFFERS; i++)
                    {
                        Pylon.StreamGrabberDeregisterBuffer(hGrabber, handles[i]);
                        buffers[i].Dispose();
                    }
                    Pylon.StreamGrabberFinishGrab(hGrabber);
                    Pylon.StreamGrabberClose(hGrabber);
                    Pylon.DeviceClose(dev);
                }
            }
            catch
            {
                Console.WriteLine(GenApi.GetLastErrorDetail());
            }
        }
Esempio n. 12
0
    public void cameraInit(string cameraType)
    {
        //Initiates camera to run in 12 bit mode with continuous acquisition.
        int  i           = 0;
        uint NUM_BUFFERS = 10;

        if (cameraType == "basler")
        {
            Pylon.Initialize();
            numDevices = Pylon.EnumerateDevices();
            if (ConfigurationManager.AppSettings.Get("ipAddress").Length > 0)
            {
                while (ip != ConfigurationManager.AppSettings.Get("ipAddress"))
                {
                    hDev = Pylon.CreateDeviceByIndex(j);
                    prop = Pylon.DeviceGetDeviceInfoHandle(hDev);
                    ip   = Pylon.DeviceInfoGetPropertyValueByIndex(prop, 8);
                    j++;
                    if (j > numDevices)
                    {
                        break;
                    }
                }
            }
            else
            {
                numDevices = Pylon.EnumerateDevices();
                hDev       = Pylon.CreateDeviceByIndex(0);
            }
            try
            {
                Pylon.DeviceOpen(hDev, Pylon.cPylonAccessModeControl | Pylon.cPylonAccessModeStream);
            }
            catch (System.Threading.ThreadAbortException) { }
            catch (Exception ex)
            {
                EmailError.emailAlert(ex);
                throw (ex);
            }

            isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "EnumEntry_PixelFormat_Mono12");
            Pylon.DeviceFeatureFromString(hDev, "PixelFormat", "Mono12");
            Pylon.DeviceFeatureFromString(hDev, "AcquisitionMode", "Continuous");
            Pylon.DeviceSetIntegerFeature(hDev, "Height", 1);
            Pylon.DeviceSetFloatFeature(hDev, "ExposureTimeAbs", exp); //Exposure time is in microseconds and rounded to the closest 100 ns.
            isAvail = Pylon.DeviceFeatureIsWritable(hDev, "GevSCPSPacketSize");
            if (isAvail)
            {
                Pylon.DeviceSetIntegerFeature(hDev, "GevSCPSPacketSize", 1500);
            }
            payloadSize = checked ((uint)Pylon.DeviceGetIntegerFeature(hDev, "PayloadSize"));
            nStreams    = Pylon.DeviceGetNumStreamGrabberChannels(hDev);
            hGrabber    = Pylon.DeviceGetStreamGrabber(hDev, 0);
            Pylon.StreamGrabberOpen(hGrabber);
            hWait = Pylon.StreamGrabberGetWaitObject(hGrabber);
            Pylon.StreamGrabberSetMaxNumBuffer(hGrabber, NUM_BUFFERS);
            Pylon.StreamGrabberSetMaxBufferSize(hGrabber, payloadSize);
            Pylon.StreamGrabberPrepareGrab(hGrabber);
            buffers = new Dictionary <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> >();
            for (i = 0; i < NUM_BUFFERS; ++i)
            {
                PylonBuffer <Byte>        buffer = new PylonBuffer <byte>(payloadSize, true);
                PYLON_STREAMBUFFER_HANDLE handle = Pylon.StreamGrabberRegisterBuffer(hGrabber, ref buffer);
                buffers.Add(handle, buffer);
            }
            i = 0;
            foreach (KeyValuePair <PYLON_STREAMBUFFER_HANDLE, PylonBuffer <Byte> > pair in buffers)
            {
                Pylon.StreamGrabberQueueBuffer(hGrabber, pair.Key, i++);
            }
            Pylon.DeviceExecuteCommandFeature(hDev, "AcquisitionStart");
        }
    }
        /* Open using device.*/
        protected void Open(PYLON_DEVICE_HANDLE device)
        {
            try
            {
                /* Use provided device. */
                m_hDevice = device;

                /* Before using the device, it must be opened. Open it for configuring
                parameters and for grabbing images. */
                Pylon.DeviceOpen(m_hDevice, Pylon.cPylonAccessModeControl | Pylon.cPylonAccessModeStream);

                /* Register the callback function. */
                m_hRemovalCallback = Pylon.DeviceRegisterRemovalCallback(m_hDevice, m_callbackHandler);

                /* For GigE cameras, we recommend increasing the packet size for better
                   performance. When the network adapter supports jumbo frames, set the packet
                   size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size
                   to 1500. */
                /* ... Check first to see if the GigE camera packet size parameter is supported and if it is writable. */
                if (Pylon.DeviceFeatureIsWritable(m_hDevice, "GevSCPSPacketSize"))
                {
                    /* ... The device supports the packet size feature. Set a value. */
                    Pylon.DeviceSetIntegerFeature(m_hDevice, "GevSCPSPacketSize", 1500);
                }

                /* The sample does not work in chunk mode. It must be disabled. */
                if (Pylon.DeviceFeatureIsWritable(m_hDevice, "ChunkModeActive"))
                {
                    /* Disable the chunk mode. */
                    Pylon.DeviceSetBooleanFeature(m_hDevice, "ChunkModeActive", false);
                }

                /* Disable acquisition start trigger if available. */
                if (Pylon.DeviceFeatureIsAvailable(m_hDevice, "EnumEntry_TriggerSelector_AcquisitionStart"))
                {
                    Pylon.DeviceFeatureFromString(m_hDevice, "TriggerSelector", "AcquisitionStart");
                    Pylon.DeviceFeatureFromString(m_hDevice, "TriggerMode", "Off");
                }

                /* Disable frame start trigger if available. */
                if (Pylon.DeviceFeatureIsAvailable(m_hDevice, "EnumEntry_TriggerSelector_FrameStart"))
                {
                    Pylon.DeviceFeatureFromString(m_hDevice, "TriggerSelector", "FrameStart");
                    Pylon.DeviceFeatureFromString(m_hDevice, "TriggerMode", "Off");
                }

                /* Image grabbing is done using a stream grabber.
                  A device may be able to provide different streams. A separate stream grabber must
                  be used for each stream. In this sample, we create a stream grabber for the default
                  stream, i.e., the first stream ( index == 0 ).
                  */

                /* Get the number of streams supported by the device and the transport layer. */
                if (Pylon.DeviceGetNumStreamGrabberChannels(m_hDevice) < 1)
                {
                    throw new Exception("The transport layer doesn't support image streams.");
                }

                /* Create and open a stream grabber for the first channel. */
                m_hGrabber = Pylon.DeviceGetStreamGrabber(m_hDevice, 0);
                Pylon.StreamGrabberOpen(m_hGrabber);

                /* Get a handle for the stream grabber's wait object. The wait object
                   allows waiting for m_buffers to be filled with grabbed data. */
                m_hWait = Pylon.StreamGrabberGetWaitObject(m_hGrabber);
            }
            catch
            {
                /* Get the last error message here, because it could be overwritten by cleaning up. */
                UpdateLastError();

                try
                {
                    Close(); /* Try to close any open handles. */
                }
                catch
                {
                    /* Another exception cannot be handled. */
                }
                throw;
            }

            /* Notify that the ImageProvider is open and ready for grabbing and configuration. */
            OnDeviceOpenedEvent();
        }
        private void initStreamMode(uint NUM_BUFFERS, out PYLON_STREAMGRABBER_HANDLE hGrabber, out PYLON_WAITOBJECT_HANDLE hWait, out Dictionary<PYLON_STREAMBUFFER_HANDLE, PylonBuffer<Byte>> buffers)
        {
            uint numDevices;               /* Number of available devices. */
            /* Handle for the pylon stream grabber. */
            /* Handle used for waiting for a grab to be finished. */
            uint payloadSize;              /* Size of an image frame in bytes. */
            /* Holds handles and buffers used for grabbing. */
            /* Stores the result of a grab operation. */
            /* Counts the number of buffers grabbed. */
            uint nStreams;                 /* The number of streams provides by the device.  */
            bool isAvail;                  /* Used for checking feature availability. */
            /* Used as an output parameter. */
            int i;                        /* Counter. */

            #if DEBUG
                /* This is a special debug setting needed only for GigE cameras.
                See 'Building Applications with pylon' in the programmer's guide. */
                Environment.SetEnvironmentVariable("PYLON_GIGE_HEARTBEAT", "300000" /*ms*/);
            #endif

            isAvail = setStreamModeFeature();

            //*******************************設定 Stream 參數 Start *****************************************************************************
            /* Determine the required size of the grab buffer. */
            payloadSize = checked((uint)Pylon.DeviceGetIntegerFeature(_pylonDevHandle, "PayloadSize"));

            /* Get the number of streams supported by the device and the transport layer. */
            nStreams = Pylon.DeviceGetNumStreamGrabberChannels(_pylonDevHandle);

            if (nStreams < 1)
            {
                throw new Exception("The transport layer doesn't support image streams.");
            }

            /* Create and open a stream grabber for the first channel. */
            hGrabber = Pylon.DeviceGetStreamGrabber(_pylonDevHandle, 0);
            Pylon.StreamGrabberOpen(hGrabber);

            /* Get a handle for the stream grabber's wait object. The wait object
               allows waiting for buffers to be filled with grabbed data. */
            hWait = Pylon.StreamGrabberGetWaitObject(hGrabber);

            /* We must tell the stream grabber the number and size of the buffers
                we are using. */
            /* .. We will not use more than NUM_BUFFERS for grabbing. */
            Pylon.StreamGrabberSetMaxNumBuffer(hGrabber, NUM_BUFFERS);

            /* .. We will not use buffers bigger than payloadSize bytes. */
            Pylon.StreamGrabberSetMaxBufferSize(hGrabber, payloadSize);

            /*  Allocate the resources required for grabbing. After this, critical parameters
                that impact the payload size must not be changed until FinishGrab() is called. */
            Pylon.StreamGrabberPrepareGrab(hGrabber);

            /* Before using the buffers for grabbing, they must be registered at
               the stream grabber. For each registered buffer, a buffer handle
               is returned. After registering, these handles are used instead of the
               buffer objects pointers. The buffer objects are held in a dictionary,
               that provides access to the buffer using a handle as key.
             */
            buffers = new Dictionary<PYLON_STREAMBUFFER_HANDLE, PylonBuffer<Byte>>();
            for (i = 0; i < NUM_BUFFERS; ++i)
            {
                PylonBuffer<Byte> buffer = new PylonBuffer<byte>(payloadSize, true);
                PYLON_STREAMBUFFER_HANDLE handle = Pylon.StreamGrabberRegisterBuffer(hGrabber, ref buffer);
                buffers.Add(handle, buffer);
            }

            /* Feed the buffers into the stream grabber's input queue. For each buffer, the API
               allows passing in an integer as additional context information. This integer
               will be returned unchanged when the grab is finished. In our example, we use the index of the
               buffer as context information. */
            i = 0;
            foreach (KeyValuePair<PYLON_STREAMBUFFER_HANDLE, PylonBuffer<Byte>> pair in buffers)
            {
                Pylon.StreamGrabberQueueBuffer(hGrabber, pair.Key, i++);
            }
        }
Esempio n. 15
0
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            /* Use a random number as the device key. */
            uint DeviceKey = (uint)(new Random()).Next(int.MaxValue);
            /* In this sample all cameras belong to the same group. */
            const uint GroupKey = 0x24;


            PYLON_DEVICE_HANDLE[] hDev = new PYLON_DEVICE_HANDLE[MAX_NUM_DEVICES];        /* Handles for the pylon devices. */
            for (int deviceIndex = 0; deviceIndex < MAX_NUM_DEVICES; ++deviceIndex)
            {
                hDev[deviceIndex] = new PYLON_DEVICE_HANDLE();
            }

            try
            {
                uint numDevicesEnumerated;    /* Number of the devices connected to this PC. */
                uint numDevicesToUse;         /* Number of the devices to use in this sample. */
                bool isAvail;                 /* Used for checking feature availability. */
                bool isReady;                 /* Used as an output parameter. */
                int  i;                       /* Counter. */
                uint deviceIndex;             /* Index of device used in the following variables. */
                PYLON_WAITOBJECTS_HANDLE wos; /* Wait objects. */

                /* These are camera specific variables: */
                PYLON_STREAMGRABBER_HANDLE[] hGrabber = new PYLON_STREAMGRABBER_HANDLE[MAX_NUM_DEVICES]; /* Handle for the pylon stream grabber. */
                PYLON_WAITOBJECT_HANDLE[]    hWait    = new PYLON_WAITOBJECT_HANDLE[MAX_NUM_DEVICES];    /* Handle used for waiting for a grab to be finished. */
                uint[] payloadSize = new uint[MAX_NUM_DEVICES];                                          /* Size of an image frame in bytes. */
                uint[] nStreams    = new uint[MAX_NUM_DEVICES];                                          /* The number of streams provided by the device. */
                PYLON_STREAMBUFFER_HANDLE[] hBuffer = new PYLON_STREAMBUFFER_HANDLE[MAX_NUM_DEVICES];
                PylonBuffer <Byte>[]        buffer  = new PylonBuffer <Byte> [MAX_NUM_DEVICES];

#if DEBUG
                /* This is a special debug setting needed only for GigE cameras.
                 * See 'Building Applications with pylon' in the Programmer's Guide. */
                Environment.SetEnvironmentVariable("PYLON_GIGE_HEARTBEAT", "300000" /*ms*/);
#endif

                /* Before using any pylon methods, the pylon runtime must be initialized. */
                Pylon.Initialize();

                /* Enumerate all camera devices. You must call
                 * PylonEnumerateDevices() before creating a device. */
                numDevicesEnumerated = Pylon.EnumerateDevices();

                if (numDevicesEnumerated == 0)
                {
                    Pylon.Terminate();

                    Console.Error.WriteLine("No devices found!");
                    Console.Error.WriteLine("\nPress enter to exit.");
                    Console.ReadLine();
                    return;
                }

                /* Create wait objects. This must be done outside of the loop. */
                wos = Pylon.WaitObjectsCreate();

                /* Open cameras and set parameter */
                deviceIndex = 0;
                for (uint enumeratedDeviceIndex = 0; enumeratedDeviceIndex < numDevicesEnumerated; ++enumeratedDeviceIndex)
                {
                    /* only open GigE devices */
                    PYLON_DEVICE_INFO_HANDLE hDI = Pylon.GetDeviceInfoHandle(enumeratedDeviceIndex);
                    if (Pylon.DeviceInfoGetPropertyValueByName(hDI, Pylon.cPylonDeviceInfoDeviceClassKey) != "BaslerGigE")
                    {
                        continue;
                    }

                    /* Get handles for the devices. */
                    hDev[deviceIndex] = Pylon.CreateDeviceByIndex((uint)enumeratedDeviceIndex);

                    /* Before using the device, it must be opened. Open it for configuring
                     * parameters and for grabbing images. */
                    Pylon.DeviceOpen(hDev[deviceIndex], Pylon.cPylonAccessModeControl | Pylon.cPylonAccessModeStream);

                    /* Print out the name of the camera we are using. */
                    Console.WriteLine("Using camera '{0}'", Pylon.DeviceInfoGetPropertyValueByName(hDI, Pylon.cPylonDeviceInfoModelNameKey));

                    isAvail = Pylon.DeviceFeatureIsReadable(hDev[deviceIndex], "ActionControl");
                    if (!isAvail)
                    {
                        throw new Exception("Device doesn't support the Action Command");
                    }

                    /* Configure the first action */
                    Pylon.DeviceSetIntegerFeature(hDev[deviceIndex], "ActionSelector", 1);
                    Pylon.DeviceSetIntegerFeature(hDev[deviceIndex], "ActionDeviceKey", DeviceKey);
                    Pylon.DeviceSetIntegerFeature(hDev[deviceIndex], "ActionGroupKey", GroupKey);
                    Pylon.DeviceSetIntegerFeature(hDev[deviceIndex], "ActionGroupMask", AllGroupMask);

                    /* Set the pixel format to Mono8, where gray values will be output as 8 bit values for each pixel. */
                    /* ... Check first to see if the device supports the Mono8 format. */
                    isAvail = Pylon.DeviceFeatureIsAvailable(hDev[deviceIndex], "EnumEntry_PixelFormat_Mono8");
                    if (!isAvail)
                    {
                        /* Feature is not available. */
                        throw new Exception("Device doesn't support the Mono8 pixel format.");
                    }

                    /* ... Set the pixel format to Mono8. */
                    Pylon.DeviceFeatureFromString(hDev[deviceIndex], "PixelFormat", "Mono8");


                    /* Disable acquisition start trigger if available */
                    isAvail = Pylon.DeviceFeatureIsAvailable(hDev[deviceIndex], "EnumEntry_TriggerSelector_AcquisitionStart");
                    if (isAvail)
                    {
                        Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerSelector", "AcquisitionStart");
                        Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerMode", "Off");
                    }
                    /* Disable line1 trigger if available */
                    isAvail = Pylon.DeviceFeatureIsAvailable(hDev[deviceIndex], "EnumEntry_TriggerSelector_Line1");
                    if (isAvail)
                    {
                        Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerSelector", "Line1");
                        Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerMode", "Off");
                    }

                    /* Enable frame start trigger with first action */
                    Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerSelector", "FrameStart");
                    Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerMode", "On");
                    Pylon.DeviceFeatureFromString(hDev[deviceIndex], "TriggerSource", "Action1");

                    /* For GigE cameras, we recommend increasing the packet size for better
                     *  performance. When the network adapter supports jumbo frames, set the packet
                     *  size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size
                     *  to 1500.
                     *
                     *  We also set the Inter-Packet and the Frame Transmission delay
                     *  so the switch can line up packets better.
                     */
                    Pylon.DeviceSetIntegerFeature(hDev[deviceIndex], "GevSCPSPacketSize", GIGE_PACKET_SIZE);
                    Pylon.DeviceSetIntegerFeature(hDev[deviceIndex], "GevSCPD", (GIGE_PACKET_SIZE + GIGE_PROTOCOL_OVERHEAD) * (MAX_NUM_DEVICES - 1));
                    Pylon.DeviceSetIntegerFeature(hDev[deviceIndex], "GevSCFTD", (GIGE_PACKET_SIZE + GIGE_PROTOCOL_OVERHEAD) * deviceIndex);

                    /* one device opened */
                    ++deviceIndex;
                }

                /* remember how many devices we have actually created */
                numDevicesToUse = deviceIndex;

                /* Remember the number of devices actually created */
                numDevicesToUse = deviceIndex;

                if (numDevicesToUse == 0)
                {
                    Console.Error.WriteLine("No suitable cameras found!");
                    Pylon.Terminate();  /* Releases all pylon resources. */
                    Console.Error.WriteLine("\nPress enter to exit.");
                    Console.ReadLine();
                    Environment.Exit(0);
                }

                if (numDevicesToUse < 2)
                {
                    Console.Error.WriteLine("WARNING: This sample works best with two or more GigE cameras supporting action commands.");
                }

                /* Allocate and register buffers for grab. */
                for (deviceIndex = 0; deviceIndex < numDevicesToUse; ++deviceIndex)
                {
                    /* Determine the required size for the grab buffer. */
                    payloadSize[deviceIndex] = checked ((uint)Pylon.DeviceGetIntegerFeature(hDev[deviceIndex], "PayloadSize"));

                    /* Image grabbing is done using a stream grabber.
                     * A device may be able to provide different streams. A separate stream grabber must
                     * be used for each stream. In this sample, we create a stream grabber for the default
                     * stream, i.e., the first stream ( index == 0 ).
                     */

                    /* Get the number of streams supported by the device and the transport layer. */
                    nStreams[deviceIndex] = Pylon.DeviceGetNumStreamGrabberChannels(hDev[deviceIndex]);

                    if (nStreams[deviceIndex] < 1)
                    {
                        throw new Exception("The transport layer doesn't support image streams.");
                    }

                    /* Create and open a stream grabber for the first channel. */
                    hGrabber[deviceIndex] = Pylon.DeviceGetStreamGrabber(hDev[deviceIndex], 0);

                    Pylon.StreamGrabberOpen(hGrabber[deviceIndex]);


                    /* Get a handle for the stream grabber's wait object. The wait object
                     * allows waiting for buffers to be filled with grabbed data. */
                    hWait[deviceIndex] = Pylon.StreamGrabberGetWaitObject(hGrabber[deviceIndex]);

                    /* Add the stream grabber's wait object to our wait objects.
                     * This is needed to be able to wait until all cameras have
                     * grabbed an image in our grab loop below. */
                    Pylon.WaitObjectsAdd(wos, hWait[deviceIndex]);

                    /* We must tell the stream grabber the number and size of the buffers
                     *  we are using. */
                    /* .. We will not use more than NUM_BUFFERS for grabbing. */
                    Pylon.StreamGrabberSetMaxNumBuffer(hGrabber[deviceIndex], NUM_BUFFERS);

                    /* .. We will not use buffers bigger than payloadSize bytes. */
                    Pylon.StreamGrabberSetMaxBufferSize(hGrabber[deviceIndex], payloadSize[deviceIndex]);

                    /*  Allocate the resources required for grabbing. After this, critical parameters
                    *   that impact the payload size must not be changed until FinishGrab() is called. */
                    Pylon.StreamGrabberPrepareGrab(hGrabber[deviceIndex]);

                    /* Before using the buffers for grabbing, they must be registered at
                     * the stream grabber. For each registered buffer, a buffer handle
                     * is returned. After registering, these handles are used instead of the
                     * buffer objects pointers. The buffer objects are held in a dictionary,
                     * that provides access to the buffer using a handle as key.
                     */
                    buffer[deviceIndex]  = new PylonBuffer <byte>(payloadSize[deviceIndex], true);
                    hBuffer[deviceIndex] = Pylon.StreamGrabberRegisterBuffer(hGrabber[deviceIndex], ref buffer[deviceIndex]);

                    /* Feed the buffers into the stream grabber's input queue. */
                    Pylon.StreamGrabberQueueBuffer(hGrabber[deviceIndex], hBuffer[deviceIndex], 0);
                }

                /* The stream grabber is now prepared. Start the image acquisition.
                 * The camera won't send any image data, since it's configured to wait
                 * for the action to trigger the acquisition */
                for (deviceIndex = 0; deviceIndex < numDevicesToUse; ++deviceIndex)
                {
                    Pylon.DeviceExecuteCommandFeature(hDev[deviceIndex], "AcquisitionStart");
                }


                /*  ======================================================================
                 *  Issue an ActionCommand and retrieve the images.
                 *  ====================================================================== */
                Console.WriteLine("*** Issuing action command ***");

                /* Trigger the camera using an action command (w/o waiting for results).
                 * If your setup support PTP, you could use a scheduled action command.
                 * Pylon.GigEIssueScheduledActionCommand(subnet, DefaultDeviceKey, DefaultGroupKey, 1, triggertime, 0)
                 */
                string subnet = Pylon.DeviceInfoGetPropertyValueByName(Pylon.DeviceGetDeviceInfoHandle(hDev[0]), "SubnetAddress");

                Pylon.GigEIssueActionCommand(DeviceKey, GroupKey, 1, subnet);

                /* Grab one image from each camera. */
                for (i = 0; i < numDevicesToUse; ++i)
                {
                    uint woIndex; /* this corresponds to the index in hDev and hGrabber */

                    /* Wait for the next buffer to be filled. Wait up to 5000 ms. */
                    isReady = Pylon.WaitObjectsWaitForAny(wos, 5000, out woIndex);

                    if (!isReady)
                    {   /* Timeout occurred */
                        /* Grab Timeout occurred. */
                        throw new Exception("Grab timeout occurred.");
                    }

                    PylonGrabResult_t grabResult;

                    /* Since the wait operation was successful, the result of at least one grab
                     * operation is available. Retrieve it. */
                    isReady = Pylon.StreamGrabberRetrieveResult(hGrabber[woIndex], out grabResult);

                    if (!isReady)
                    {
                        /* Oops. No grab result available? We should never have reached this point.
                         * Since the wait operation above returned without a timeout, a grab result
                         * should be available. */
                        throw new Exception("Failed to retrieve a grab result.");
                    }

                    /* Check to see if the image was grabbed successfully. */
                    if (grabResult.Status == EPylonGrabStatus.Grabbed)
                    {
                        /* Success. Perform image processing. Since we passed more than one buffer
                         * to the stream grabber, the remaining buffers are filled in the background while
                         * we do the image processing. The processed buffer won't be touched by
                         * the stream grabber until we pass it back to the stream grabber. */

                        /* We only use one buffer per camera */
                        System.Diagnostics.Debug.Assert(grabResult.hBuffer == hBuffer[woIndex]);

                        byte pixel = buffer[woIndex].Array[0];

                        /* Perform processing. */
                        Console.WriteLine("Grabbed a frame from camera {0}.", woIndex);

                        /* Display image */
                        if (woIndex < 32)
                        {
                            Pylon.ImageWindowDisplayImage <Byte>(woIndex, buffer[woIndex], grabResult);
                        }
                    }
                    else if (grabResult.Status == EPylonGrabStatus.Failed)
                    {
                        /* If a buffer has been incompletely grabbed the network bandwidth is possibly insufficient for transferring
                         * multiple images simultaneously. See note above MAX_NUM_DEVICES. */
                        Console.Error.WriteLine("Frame from camera {0} wasn't grabbed successfully.  Error code = {1}",
                                                woIndex, grabResult.ErrorCode);
                    }
                }

                /* Stop the image acquisition on the cameras. */
                for (deviceIndex = 0; deviceIndex < numDevicesToUse; ++deviceIndex)
                {
                    /*  Stop the camera. */
                    Pylon.DeviceExecuteCommandFeature(hDev[deviceIndex], "AcquisitionStop");
                }

                // Remove all wait objects from WaitObjects.
                Pylon.WaitObjectsRemoveAll(wos);
                Pylon.WaitObjectsDestroy(wos);

                for (deviceIndex = 0; deviceIndex < numDevicesToUse; ++deviceIndex)
                {
                    /* We must issue a cancel call to ensure that all pending buffers are put into the
                     * stream grabber's output queue. */
                    Pylon.StreamGrabberCancelGrab(hGrabber[deviceIndex]);

                    /* The buffers can now be retrieved from the stream grabber. */
                    do
                    {
                        PylonGrabResult_t grabResult;
                        isReady = Pylon.StreamGrabberRetrieveResult(hGrabber[deviceIndex], out grabResult);
                    } while (isReady);

                    /* When all buffers are retrieved from the stream grabber, they can be de-registered.
                     * After de-registering the buffers, it is safe to free the memory. */

                    Pylon.StreamGrabberDeregisterBuffer(hGrabber[deviceIndex], hBuffer[deviceIndex]);
                    buffer[deviceIndex].Dispose();
                    buffer[deviceIndex] = null;

                    /* Release grabbing related resources. */
                    Pylon.StreamGrabberFinishGrab(hGrabber[deviceIndex]);

                    /* After calling PylonStreamGrabberFinishGrab(), parameters that impact the payload size (e.g.,
                     * the AOI width and height parameters) are unlocked and can be modified again. */

                    /* Close the stream grabber. */
                    Pylon.StreamGrabberClose(hGrabber[deviceIndex]);

                    /* Close and release the pylon device. The stream grabber becomes invalid
                     * after closing the pylon device. Don't call stream grabber related methods after
                     * closing or releasing the device. */
                    Pylon.DeviceClose(hDev[deviceIndex]);
                    Pylon.DestroyDevice(hDev[deviceIndex]);
                }


                Console.Error.WriteLine("\nPress enter to exit.");
                Console.ReadLine();

                /* Shut down the pylon runtime system. Don't call any pylon function after
                 * calling PylonTerminate(). */
                Pylon.Terminate();
            }
            catch (Exception e)
            {
                /* Retrieve the error message. */
                string msg = GenApi.GetLastErrorMessage() + "\n" + GenApi.GetLastErrorDetail();
                Console.Error.WriteLine("Exception caught:");
                Console.Error.WriteLine(e.Message);
                if (msg != "\n")
                {
                    Console.Error.WriteLine("Last error message:");
                    Console.Error.WriteLine(msg);
                }

                for (uint deviceIndex = 0; deviceIndex < MAX_NUM_DEVICES; ++deviceIndex)
                {
                    try
                    {
                        if (hDev[deviceIndex].IsValid)
                        {
                            /* Close and release the pylon device. */
                            if (Pylon.DeviceIsOpen(hDev[deviceIndex]))
                            {
                                Pylon.DeviceClose(hDev[deviceIndex]);
                            }
                            Pylon.DestroyDevice(hDev[deviceIndex]);
                        }
                    }
                    catch (Exception)
                    {
                        /* No further handling here.*/
                    }
                }
                Pylon.Terminate();  /* Releases all pylon resources. */

                Console.Error.WriteLine("\nPress enter to exit.");
                Console.ReadLine();

                Environment.Exit(1);
            }
        }