diff --git a/FLIR/DavidsReadme.txt b/FLIR/DavidsReadme.txt new file mode 100644 index 0000000..f96a76e --- /dev/null +++ b/FLIR/DavidsReadme.txt @@ -0,0 +1,2 @@ +Since it was less than 100mb, I copied the entire python SDK here. You must have it locally installed to be able to run it from here! +The OneNote has instructions on how to install. Dont use their install guide! \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/AcquireAndDisplay.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/AcquireAndDisplay.py new file mode 100644 index 0000000..2aee556 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/AcquireAndDisplay.py @@ -0,0 +1,313 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# This AcquireAndDisplay.py shows how to get the image data, and then display images in a GUI. +# This example relies on information provided in the ImageChannelStatistics.py example. +# +# This example demonstrates how to display images represented as numpy arrays. +# Currently, this program is limited to single camera use. +# NOTE: keyboard and matplotlib must be installed on Python interpreter prior to running this example. + +import os +import PySpin +import matplotlib.pyplot as plt +import sys +import keyboard +import time + +global continue_recording +continue_recording = True + + +def handle_close(evt): + """ + This function will close the GUI when close event happens. + + :param evt: Event that occurs when the figure closes. + :type evt: Event + """ + + global continue_recording + continue_recording = False + + +def acquire_and_display_images(cam, nodemap, nodemap_tldevice): + """ + This function continuously acquires images from a device and display them in a GUI. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + global continue_recording + + sNodemap = cam.GetTLStreamNodeMap() + + # Change bufferhandling mode to NewestOnly + node_bufferhandling_mode = PySpin.CEnumerationPtr(sNodemap.GetNode('StreamBufferHandlingMode')) + if not PySpin.IsAvailable(node_bufferhandling_mode) or not PySpin.IsWritable(node_bufferhandling_mode): + print('Unable to set stream buffer handling mode.. Aborting...') + return False + + # Retrieve entry node from enumeration node + node_newestonly = node_bufferhandling_mode.GetEntryByName('NewestOnly') + if not PySpin.IsAvailable(node_newestonly) or not PySpin.IsReadable(node_newestonly): + print('Unable to set stream buffer handling mode.. Aborting...') + return False + + # Retrieve integer value from entry node + node_newestonly_mode = node_newestonly.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_bufferhandling_mode.SetIntValue(node_newestonly_mode) + + print('*** IMAGE ACQUISITION ***\n') + try: + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (enum retrieval). Aborting...') + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...') + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Begin acquiring images + # + # *** NOTES *** + # What happens when the camera begins acquiring images depends on the + # acquisition mode. Single frame captures only a single image, multi + # frame catures a set number of images, and continuous captures a + # continuous stream of images. + # + # *** LATER *** + # Image acquisition must be ended when no more images are needed. + cam.BeginAcquisition() + + print('Acquiring images...') + + # Retrieve device serial number for filename + # + # *** NOTES *** + # The device serial number is retrieved in order to keep cameras from + # overwriting one another. Grabbing image IDs could also accomplish + # this. + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Device serial number retrieved as %s...' % device_serial_number) + + # Close program + print('Press enter to close the program..') + + # Figure(1) is default so you can omit this line. Figure(0) will create a new window every time program hits this line + fig = plt.figure(1) + + # Close the GUI when close event happens + fig.canvas.mpl_connect('close_event', handle_close) + + # Retrieve and display images + while(continue_recording): + try: + + # Retrieve next received image + # + # *** NOTES *** + # Capturing an image houses images on the camera buffer. Trying + # to capture an image that does not exist will hang the camera. + # + # *** LATER *** + # Once an image from the buffer is saved and/or no longer + # needed, the image must be released in order to keep the + # buffer from filling up. + + image_result = cam.GetNextImage(1000) + + # Ensure image completion + if image_result.IsIncomplete(): + print('Image incomplete with image status %d ...' % image_result.GetImageStatus()) + + else: + + # Getting the image data as a numpy array + image_data = image_result.GetNDArray() + + # Draws an image on the current figure + plt.imshow(image_data, cmap='gray') + + # Interval in plt.pause(interval) determines how fast the images are displayed in a GUI + # Interval is in seconds. + plt.pause(0.001) + + # Clear current reference of a figure. This will improve display speed significantly + plt.clf() + + # If user presses enter, close the program + if keyboard.is_pressed('ENTER'): + print('Program is closing...') + + # Close figure + plt.close('all') + input('Done! Press Enter to exit...') + continue_recording=False + + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + # End acquisition + # + # *** NOTES *** + # Ending acquisition appropriately helps ensure that devices clean up + # properly and do not need to be power-cycled to maintain integrity. + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return True + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Acquire images + result &= acquire_and_display_images(cam, nodemap, nodemap_tldevice) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point; notice the volume of data that the logging event handler + prints out on debug despite the fact that very little really happens in this + example. Because of this, it may be better to have the logger set to lower + level in order to provide a more concise, focused log. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Acquisition.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Acquisition.py new file mode 100644 index 0000000..63b221e --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Acquisition.py @@ -0,0 +1,372 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Acquisition.py shows how to acquire images. It relies on +# information provided in the Enumeration example. Also, check out the +# ExceptionHandling and NodeMapInfo examples if you haven't already. +# ExceptionHandling shows the handling of standard and Spinnaker exceptions +# while NodeMapInfo explores retrieving information from various node types. +# +# This example touches on the preparation and cleanup of a camera just before +# and just after the acquisition of images. Image retrieval and conversion, +# grabbing image data, and saving images are all covered as well. +# +# Once comfortable with Acquisition, we suggest checking out +# AcquisitionMultipleCamera, NodeMapCallback, or SaveToAvi. +# AcquisitionMultipleCamera demonstrates simultaneously acquiring images from +# a number of cameras, NodeMapCallback serves as a good introduction to +# programming with callbacks and events, and SaveToAvi exhibits video creation. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '*** IMAGE ACQUISITION ***\n' + try: + result = True + + # Set acquisition mode to continuous + # + # *** NOTES *** + # Because the example acquires and saves 10 images, setting acquisition + # mode to continuous lets the example finish. If set to single frame + # or multiframe (at a lower number of images), the example would just + # hang. This would happen because the example has been written to + # acquire 10 images while the camera would have been programmed to + # retrieve less than that. + # + # Setting the value of an enumeration node is slightly more complicated + # than other node types. Two nodes must be retrieved: first, the + # enumeration node is retrieved from the nodemap; and second, the entry + # node is retrieved from the enumeration node. The integer value of the + # entry node is then set as the new value of the enumeration node. + # + # Notice that both the enumeration and the entry nodes are checked for + # availability and readability/writability. Enumeration nodes are + # generally readable and writable whereas their entry nodes are only + # ever readable. + # + # Retrieve enumeration node from nodemap + + # In order to access the node entries, they have to be casted to a pointer type (CEnumerationPtr here) + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (enum retrieval). Aborting...' + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable(node_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (entry retrieval). Aborting...' + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + # + # *** NOTES *** + # What happens when the camera begins acquiring images depends on the + # acquisition mode. Single frame captures only a single image, multi + # frame catures a set number of images, and continuous captures a + # continuous stream of images. Because the example calls for the + # retrieval of 10 images, continuous mode has been set. + # + # *** LATER *** + # Image acquisition must be ended when no more images are needed. + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Retrieve device serial number for filename + # + # *** NOTES *** + # The device serial number is retrieved in order to keep cameras from + # overwriting one another. Grabbing image IDs could also accomplish + # this. + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print 'Device serial number retrieved as %s...' % device_serial_number + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve next received image + # + # *** NOTES *** + # Capturing an image houses images on the camera buffer. Trying + # to capture an image that does not exist will hang the camera. + # + # *** LATER *** + # Once an image from the buffer is saved and/or no longer + # needed, the image must be released in order to keep the + # buffer from filling up. + image_result = cam.GetNextImage(1000) + + # Ensure image completion + # + # *** NOTES *** + # Images can easily be checked for completion. This should be + # done whenever a complete image is expected or required. + # Further, check image status for a little more insight into + # why an image is incomplete. + if image_result.IsIncomplete(): + print 'Image incomplete with image status %d ...' % image_result.GetImageStatus() + + else: + + # Print image information; height and width recorded in pixels + # + # *** NOTES *** + # Images have quite a bit of available metadata including + # things such as CRC, image status, and offset values, to + # name a few. + width = image_result.GetWidth() + height = image_result.GetHeight() + print 'Grabbed Image %d, width = %d, height = %d' % (i, width, height) + + # Convert image to mono 8 + # + # *** NOTES *** + # Images can be converted between pixel formats by using + # the appropriate enumeration value. Unlike the original + # image, the converted one does not need to be released as + # it does not affect the camera buffer. + # + # When converting images, color processing algorithm is an + # optional parameter. + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'Acquisition-%s-%d.jpg' % (device_serial_number, i) + else: # if serial number is empty + filename = 'Acquisition-%d.jpg' % i + + # Save image + # + # *** NOTES *** + # The standard practice of the examples is to use device + # serial numbers to keep images of one device from + # overwriting those of another. + image_converted.Save(filename) + print 'Image saved at %s' % filename + + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + print '' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + # End acquisition + # + # *** NOTES *** + # Ending acquisition appropriately helps ensure that devices clean up + # properly and do not need to be power-cycled to maintain integrity. + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print '*** DEVICE INFORMATION ***\n' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/AcquisitionMultipleCamera.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/AcquisitionMultipleCamera.py new file mode 100644 index 0000000..46bd430 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/AcquisitionMultipleCamera.py @@ -0,0 +1,333 @@ +# ============================================================================ +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. + +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================ +# +# AcquisitionMultipleCamera.py shows how to capture images from +# multiple cameras simultaneously. It relies on information provided in the +# Enumeration, Acquisition, and NodeMapInfo examples. +# +# This example reads similarly to the Acquisition example, +# except that loops are used to allow for simultaneous acquisitions. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + +def acquire_images(cam_list): + """ + This function acquires and saves 10 images from each device. + + :param cam_list: List of cameras + :type cam_list: CameraList + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** IMAGE ACQUISITION ***\n') + try: + result = True + + # Prepare each camera to acquire images + # + # *** NOTES *** + # For pseudo-simultaneous streaming, each camera is prepared as if it + # were just one, but in a loop. Notice that cameras are selected with + # an index. We demonstrate pseduo-simultaneous streaming because true + # simultaneous streaming would require multiple process or threads, + # which is too complex for an example. + # + + for i, cam in enumerate(cam_list): + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(cam.GetNodeMap().GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (node retrieval; camera %d). Aborting... \n' % i + return False + + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (entry \'continuous\' retrieval %d). \ + Aborting... \n' % i + return False + + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print'Camera %d acquisition mode set to continuous...' % i + + # Begin acquiring images + cam.BeginAcquisition() + + print'Camera %d started acquiring images...' % i + + print'' + + # Retrieve, convert, and save images for each camera + # + # *** NOTES *** + # In order to work with simultaneous camera streams, nested loops are + # needed. It is important that the inner loop be the one iterating + # through the cameras; otherwise, all images will be grabbed from a + # single camera before grabbing any images from another. + for n in range(NUM_IMAGES): + for i, cam in enumerate(cam_list): + try: + # Retrieve device serial number for filename + node_device_serial_number = PySpin.CStringPtr(cam.GetTLDeviceNodeMap().GetNode('DeviceSerialNumber')) + + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print'Camera %d serial number set to %s...' % (i, device_serial_number) + + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print'Image incomplete with image status %d ... \n' % image_result.GetImageStatus() + else: + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print'Camera %d grabbed image %d, width = %d, height = %d' % (i, n, width, height) + + # Convert image to mono 8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'AcquisitionMultipleCamera-%s-%d.jpg' % (device_serial_number, n) + else: + filename = 'AcquisitionMultipleCamera-%d-%d.jpg' % (i, n) + + # Save image + image_converted.Save(filename) + print'Image saved at %s' % filename + + # Release image + image_result.Release() + print'' + + except PySpin.SpinnakerException as ex: + print'Error: %s' % ex + result = False + + # End acquisition for each camera + # + # *** NOTES *** + # Notice that what is usually a one-step process is now two steps + # because of the additional step of selecting the camera. It is worth + # repeating that camera selection needs to be done once per loop. + # + # It is possible to interact with cameras through the camera list with + # GetByIndex(); this is an alternative to retrieving cameras as + # CameraPtr objects that can be quick and easy for small tasks. + for cam in cam_list: + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print'Error: %s' % ex + result = False + + return result + + +def print_device_info(nodemap, cam_num): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :param cam_num: Camera number. + :type nodemap: INodeMap + :type cam_num: int + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print'Printing device information for camera %d... \n' % cam_num + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print'%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print'Device control information not available.' + print'' + + except PySpin.SpinnakerException as ex: + print'Error: %s' % ex + return False + + return result + +def run_multiple_cameras(cam_list): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam_list: List of cameras + :type cam_list: CameraList + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve transport layer nodemaps and print device information for + # each camera + # *** NOTES *** + # This example retrieves information from the transport layer nodemap + # twice: once to print device information and once to grab the device + # serial number. Rather than caching the nodem#ap, each nodemap is + # retrieved both times as needed. + print'*** DEVICE INFORMATION ***\n' + + for i, cam in enumerate(cam_list): + + # Retrieve TL device nodemap + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + # Print device information + result &= print_device_info(nodemap_tldevice, i) + + # Initialize each camera + # + # *** NOTES *** + # You may notice that the steps in this function have more loops with + # less steps per loop; this contrasts the AcquireImages() function + # which has less loops but more steps per loop. This is done for + # demonstrative purposes as both work equally well. + # + # *** LATER *** + # Each camera needs to be deinitialized once all images have been + # acquired. + for i, cam in enumerate(cam_list): + + # Initialize camera + cam.Init() + + # Acquire images on all cameras + result &= acquire_images(cam_list) + + # Deinitialize each camera + # + # *** NOTES *** + # Again, each camera must be deinitialized separately by first + # selecting the camera and then deinitializing it. + for cam in cam_list: + + # Deinitialize camera + cam.DeInit() + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + except PySpin.SpinnakerException as ex: + print'Error: %s' % ex + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on all cameras + print'Running example for all cameras...' + + result = run_multiple_cameras(cam_list) + + print'Example complete... \n' + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/BufferHandling.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/BufferHandling.py new file mode 100644 index 0000000..a48b7da --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/BufferHandling.py @@ -0,0 +1,493 @@ +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= + +# BufferHandling.py shows how the different buffer handling modes work. +# It relies on information provided in the Acquisition and Trigger examples. +# +# Buffer handling determines the ordering at which images are retrieved, and +# what occurs when an image is transmitted while the buffer is full. There are +# four different buffer handling modes available; NewestFirst, NewestOnly, +# OldestFirst and OldestFirstOverwrite. +# +# This example explores retrieving images in a set pattern; triggering the camera +# while not retrieving an image (letting the buffer fill up), and retrieving +# images while not triggering. We cycle through the different buffer handling +# modes to see which images are retrieved, confirming their identites via their +# Frame ID values. + +import os +import PySpin +import time +import sys + +# Total number of buffers +NUM_BUFFERS = 3 +# Number of triggers +NUM_TRIGGERS = 6 +# Total number of loops +NUM_LOOPS = 9 + +def configure_trigger(nodemap): + """ + This function configures the camera to use a trigger. First, trigger mode is + set to off in order to select the trigger source. Once the trigger source + has been selected, trigger mode is then enabled, which has the camera + capture only a single image upon the execution of the trigger. + + :param nodemap: Device nodemap to retrieve images from. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + try: + result = True + print '\n*** CONFIGURING TRIGGER ***\n' + + # Ensure trigger mode off + # + # *** NOTES *** + # The trigger must be disabled in order to configure the + # trigger source. + trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(trigger_mode) or not PySpin.IsWritable(trigger_mode): + print 'Unable to disable trigger mode (node retrieval). Aborting...\n' + return False + + trigger_mode_off = PySpin.CEnumEntryPtr(trigger_mode.GetEntryByName('Off')) + if not PySpin.IsAvailable(trigger_mode_off) or not PySpin.IsReadable(trigger_mode_off): + print 'Unable to disable trigger mode (enum entry retrieval). Aborting...\n' + return False + + trigger_mode.SetIntValue(trigger_mode_off.GetValue()) + print 'Trigger mode disabled...' + + # Set trigger source to software + trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerSource')) + if not PySpin.IsAvailable(trigger_source) or not PySpin.IsWritable(trigger_source): + print 'Unable to set trigger mode (node retrieval). Aborting...' + return False + + trigger_source_software = PySpin.CEnumEntryPtr(trigger_source.GetEntryByName('Software')) + if not PySpin.IsAvailable(trigger_source_software) or not PySpin.IsReadable(trigger_source_software): + print 'Unable to set trigger mode (enum entry retrieval). Aborting...' + return False + + trigger_source.SetIntValue(trigger_source_software.GetValue()) + print 'Trigger source set to software...' + + # Turn trigger mode on + trigger_mode_on = PySpin.CEnumEntryPtr(trigger_mode.GetEntryByName('On')) + if not PySpin.IsAvailable(trigger_mode_on) or not PySpin.IsReadable(trigger_mode_on): + print 'Unable to enable trigger mode (enum entry retrieval). Aborting...\n' + return False + + trigger_mode.SetIntValue(trigger_mode_on.GetValue()) + print 'Trigger mode turned back on...' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + +def grab_next_image_by_trigger(nodemap): + """ + This function retrieves a single image using the trigger. In this example, + only a single image is captured and made available for acquisition - as such, + attempting to acquire two images for a single trigger execution would cause + the example to hang. This is different from other examples, whereby a + constant stream of images are being captured and made available for image + acquisition. + + :param nodemap: Device nodemap to retrieve images from. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + try: + result = True + + # Execute software trigger + software_trigger_command = PySpin.CCommandPtr(nodemap.GetNode('TriggerSoftware')) + if not PySpin.IsAvailable(software_trigger_command) or not PySpin.IsWritable(software_trigger_command): + print 'Unable to execute trigger. Aborting...\n' + return False + + software_trigger_command.Execute() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + +def reset_trigger(nodemap): + """ + This function returns the camera to a normal state by turning off trigger mode. + + :param nodemap: Device nodemap to retrieve images from. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + try: + result = True + + # Turn trigger mode back off + # + # *** NOTES *** + # Once all images have been captured, turn trigger mode back off to + # restore the camera to a clean state. + trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(trigger_mode) or not PySpin.IsWritable(trigger_mode): + print 'Unable to disable trigger mode (node retrieval). Non-fatal error...\n' + return False + + trigger_mode_off = PySpin.CEnumEntryPtr(trigger_mode.GetEntryByName('Off')) + if not PySpin.IsAvailable(trigger_mode_off) or not PySpin.IsReadable(trigger_mode_off): + print 'Unable to disable trigger mode (enum entry retrieval). Non-fatal error...\n' + return False + + trigger_mode.SetIntValue(trigger_mode_off.GetValue()) + print 'Trigger mode disabled...\n' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap from camera. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + print('\n*** DEVICE INFORMATION ***\n') + + # Retrieve and display Device Information + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print'%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function cycles through the four different buffer handling modes. + It saves three images for three of the buffer handling modes + (NewestFirst, OldestFirst, and OldestFirstOverwrite). For NewestOnly, + it saves one image. + + :param cam: Camera instance to grab images from. + :param nodemap: Device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + print '\n*** IMAGE ACQUISITION ***\n' + + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (node retrieval). Aborting...' + return False + + # Retrieve entry node from enumeration mode + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (entry retrieval). Aborting...' + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print 'Acquisition mode set to continuous...' + + # Retrieve device serial number for filename + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print 'Device serial number retrieved as %s...' % device_serial_number + + # Retrieve Stream Parameters device nodemap + s_node_map = cam.GetTLStreamNodeMap() + + # Retrieve Buffer Handling Mode Information + handling_mode = PySpin.CEnumerationPtr(s_node_map.GetNode('StreamBufferHandlingMode')) + if not PySpin.IsAvailable(handling_mode) or not PySpin.IsWritable(handling_mode): + print 'Unable to set Buffer Handling mode (node retrieval). Aborting...\n' + return False + + handling_mode_entry = PySpin.CEnumEntryPtr(handling_mode.GetCurrentEntry()) + if not PySpin.IsAvailable(handling_mode_entry) or not PySpin.IsReadable(handling_mode_entry): + print 'Unable to set Buffer Handling mode (Entry retrieval). Aborting...\n' + return False + + # Set stream buffer Count Mode to manual + stream_buffer_count_mode = PySpin.CEnumerationPtr(s_node_map.GetNode('StreamBufferCountMode')) + if not PySpin.IsAvailable(stream_buffer_count_mode) or not PySpin.IsWritable(stream_buffer_count_mode): + print 'Unable to set Buffer Count Mode (node retrieval). Aborting...\n' + return False + + stream_buffer_count_mode_manual = PySpin.CEnumEntryPtr(stream_buffer_count_mode.GetEntryByName('Manual')) + if not PySpin.IsAvailable(stream_buffer_count_mode_manual) or not PySpin.IsReadable(stream_buffer_count_mode_manual): + print 'Unable to set Buffer Count Mode entry (Entry retrieval). Aborting...\n' + return False + + stream_buffer_count_mode.SetIntValue(stream_buffer_count_mode_manual.GetValue()) + print 'Stream Buffer Count Mode set to manual...' + + # Retrieve and modify Stream Buffer Count + buffer_count = PySpin.CIntegerPtr(s_node_map.GetNode('StreamBufferCountManual')) + if not PySpin.IsAvailable(buffer_count) or not PySpin.IsWritable(buffer_count): + print 'Unable to set Buffer Count (Integer node retrieval). Aborting...\n' + return False + + # Display Buffer Info + print '\nDefault Buffer Handling Mode: %s' % handling_mode_entry.GetDisplayName() + print 'Default Buffer Count: %d' % buffer_count.GetValue() + print 'Maximum Buffer Count: %d' % buffer_count.GetMax() + + buffer_count.SetValue(NUM_BUFFERS) + + print 'Buffer count now set to: %d' % buffer_count.GetValue() + print '\nCamera will be triggered %d times in a row before %d images will be retrieved' % (NUM_TRIGGERS,(NUM_LOOPS-NUM_TRIGGERS)) + + for x in range (0, 4): + if x == 0: + handling_mode_entry = handling_mode.GetEntryByName('NewestFirst') + handling_mode.SetIntValue(handling_mode_entry.GetValue()) + print '\n\nBuffer Handling Mode has been set to %s' % handling_mode_entry.GetDisplayName() + elif x == 1: + handling_mode_entry = handling_mode.GetEntryByName('NewestOnly') + handling_mode.SetIntValue(handling_mode_entry.GetValue()) + print '\n\nBuffer Handling Mode has been set to %s' % handling_mode_entry.GetDisplayName() + elif x == 2: + handling_mode_entry = handling_mode.GetEntryByName('OldestFirst') + handling_mode.SetIntValue(handling_mode_entry.GetValue()) + print '\n\nBuffer Handling Mode has been set to %s' % handling_mode_entry.GetDisplayName() + elif x == 3: + handling_mode_entry = handling_mode.GetEntryByName('OldestFirstOverwrite') + handling_mode.SetIntValue(handling_mode_entry.GetValue()) + print '\n\nBuffer Handling Mode has been set to %s' % handling_mode_entry.GetDisplayName() + + # Begin capturing images + cam.BeginAcquisition() + + # Sleep for one second; only necessary when using non-BFS/ORX cameras on startup + if x == 0: + time.sleep(1) + + try: + # Software Trigger the camera then save images + for loop_cnt in range (0, NUM_LOOPS): + if loop_cnt < NUM_TRIGGERS: + # Retrieve the next image from the trigger + result &= grab_next_image_by_trigger(nodemap) + print '\nCamera triggered. No image grabbed' + else: + print '\nNo trigger. Grabbing image %d' %(loop_cnt-NUM_TRIGGERS) + result_image = cam.GetNextImage(500) + + if result_image.IsIncomplete(): + print 'Image incomplete with image status %s ...\n' % result_image.GetImageStatus() + + if loop_cnt >= NUM_TRIGGERS: + # Retrieve Frame ID + print 'Frame ID: %d' % result_image.GetFrameID() + + # Create a unique filename + if device_serial_number: + filename = '%s-%s-%d.jpg' % (handling_mode_entry.GetSymbolic(),device_serial_number, (loop_cnt-NUM_TRIGGERS)) + else: + filename = '%s-%d.jpg' % (handling_mode_entry.GetSymbolic(),(loop_cnt-NUM_TRIGGERS)) + + # Save image + result_image.Save(filename) + print 'Image saved at %s' % filename + + # Release image + result_image.Release() + + # To control the framerate, have the application pause for 250ms. + time.sleep(0.25) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + if handling_mode_entry.GetSymbolic() == 'NewestOnly': + print 'Error should occur when grabbing image 1 with handling mode set to NewestOnly' + result = False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure chunk data + if configure_trigger(nodemap) is False: + return False + + # Acquire images and display chunk data + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Reset trigger + result &= reset_trigger(nodemap) + + # De-initialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + print '\n\nRunning example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) + + + diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ChunkData.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ChunkData.py new file mode 100644 index 0000000..1e2a3d5 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ChunkData.py @@ -0,0 +1,673 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# ChunkData.py shows how to get chunk data on an image, either from +# the nodemap or from the image itself. It relies on information provided in +# the Enumeration, Acquisition, and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the ImageFormatControl +# and Exposure samples. As they are somewhat shorter and simpler, either +# provides a strong introduction to camera customization. +# +# Chunk data provides information on various traits of an image. This includes +# identifiers such as frame ID, properties such as black level, and more. This +# information can be acquired from either the nodemap or the image itself. +# +# It may be preferable to grab chunk data from each individual image, as it +# can be hard to verify whether data is coming from the correct image when +# using the nodemap. This is because chunk data retrieved from the nodemap is +# only valid for the current image; when GetNextImage() is called, chunk data +# will be updated to that of the new current image. +# + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +# Use the following class and global variable to select whether +# chunk data is displayed from the image or the nodemap. +class ChunkDataTypes: + IMAGE = 1 + NODEMAP = 2 + + +CHOSEN_CHUNK_DATA_TYPE = ChunkDataTypes.NODEMAP + + +def configure_chunk_data(nodemap): + """ + This function configures the camera to add chunk data to each image. It does + this by enabling each type of chunk data before enabling chunk data mode. + When chunk data is turned on, the data is made available in both the nodemap + and each image. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + try: + result = True + print '\n*** CONFIGURING CHUNK DATA ***\n' + + # Activate chunk mode + # + # *** NOTES *** + # Once enabled, chunk data will be available at the end of the payload + # of every image captured until it is disabled. Chunk data can also be + # retrieved from the nodemap. + chunk_mode_active = PySpin.CBooleanPtr(nodemap.GetNode('ChunkModeActive')) + + if PySpin.IsAvailable(chunk_mode_active) and PySpin.IsWritable(chunk_mode_active): + chunk_mode_active.SetValue(True) + + print 'Chunk mode activated...' + + # Enable all types of chunk data + # + # *** NOTES *** + # Enabling chunk data requires working with nodes: "ChunkSelector" + # is an enumeration selector node and "ChunkEnable" is a boolean. It + # requires retrieving the selector node (which is of enumeration node + # type), selecting the entry of the chunk data to be enabled, retrieving + # the corresponding boolean, and setting it to be true. + # + # In this example, all chunk data is enabled, so these steps are + # performed in a loop. Once this is complete, chunk mode still needs to + # be activated. + chunk_selector = PySpin.CEnumerationPtr(nodemap.GetNode('ChunkSelector')) + + if not PySpin.IsAvailable(chunk_selector) or not PySpin.IsReadable(chunk_selector): + print 'Unable to retrieve chunk selector. Aborting...\n' + return False + + # Retrieve entries + # + # *** NOTES *** + # PySpin handles mass entry retrieval in a different way than the C++ + # API. Instead of taking in a NodeList_t reference, GetEntries() takes + # no parameters and gives us a list of INodes. Since we want these INodes + # to be of type CEnumEntryPtr, we can use a list comprehension to + # transform all of our collected INodes into CEnumEntryPtrs at once. + entries = [PySpin.CEnumEntryPtr(chunk_selector_entry) for chunk_selector_entry in chunk_selector.GetEntries()] + + print 'Enabling entries...' + + # Iterate through our list and select each entry node to enable + for chunk_selector_entry in entries: + # Go to next node if problem occurs + if not PySpin.IsAvailable(chunk_selector_entry) or not PySpin.IsReadable(chunk_selector_entry): + continue + + chunk_selector.SetIntValue(chunk_selector_entry.GetValue()) + + chunk_symbolic_form = '\t {}:'.format(chunk_selector_entry.GetSymbolic()) + + # Retrieve corresponding boolean + chunk_enable = PySpin.CBooleanPtr(nodemap.GetNode('ChunkEnable')) + + # Enable the boolean, thus enabling the corresponding chunk data + if not PySpin.IsAvailable(chunk_enable): + print '{} not available'.format(chunk_symbolic_form) + result = False + elif chunk_enable.GetValue() is True: + print '{} enabled'.format(chunk_symbolic_form) + elif PySpin.IsWritable(chunk_enable): + chunk_enable.SetValue(True) + print '{} enabled'.format(chunk_symbolic_form) + else: + print '{} not writable'.format(chunk_symbolic_form) + result = False + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def display_chunk_data_from_nodemap(nodemap): + """ + This function displays all available chunk data by looping through the + chunk data category node on the nodemap. + + :param nodemap: Device nodemap to retrieve images from. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + print 'Printing chunk data from nodemap...' + try: + result = True + # Retrieve chunk data information nodes + # + # *** NOTES *** + # As well as being written into the payload of the image, chunk data is + # accessible on the GenICam nodemap. When chunk data is enabled, it is + # made available from both the image payload and the nodemap. + chunk_data_control = PySpin.CCategoryPtr(nodemap.GetNode('ChunkDataControl')) + if not PySpin.IsAvailable(chunk_data_control) or not PySpin.IsReadable(chunk_data_control): + print 'Unable to retrieve chunk data control. Aborting...\n' + return False + + features = chunk_data_control.GetFeatures() + + # Iterate through children + for feature in features: + feature_node = PySpin.CNodePtr(feature) + feature_display_name = '\t{}:'.format(feature_node.GetDisplayName()) + + if not PySpin.IsAvailable(feature_node) or not PySpin.IsReadable(feature_node): + print '{} node not available'.format(feature_display_name) + result &= False + continue + # Print node type value + # + # *** NOTES *** + # All nodes can be cast as value nodes and have their information + # retrieved as a string using the ToString() method. This is much + # easier than dealing with each individual node type. + else: + feature_value = PySpin.CValuePtr(feature) + print '{} {}'.format(feature_display_name, feature_value.ToString()) + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def display_chunk_data_from_image(image): + """ + This function displays a select amount of chunk data from the image. Unlike + accessing chunk data via the nodemap, there is no way to loop through all + available data. + + :param image: Image to acquire chunk data from + :type image: ImagePtr + :return: True if successful, False otherwise. + :rtype: bool + """ + print 'Printing chunk data from image...' + try: + result = True + # Retrieve chunk data from image + # + # *** NOTES *** + # When retrieving chunk data from an image, the data is stored in a + # ChunkData object and accessed with getter functions. + chunk_data = image.GetChunkData() + + # Retrieve exposure time (recorded in microseconds) + exposure_time = chunk_data.GetExposureTime() + print '\tExposure time: {}'.format(exposure_time) + + # Retrieve frame ID + frame_id = chunk_data.GetFrameID() + print '\tFrame ID: {}'.format(frame_id) + + # Retrieve gain; gain recorded in decibels + gain = chunk_data.GetGain() + print '\tGain: {}'.format(gain) + + # Retrieve height; height recorded in pixels + height = chunk_data.GetHeight() + print '\tHeight: {}'.format(height) + + # Retrieve offset X; offset X recorded in pixels + offset_x = chunk_data.GetOffsetX() + print '\tOffset X: {}'.format(offset_x) + + # Retrieve offset Y; offset Y recorded in pixels + offset_y = chunk_data.GetOffsetY() + print '\tOffset Y: {}'.format(offset_y) + + # Retrieve sequencer set active + sequencer_set_active = chunk_data.GetSequencerSetActive() + print '\tSequencer set active: {}'.format(sequencer_set_active) + + # Retrieve timestamp + timestamp = chunk_data.GetTimestamp() + print '\tTimestamp: {}'.format(timestamp) + + # Retrieve width; width recorded in pixels + width = chunk_data.GetWidth() + print '\tWidth: {}'.format(width) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '\n*** DEVICE INFORMATION ***\n' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + else: + print 'Device control information not available.' + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print '\n*** IMAGE ACQUISITION ***\n' + + try: + result = True + # Set acquisition mode to continuous + # + # *** NOTES *** + # Because the example acquires and saves 10 images, setting acquisition + # mode to continuous lets the example finish. If set to single frame + # or multiframe (at a lower number of images), the example would just + # hang. This would happen because the example has been written to + # acquire 10 images while the camera would have been programmed to + # retrieve less than that. + # + # Setting the value of an enumeration node is slightly more complicated + # than other node types. Two nodes must be retrieved: first, the + # enumeration node is retrieved from the nodemap; and second, the entry + # node is retrieved from the enumeration node. The integer value of the + # entry node is then set as the new value of the enumeration node. + # + # Notice that both the enumeration and the entry nodes are checked for + # availability and readability/writability. Enumeration nodes are + # generally readable and writable whereas their entry nodes are only + # ever readable. + # + # Retrieve enumeration node from nodemap + + # In order to access the node entries, they have to be casted to a pointer type (CEnumerationPtr here) + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (node retrieval). Aborting...' + return False + + # Retrieve entry node from enumeration mode + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable(node_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (entry retrieval). Aborting...' + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + # + # *** NOTES *** + # What happens when the camera begins acquiring images depends on the + # acquisition mode. Single frame captures only a single image, multi + # frame captures a set number of images, and continuous captures a + # continuous stream of images. As the example calls for the + # retrieval of 10 images, continuous mode has been set. + # + # *** LATER *** + # Image acquisition must be ended when no more images are needed. + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Retrieve device serial number for filename + # + # *** NOTES *** + # The device serial number is retrieved in order to keep cameras from + # overwriting one another. Grabbing image IDs could also accomplish + # this. + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print 'Device serial number retrieved as %s...' % device_serial_number + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + # Retrieve next received image + # + # *** NOTES *** + # Capturing an image houses images on the camera buffer. Trying + # to capture an image that does not exist will hang the camera. + # + # *** LATER *** + # Once an image from the buffer is saved and/or no longer + # needed, the image must be released in order to keep the + # buffer from filling up. + image_result = cam.GetNextImage(1000) + + # Ensure image completion + # + # *** NOTES *** + # Images can be easily checked for completion. This should be + # done whenever a complete image is expected or required. + # Further, check image status for a little more insight into + # why an image is incomplete. + if image_result.IsIncomplete(): + print 'Image incomplete with image status %d ...' % image_result.GetImageStatus() + else: + + # Print image information + # + # *** NOTES *** + # Images have quite a bit of available metadata including + # things such as CRC, image status, and offset values, to + # name a few. + width = image_result.GetWidth() + height = image_result.GetHeight() + print 'Grabbed Image %d, width = %d, height = %d' % (i, width, height) + + # Convert image to mono 8 + # + # *** NOTES *** + # Images can be converted between pixel formats by using + # the appropriate enumeration value. Unlike the original + # image, the converted one does not need to be released as + # it does not affect the camera buffer. + # + # When converting images, color processing algorithm is an + # optional parameter. + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'ChunkData-%s-%d.jpg' % (device_serial_number, i) + else: + filename = 'ChunkData-%d.jpg' % i + + # Save image + # + # *** NOTES *** + # The standard practice of the examples is to use device + # serial numbers to keep images of one device from + # overwriting those of another. + image_converted.Save(filename) + print 'Image saved at %s' % filename + + # Display chunk data + + if CHOSEN_CHUNK_DATA_TYPE == ChunkDataTypes.IMAGE: + result &= display_chunk_data_from_image(image_result) + elif CHOSEN_CHUNK_DATA_TYPE == ChunkDataTypes.NODEMAP: + result &= display_chunk_data_from_nodemap(nodemap) + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + print '' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + # End acquisition + # + # *** NOTES *** + # Ending acquisition appropriately helps ensure that devices clean up + # properly and do not need to be power-cycled to maintain integrity. + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def disable_chunk_data(nodemap): + """ + This function disables each type of chunk data before disabling chunk data mode. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + try: + result = True + + # Retrieve the selector node + chunk_selector = PySpin.CEnumerationPtr(nodemap.GetNode('ChunkSelector')) + + if not PySpin.IsAvailable(chunk_selector) or not PySpin.IsReadable(chunk_selector): + print 'Unable to retrieve chunk selector. Aborting...\n' + return False + + # Retrieve entries + # + # *** NOTES *** + # PySpin handles mass entry retrieval in a different way than the C++ + # API. Instead of taking in a NodeList_t reference, GetEntries() takes + # no parameters and gives us a list of INodes. Since we want these INodes + # to be of type CEnumEntryPtr, we can use a list comprehension to + # transform all of our collected INodes into CEnumEntryPtrs at once. + entries = [PySpin.CEnumEntryPtr(chunk_selector_entry) for chunk_selector_entry in chunk_selector.GetEntries()] + + print 'Disabling entries...' + + for chunk_selector_entry in entries: + # Go to next node if problem occurs + if not PySpin.IsAvailable(chunk_selector_entry) or not PySpin.IsReadable(chunk_selector_entry): + continue + + chunk_selector.SetIntValue(chunk_selector_entry.GetValue()) + + chunk_symbolic_form = '\t {}:'.format(chunk_selector_entry.GetSymbolic()) + + # Retrieve corresponding boolean + chunk_enable = PySpin.CBooleanPtr(nodemap.GetNode('ChunkEnable')) + + # Disable the boolean, thus disabling the corresponding chunk data + if not PySpin.IsAvailable(chunk_enable): + print '{} not available'.format(chunk_symbolic_form) + result = False + elif not chunk_enable.GetValue(): + print '{} disabled'.format(chunk_symbolic_form) + elif PySpin.IsWritable(chunk_enable): + chunk_enable.SetValue(False) + print '{} disabled'.format(chunk_symbolic_form) + else: + print '{} not writable'.format(chunk_symbolic_form) + + # Deactivate Chunk Mode + chunk_mode_active = PySpin.CBooleanPtr(nodemap.GetNode('ChunkModeActive')) + + if not PySpin.IsAvailable(chunk_mode_active) or not PySpin.IsWritable(chunk_mode_active): + print 'Unable to deactivate chunk mode. Aborting...\n' + return False + + chunk_mode_active.SetValue(False) + + print('Chunk mode deactivated...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure chunk data + if configure_chunk_data(nodemap) is False: + return False + + # Acquire images and display chunk data + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Disable chunk data + if disable_chunk_data(nodemap) is False: + return False + + # De-initialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/CounterAndTimer.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/CounterAndTimer.py new file mode 100644 index 0000000..875ddbb --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/CounterAndTimer.py @@ -0,0 +1,669 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# CounterAndTimer.py shows how to setup a Pulse Width Modulation (PWM) +# signal using counters and timers. The camera will output the PWM signal via +# strobe, and capture images at a rate defined by the PWM signal as well. +# Users should take care to use a PWM signal within the camera's max +# frame rate (by default, the PWM signal is set to 50 Hz). +# +# Counter and Timer functionality is only available for BFS and Oryx Cameras. +# For details on the hardware setup, see our kb article, "Using Counter and +# Timer Control"; https://www.flir.com/support-center/iis/machine-vision/application-note/using-counter-and-timer-control + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '*** DEVICE INFORMATION ***\n' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + feature_string = node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable' + print '{}: {}'.format(node_feature.GetName(), feature_string) + + else: + print 'Device control information not available.' + + print '' + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + return False + + return result + + +def setup_counter_and_timer(nodemap): + """ + This function configures the camera to setup a Pulse Width Modulation signal using + Counter and Timer functionality. By default, the PWM signal will be set to run at + 50hz, with a duty cycle of 70%. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print 'Configuring Pulse Width Modulation signal' + + try: + result = True + + # Set Counter Selector to Counter 0 + node_counter_selector = PySpin.CEnumerationPtr(nodemap.GetNode('CounterSelector')) + + # Check to see if camera supports Counter and Timer functionality + if not PySpin.IsAvailable(node_counter_selector): + print '\nCamera does not support Counter and Timer Functionality. Aborting...\n' + return False + + if not PySpin.IsWritable(node_counter_selector): + print '\nUnable to set Counter Selector (enumeration retrieval). Aborting...\n' + return False + + entry_counter_0 = node_counter_selector.GetEntryByName('Counter0') + if not PySpin.IsAvailable(entry_counter_0) or not PySpin.IsReadable(entry_counter_0): + print '\nUnable to set Counter Selector (entry retrieval). Aborting...\n' + return False + + counter_0 = entry_counter_0.GetValue() + + node_counter_selector.SetIntValue(counter_0) + + # Set Counter Event Source to MHzTick + node_counter_event_source = PySpin.CEnumerationPtr(nodemap.GetNode('CounterEventSource')) + if not PySpin.IsAvailable(node_counter_event_source) or not PySpin.IsWritable(node_counter_event_source): + print '\nUnable to set Counter Event Source (enumeration retrieval). Aborting...\n' + return False + + entry_counter_event_source_mhz_tick = node_counter_event_source.GetEntryByName('MHzTick') + if not PySpin.IsAvailable(entry_counter_event_source_mhz_tick) \ + or not PySpin.IsReadable(entry_counter_event_source_mhz_tick): + print '\nUnable to set Counter Event Source (entry retrieval). Aborting...\n' + return False + + counter_event_source_mhz_tick = entry_counter_event_source_mhz_tick.GetValue() + + node_counter_event_source.SetIntValue(counter_event_source_mhz_tick) + + # Set Counter Duration to 14000 + node_counter_duration = PySpin.CIntegerPtr(nodemap.GetNode('CounterDuration')) + if not PySpin.IsAvailable(node_counter_duration) or not PySpin.IsWritable(node_counter_duration): + print '\nUnable to set Counter Duration (integer retrieval). Aborting...\n' + return False + + node_counter_duration.SetValue(14000) + + # Set Counter Delay to 6000 + node_counter_delay = PySpin.CIntegerPtr(nodemap.GetNode('CounterDelay')) + if not PySpin.IsAvailable(node_counter_delay) or not PySpin.IsWritable(node_counter_delay): + print '\nUnable to set Counter Delay (integer retrieval). Aborting...\n' + return False + + node_counter_delay.SetValue(6000) + + # Determine Duty Cycle of PWM signal + duty_cycle = float(node_counter_duration.GetValue()) / (float(node_counter_duration.GetValue() + + node_counter_delay.GetValue())) * 100 + + print '\nThe duty cycle has been set to {}%'.format(duty_cycle) + + # Determine pulse rate of PWM signal + pulse_rate = 1000000 / float(node_counter_duration.GetValue() + node_counter_delay.GetValue()) + + print '\nThe pulse rate has been set to {} Hz'.format(pulse_rate) + + # Set Counter Trigger Source to Frame Trigger Wait + node_counter_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode('CounterTriggerSource')) + if not PySpin.IsAvailable(node_counter_trigger_source) or not PySpin.IsWritable(node_counter_trigger_source): + print '\nUnable to set Counter Trigger Source (enumeration retrieval). Aborting...\n' + return False + + entry_counter_trigger_source_ftw = node_counter_trigger_source.GetEntryByName('FrameTriggerWait') + if not PySpin.IsAvailable(entry_counter_trigger_source_ftw)\ + or not PySpin.IsReadable(entry_counter_trigger_source_ftw): + print '\nUnable to set Counter Trigger Source (entry retrieval). Aborting...\n' + return False + + counter_trigger_source_ftw = entry_counter_trigger_source_ftw.GetValue() + + node_counter_trigger_source.SetIntValue(counter_trigger_source_ftw) + + # Set Counter Trigger Activation to Level High + node_counter_trigger_activation = PySpin.CEnumerationPtr(nodemap.GetNode('CounterTriggerActivation')) + if not PySpin.IsAvailable(node_counter_trigger_activation) or \ + not PySpin.IsWritable(node_counter_trigger_activation): + print '\nUnable to set Counter Trigger Activation (enumeration retrieval). Aborting...\n' + return False + + entry_counter_trigger_source_lh = node_counter_trigger_activation.GetEntryByName('LevelHigh') + if not PySpin.IsAvailable(entry_counter_trigger_source_lh) \ + or not PySpin.IsReadable(entry_counter_trigger_source_lh): + print '\nUnable to set Counter Trigger Activation (entry retrieval). Aborting...\n' + return False + + counter_trigger_level_high = entry_counter_trigger_source_lh.GetValue() + + node_counter_trigger_activation.SetIntValue(counter_trigger_level_high) + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + return False + + return result + + +def configure_digital_io(nodemap): + """ + This function configures the GPIO to output the PWM signal. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '\nConfiguring GPIO strobe output' + + try: + result = True + camera_family_bfs = "BFS" + camera_family_oryx = "ORX" + + # Determine camera family + node_device_name = PySpin.CStringPtr(nodemap.GetNode('DeviceModelName')) + if not PySpin.IsAvailable(node_device_name) or not PySpin.IsReadable(node_device_name): + print '\nUnable to determine camera family. Aborting...\n' + return False + + camera_model = node_device_name.GetValue() + + # Set Line Selector + node_line_selector = PySpin.CEnumerationPtr(nodemap.GetNode('LineSelector')) + if not PySpin.IsAvailable(node_line_selector) or not PySpin.IsWritable(node_line_selector): + print '\nUnable to set Line Selector (enumeration retrieval). Aborting...\n' + return False + + if camera_family_bfs in camera_model: + + entry_line_selector_line_1 = node_line_selector.GetEntryByName('Line1') + if not PySpin.IsAvailable(entry_line_selector_line_1) or not PySpin.IsReadable(entry_line_selector_line_1): + print '\nUnable to set Line Selector (entry retrieval). Aborting...\n' + return False + + line_selector_line_1 = entry_line_selector_line_1.GetValue() + + node_line_selector.SetIntValue(line_selector_line_1) + + elif camera_family_oryx in camera_model: + + entry_line_selector_line_2 = node_line_selector.GetEntryByName('Line2') + if not PySpin.IsAvailable(entry_line_selector_line_2) or not PySpin.IsReadable(entry_line_selector_line_2): + print '\nUnable to set Line Selector (entry retrieval). Aborting...\n' + return False + + line_selector_line_2 = entry_line_selector_line_2.GetValue() + + node_line_selector.SetIntValue(line_selector_line_2) + + # Set Line Mode to output + node_line_mode = PySpin.CEnumerationPtr(nodemap.GetNode('LineMode')) + if not PySpin.IsAvailable(node_line_mode) or not PySpin.IsWritable(node_line_mode): + print '\nUnable to set Line Mode (enumeration retrieval). Aborting...\n' + return False + + entry_line_mode_output = node_line_mode.GetEntryByName('Output') + if not PySpin.IsAvailable(entry_line_mode_output) or not PySpin.IsReadable(entry_line_mode_output): + print '\nUnable to set Line Mode (entry retrieval). Aborting...\n' + return False + + line_mode_output = entry_line_mode_output.GetValue() + + node_line_mode.SetIntValue(line_mode_output) + + # Set Line Source for Selected Line to Counter 0 Active + node_line_source = PySpin.CEnumerationPtr(nodemap.GetNode('LineSource')) + if not PySpin.IsAvailable(node_line_source) or not PySpin.IsWritable(node_line_source): + print '\nUnable to set Line Source (enumeration retrieval). Aborting...\n' + return False + + entry_line_source_counter_0_active = node_line_source.GetEntryByName('Counter0Active') + if not PySpin.IsAvailable(entry_line_source_counter_0_active) \ + or not PySpin.IsReadable(entry_line_source_counter_0_active): + print '\nUnable to set Line Source (entry retrieval). Aborting...\n' + return False + + line_source_counter_0_active = entry_line_source_counter_0_active.GetValue() + + node_line_source.SetIntValue(line_source_counter_0_active) + + if camera_family_bfs in camera_model: + # Change Line Selector to Line 2 and Enable 3.3 Voltage Rail + entry_line_selector_line_2 = node_line_selector.GetEntryByName('Line2') + if not PySpin.IsAvailable(entry_line_selector_line_2) or not PySpin.IsReadable(entry_line_selector_line_2): + print '\nUnable to set Line Selector (entry retrieval). Aborting...\n' + return False + + line_selector_line_2 = entry_line_selector_line_2.GetValue() + + node_line_selector.SetIntValue(line_selector_line_2) + + node_voltage_enable = PySpin.CBooleanPtr(nodemap.GetNode('V3_3Enable')) + if not PySpin.IsAvailable(node_voltage_enable) or not PySpin.IsWritable(node_voltage_enable): + print '\nUnable to set Voltage Enable (boolean retrieval). Aborting...\n' + return False + + node_voltage_enable.SetValue(True) + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + return False + + return result + + +def configure_exposure_and_trigger(nodemap): + """ + This function configures the camera to set a manual exposure value and enables + camera to be triggered by the PWM signal. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '\nConfiguring Exposure and Trigger' + + try: + result = True + + # Turn off auto exposure + node_exposure_auto = PySpin.CEnumerationPtr(nodemap.GetNode('ExposureAuto')) + if not PySpin.IsAvailable(node_exposure_auto) or not PySpin.IsWritable(node_exposure_auto): + print '\nUnable to set Exposure Auto (enumeration retrieval). Aborting...\n' + return False + + entry_exposure_auto_off = node_exposure_auto.GetEntryByName('Off') + if not PySpin.IsAvailable(entry_exposure_auto_off) or not PySpin.IsReadable(entry_exposure_auto_off): + print '\nUnable to set Exposure Auto (entry retrieval). Aborting...\n' + return False + + exposure_auto_off = entry_exposure_auto_off.GetValue() + + node_exposure_auto.SetIntValue(exposure_auto_off) + + # Set Exposure Time to less than 1/50th of a second (5000 us is used as an example) + node_exposure_time = PySpin.CFloatPtr(nodemap.GetNode('ExposureTime')) + if not PySpin.IsAvailable(node_exposure_time) or not PySpin.IsWritable(node_exposure_time): + print '\nUnable to set Exposure Time (float retrieval). Aborting...\n' + return False + + node_exposure_time.SetValue(5000) + + # Ensure trigger mode is off + # + # *** NOTES *** + # The trigger must be disabled in order to configure + node_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(node_trigger_mode) or not PySpin.IsWritable(node_trigger_mode): + print '\nUnable to disable trigger mode (node retrieval). Aborting...\n' + return False + + entry_trigger_mode_off = node_trigger_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(entry_trigger_mode_off) or not PySpin.IsReadable(entry_trigger_mode_off): + print '\nUnable to disable trigger mode (enum entry retrieval). Aborting...\n' + return False + + node_trigger_mode.SetIntValue(entry_trigger_mode_off.GetValue()) + + # Set Trigger Source to Counter 0 Start + node_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerSource')) + if not PySpin.IsAvailable(node_trigger_source) or not PySpin.IsWritable(node_trigger_source): + print '\nUnable to set trigger source (enumeration retrieval). Aborting...\n' + return False + + entry_trigger_source_counter_0_start = node_trigger_source.GetEntryByName('Counter0Start') + if not PySpin.IsAvailable(entry_trigger_source_counter_0_start)\ + or not PySpin.IsReadable(entry_trigger_source_counter_0_start): + print '\nUnable to set trigger mode (enum entry retrieval). Aborting...\n' + return False + + node_trigger_source.SetIntValue(entry_trigger_source_counter_0_start.GetValue()) + + # Set Trigger Overlap to Readout + node_trigger_overlap = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerOverlap')) + if not PySpin.IsAvailable(node_trigger_overlap) or not PySpin.IsWritable(node_trigger_overlap): + print '\nUnable to set Trigger Overlap (enumeration retrieval). Aborting...\n' + return False + + entry_trigger_overlap_ro = node_trigger_overlap.GetEntryByName('ReadOut') + if not PySpin.IsAvailable(entry_trigger_overlap_ro) or not PySpin.IsReadable(entry_trigger_overlap_ro): + print '\nUnable to set Trigger Overlap (entry retrieval). Aborting...\n' + return False + + trigger_overlap_ro = entry_trigger_overlap_ro.GetValue() + + node_trigger_overlap.SetIntValue(trigger_overlap_ro) + + # Turn trigger mode on + entry_trigger_mode_on = node_trigger_mode.GetEntryByName('On') + if not PySpin.IsAvailable(entry_trigger_mode_on) or not PySpin.IsReadable(entry_trigger_mode_on): + print '\nUnable to enable trigger mode (enum entry retrieval). Aborting...\n' + return False + + node_trigger_mode.SetIntValue(entry_trigger_mode_on.GetValue()) + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + return False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device; please see + Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '\n*** IMAGE ACQUISITION ***\n' + try: + result = True + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (enumeration retrieval). Aborting...\n' + return False + + entry_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(entry_acquisition_mode_continuous)\ + or not PySpin.IsReadable(entry_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (enum entry retrieval). Aborting...\n' + return False + + acquisition_mode_continuous = entry_acquisition_mode_continuous.GetValue() + + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Retrieve device serial number for filename + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print 'Device serial number retrieved as {}...'.format(device_serial_number) + + print '' + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print 'Image incomplete with image status {} ...'.format(image_result.GetImageStatus()) + + else: + + # Print image information; height and width recorded in pixels + width = image_result.GetWidth() + height = image_result.GetHeight() + print 'Grabbed image {}, width = {}, height = {}'.format(i, width, height) + + # Convert image to mono 8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'CounterAndTimer-{}-{}.jpg'.format(device_serial_number, i) + else: # if serial number is empty + filename = 'CounterAndTimer-{}.jpg'.format(i) + + # Save image + image_converted.Save(filename) + print 'Image saved at {}'.format(filename) + + # Release image + image_result.Release() + print '' + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + return False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + return False + + return result + + +def reset_trigger(nodemap): + """ + This function returns the camera to a normal state by turning off trigger mode. + + *** NOTES *** + This function turns off trigger mode, but does not change the trigger source. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Turn trigger mode back off + node_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(node_trigger_mode) or not PySpin.IsWritable(node_trigger_mode): + print 'Unable to disable trigger mode (node retrieval). Non-fatal error...\n' + + entry_trigger_mode_off = node_trigger_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(entry_trigger_mode_off) or not PySpin.IsReadable(entry_trigger_mode_off): + print 'Unable to disable trigger mode (enum entry retrieval). Non-fatal error...\n' + + node_trigger_mode.SetIntValue(entry_trigger_mode_off.GetValue()) + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see the NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure Counter and Timer setup + result &= setup_counter_and_timer(nodemap) + if not result: + return result + + # Configure DigitalIO (GPIO output) + result &= configure_digital_io(nodemap) + if not result: + return result + + # Configure Exposure and Trigger + result &= configure_exposure_and_trigger(nodemap) + if not result: + return result + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Reset trigger + result &= reset_trigger(nodemap) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: {}.{}.{}.{}'.format(version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: {}'.format(num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera {}...'.format(i) + + result &= run_single_camera(cam) + print 'Camera {} example complete... \n'.format(i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/DeviceEvents.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/DeviceEvents.py new file mode 100644 index 0000000..69094e1 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/DeviceEvents.py @@ -0,0 +1,494 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# DeviceEvents.py shows how to create a handler to access device +# events. It relies on information provided in the Enumeration, Acquisition, +# and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the NodeMapCallback +# example, as nodemap callbacks follow the same general procedure as events. +# +# Device events can be thought of as camera-related events. This example +# creates a user-defined class, DeviceEventHandler, which allows the user to +# define any properties, parameters, and the event handler itself while DeviceEventHandler, +# the parent class, allows the child class to appropriately interface with +# the Spinnaker SDK. + +import os +import PySpin +import sys + + +class EventType: + """ + 'Enum' for choosing whether to register a event specifically for exposure end events + or universally for all events. + """ + GENERIC = 0 + SPECIFIC = 1 + +CHOSEN_EVENT = EventType.GENERIC # change me! +NUM_IMAGES = 10 # number of images to acquire + + +class DeviceEventHandler(PySpin.DeviceEventHandler): + """ + This class defines the properties, parameters, and the event handler itself. Take a + moment to notice what parts of the class are mandatory, and what have been + added for demonstration purposes. First, any class used to define device + events must inherit from DeviceEventHandler. Second, the method signature of + OnDeviceEvent() must also be consistent. Everything else - including the + constructor, destructor, properties, and body of OnDeviceEvent() - are + particular to the example. + """ + def __init__(self, eventname): + """ + This constructor registers an event name to be used on device events. + + :param eventname: Name of event to register. + :type eventname: str + :rtype: None + """ + super(DeviceEventHandler, self).__init__() + self.event_name = eventname + self.count = 0 + + def OnDeviceEvent(self, eventname): + """ + Callback function when a device event occurs. + Note eventname is a wrapped gcstring, not a Python string, but basic operations such as printing and comparing + with Python strings are supported. + + :param eventname: gcstring representing the name of the occurred event. + :type eventname: gcstring + :rtype: None + """ + if eventname == self.event_name: + self.count += 1 + + # Print information on specified device event + print '\tDevice event %s with ID %i number %i...' % (self.GetDeviceEventName(), + self.GetDeviceEventId(), + self.count) + else: + # Print no information on non-specified event + print '\tDevice event occurred; not %s; ignoring...' % self.event_name + + +def configure_device_events(nodemap, cam): + """ + This function configures the example to execute device events by enabling all + types of device events, and then creating and registering a device event handler that + only concerns itself with an end of exposure event. + + :param INodeMap nodemap: Device nodemap. + :param CameraPtr cam: Pointer to camera. + :returns: tuple (result, device_event_handler) + WHERE + result is True if successful, False otherwise + device_event_handler is the event handler + :rtype: (bool, DeviceEventHandler) + """ + print '\n*** CONFIGURING DEVICE EVENTS ***\n' + + try: + result = True + + # Retrieve device event selector + # + # *** NOTES *** + # Each type of device event must be enabled individually. This is done + # by retrieving "EventSelector" (an enumeration node) and then enabling + # the device event on "EventNotification" (another enumeration node). + # + # This example only deals with exposure end events. However, instead of + # only enabling exposure end events with a simpler device event function, + # all device events are enabled while the device event handler deals with + # ensuring that only exposure end events are considered. A more standard + # use-case might be to enable only the events of interest. + node_event_selector = PySpin.CEnumerationPtr(nodemap.GetNode('EventSelector')) + if not PySpin.IsAvailable(node_event_selector) or not PySpin.IsReadable(node_event_selector): + print 'Unable to retrieve event selector entries. Aborting...' + return False + + entries = node_event_selector.GetEntries() + print 'Enabling event selector entries...' + + # Enable device events + # + # *** NOTES *** + # In order to enable a device event, the event selector and event + # notification nodes (both of type enumeration) must work in unison. + # The desired event must first be selected on the event selector node + # and then enabled on the event notification node. + for entry in entries: + + # Select entry on selector node + node_entry = PySpin.CEnumEntryPtr(entry) + if not PySpin.IsAvailable(node_entry) or not PySpin.IsReadable(node_entry): + + # Skip if node fails + result = False + continue + + node_event_selector.SetIntValue(node_entry.GetValue()) + + # Retrieve event notification node (an enumeration node) + node_event_notification = PySpin.CEnumerationPtr(nodemap.GetNode('EventNotification')) + if not PySpin.IsAvailable(node_event_notification) or not PySpin.IsWritable(node_event_notification): + + # Skip if node fails + result = False + continue + + # Retrieve entry node to enable device event + node_event_notification_on = PySpin.CEnumEntryPtr(node_event_notification.GetEntryByName('On')) + if not PySpin.IsAvailable(node_event_notification_on) or not PySpin.IsReadable(node_event_notification_on): + + # Skip if node fails + result = False + continue + + node_event_notification.SetIntValue(node_event_notification_on.GetValue()) + + print '\t%s: enabled...' % node_entry.GetDisplayName() + + # Create device event handler + # + # *** NOTES *** + # The class has been designed to take in the name of an event. If all + # events are registered generically, all event types will trigger a + # device event; on the other hand, if an event is registered + # specifically, only that event will trigger an event. + device_event_handler = DeviceEventHandler('EventExposureEnd') + + # Register device event handler + # + # *** NOTES *** + # Device event handlers are registered to cameras. If there are multiple + # cameras, each camera must have any device event handlers registered to it + # separately. Note that multiple device event handlers may be registered to a + # single camera. + # + # *** LATER *** + # Device events handler must be unregistered manually. This must be done prior + # to releasing the system and while the device event handlers are still in + # scope. + if CHOSEN_EVENT == EventType.GENERIC: + + # Device event handlers registered generally will be triggered by any device event handlers. + cam.RegisterEventHandler(device_event_handler) + + print 'Device event handler registered generally...' + + elif CHOSEN_EVENT == EventType.SPECIFIC: + + # Device event handlers registered to a specified event will only + # be triggered by the type of event is it registered to. + cam.RegisterEventHandler(device_event_handler, 'EventExposureEnd') + + print 'Device event handler registered specifically to EventExposureEnd events...' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result, device_event_handler + + +def reset_device_events(cam, device_event_handler): + """ + This function resets the example by unregistering the device event handler. + + :param cam: Camera to unregister event handler from. + :param device_event_handler: Event handler for this example. + :type cam: CameraPtr + :type device_event_handler: DeviceEventHandler + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Unregister device event handler + # + # *** NOTES *** + # It is important to unregister all device event handlers from all cameras that + # they are registered to. + cam.UnregisterEventHandler(device_event_handler) + + print 'Device event handler unregistered...\n' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print '\n*** DEVICE INFORMATION ***\n' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex.message + return False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device; please see + Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print '\n*** IMAGE ACQUISITION ***\n' + try: + result = True + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (enum retrieval). Aborting...\n' + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) \ + or not PySpin.IsReadable(node_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (entry retrieval). Aborting...\n' + return False + + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Retrieve device serial number for filename + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print 'Device serial number retrieved as %s...' % device_serial_number + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print 'Image incomplete with image status %s...' % image_result.GetImageStatus() + + else: + + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print 'Grabbed Image %i, width = %i, height = %i' % (i, width, height) + + # Convert to mono8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + if device_serial_number: + filename = 'DeviceEvents-%s-%i.jpg' % (device_serial_number, i) + else: + filename = 'DeviceEvents-%i.jpg' % i + + # Save image + image_converted.Save(filename) + print 'Image saved at %s' % filename + + # Release image + image_result.Release() + print '' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to setup and run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure device event handlers + err, device_event_handler = configure_device_events(nodemap, cam) + if not err: + return err + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Reset device event handlers + result &= reset_device_events(cam, device_event_handler) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex.message + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Enumeration.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Enumeration.py new file mode 100644 index 0000000..ff5a70a --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Enumeration.py @@ -0,0 +1,271 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Enumeration.py shows how to enumerate interfaces and cameras. +# Knowing this is mandatory for doing anything with the Spinnaker SDK, and is +# therefore the best place to start learning how to use the SDK. +# +# This example introduces the preparation, use, and cleanup of the system +# object, interface and camera lists, interfaces, and cameras. It also touches +# on retrieving both nodes from nodemaps and information from nodes. +# +# Once comfortable with enumeration, we suggest checking out the Acquisition and/or +# NodeMapInfo examples. Acquisition demonstrates using a camera to acquire images, +# and NodeMapInfo demonstrates retrieving information from various node types. + +import PySpin +import sys + + +def query_interface(interface): + """ + Queries an interface for its cameras and prints out device information. + + :param interface: InterfacePtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Retrieve TL nodemap from interface + # + # *** NOTES *** + # Each interface has a nodemap that can be retrieved in order to + # access information about the interface itself, any devices + # connected, or addressing information if applicable. + nodemap_interface = interface.GetTLNodeMap() + + # Print interface display name + # + # *** NOTES *** + # Grabbing node information requires first retrieving the node and + # then retrieving its information. There are two things to keep in + # mind. First, a node is distinguished by type, which is related + # to its value's data type. Second, nodes should be checked for + # availability and readability/writability prior to making an + # attempt to read from or write to the node. + # + # Note that for Python, the node retrieved then has to be 'cast' + # to the proper type (CStringPtr in this case) before it can be used. + node_interface_display_name = PySpin.CStringPtr(nodemap_interface.GetNode('InterfaceDisplayName')) + + if PySpin.IsAvailable(node_interface_display_name) and PySpin.IsReadable(node_interface_display_name): + interface_display_name = node_interface_display_name.GetValue() + + print interface_display_name + + else: + print 'Interface display name not readable' + + # Update list of cameras on the interface + # + # *** NOTES *** + # Updating the cameras on each interface is especially important if + # there has been any device arrivals or removals since the last time + # that UpdateCameras() was called. + interface.UpdateCameras() + + # Retrieve list of cameras from the interface + # + # *** NOTES *** + # Camera lists can be retrieved from an interface or the system object. + # Camera lists retrieved from an interface, such as this one, only + # return cameras attached on that specific interface whereas camera + # lists retrieved from the system will return all cameras on all + # interfaces. + # + # *** LATER *** + # Camera lists must be cleared manually. This must be done prior to + # releasing the system and while the camera list is still in scope. + cam_list = interface.GetCameras() + + # Retrieve number of cameras + num_cams = cam_list.GetSize() + + # Return if no cameras detected + if num_cams == 0: + print '\tNo devices detected.\n' + return result + + # Print device vendor and model name for each camera on the interface + for i, cam in enumerate(cam_list): + + # Retrieve TL device nodemap; please see NodeMapInfo example for + # additional comments on transport layer nodemaps + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + # Print device vendor name and device model name + # + # *** NOTES *** + # Grabbing node information requires first retrieving the node and + # then retrieving its information. There are two things to keep in + # mind. First, a node is distinguished by type, which is related + # to its value's data type. Second, nodes should be checked for + # availability and readability/writability prior to making an + # attempt to read from or write to the node. + node_device_vendor_name = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceVendorName')) + + if PySpin.IsAvailable(node_device_vendor_name) and PySpin.IsReadable(node_device_vendor_name): + device_vendor_name = node_device_vendor_name.ToString() + + node_device_model_name = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceModelName')) + + if PySpin.IsAvailable(node_device_model_name) and PySpin.IsReadable(node_device_model_name): + device_model_name = node_device_model_name.ToString() + + print '\tDevice %i %s %s \n' % (i, device_vendor_name, device_model_name) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before losing scope + # + # *** NOTES *** + # Camera lists (and interface lists) must be cleared manually while in + # the same scope that the system is released. However, in cases like this + # where scope is lost, camera lists (and interface lists) will be cleared + # automatically. + cam_list.Clear() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def main(): + """ + Example entry point. + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + # + # *** NOTES *** + # Everything originates with the system object. It is important to notice + # that it has a singleton implementation, so it is impossible to have + # multiple system objects at the same time. Users can only get a smart + # pointer (SystemPtr) to the system instance. + # + # *** LATER *** + # The system object should be cleared prior to program completion. If not + # released explicitly, it will be released automatically when all SystemPtr + # objects that point to the system go out of scope. + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of interfaces from the system + # + # *** NOTES *** + # Interface lists are retrieved from the system object. + # + # *** LATER *** + # Interface lists must be cleared manually. This must be done prior to + # releasing the system and while the interface list is still in scope. + iface_list = system.GetInterfaces() + + # Get number of interfaces + num_ifaces = iface_list.GetSize() + + print 'Number of interfaces detected: %i' % num_ifaces + + # Retrieve list of cameras from the system + # + # *** NOTES *** + # Camera lists can be retrieved from an interface or the system object. + # Camera lists retrieved from the system, such as this one, return all + # cameras available on the system. + # + # *** LATER *** + # Camera lists must be cleared manually. This must be done prior to + # releasing the system and while the camera list is still in scope. + cam_list = system.GetCameras() + + num_cams = cam_list.GetSize() + + print 'Number of cameras detected: %i' % num_cams + + # Finish if there are no cameras + if num_cams == 0 or num_ifaces == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Clear interface list before releasing system + iface_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + print '\n*** QUERYING INTERFACES ***\n' + + for iface in iface_list: + + # Query interface + result &= query_interface(iface) + + # Release reference to interface + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del iface + + # Clear camera list before releasing system + # + # *** NOTES *** + # Camera lists must be cleared manually prior to a system release call. + cam_list.Clear() + + # Clear interface list before releasing system + # + # *** NOTES *** + # Interface lists must be cleared manually prior to a system release call. + iface_list.Clear() + + # Release system instance + # + # *** NOTES *** + # The system should be released, but if it is not, it will do so itself. + # It is often at the release of the system (whether manual or automatic) + # that unreleased resources and still-registered events will throw an + # exception. + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/EnumerationEvents.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/EnumerationEvents.py new file mode 100644 index 0000000..64454af --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/EnumerationEvents.py @@ -0,0 +1,216 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# EnumerationEvents.py explores camera arrival and removal events on the interfaces. +# It relies on information provided in the Enumeration, Acquisition, and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the NodeMapCallback example, +# as nodemap callbacks follow the same general procedure as events, but with a few less steps. +# +# This example creates a user-defined class: SystemEventHandler. +# This child class allows the user to define properties, parameters, and the event handler itself +# while the parent classes - DeviceArrivalEventHandler, DeviceRemovalEventHandler, and InterfaceEventHandler - +# allow the child classes to interface with Spinnaker. + +import PySpin + + +class SystemEventHandler(PySpin.InterfaceEventHandler): + """ + This class defines the properties and methods for device arrivals and removals + on the system. Take special note of the signatures of the OnDeviceArrival() + and OnDeviceRemoval() methods. + All three event handler types - DeviceArrivalEventHandler, DeviceRemovalEventHandler, + and InterfaceEventHandler - can be registered to interfaces, the system, or both. + However, in Spinnaker Python, an enumeration event handler must inherit from + InterfaceEventHandler if we want to handle both arrival and removal events. + + *** NOTES *** + Registering an interface event handler to the system is basically the same thing + as registering that event handler to all interfaces, with the added benefit of + not having to manage newly arrived or newly removed interfaces. In order to manually + manage newly arrived or removed interfaces, one would need to implement interface + arrival/removal event handlers, which are not yet supported in the Spinnaker Python API. + """ + def __init__(self, system): + """ + Constructor. This sets the system instance. + + :param system: Instance of the system. + :type system: SystemPtr + :rtype: None + """ + super(SystemEventHandler, self).__init__() + self.system = system + + + def OnDeviceArrival(self, serial_number): + """ + This method defines the arrival event on the system. It prints out + the device serial number of the camera arriving and the number of + cameras currently connected. The argument is the serial number of + the camera that triggered the arrival event. + + :param serial_number: gcstring representing the serial number of the arriving camera. + :type serial_number: gcstring + :return: None + """ + cam_list = self.system.GetCameras() + count = cam_list.GetSize() + print 'System event handler:' + print '\tDevice %i has arrived on the system.' % (serial_number) + print '\tThere %s %i %s on the system.' % ('is' if count == 1 else 'are', + count, + 'device' if count == 1 else 'devices') + + + def OnDeviceRemoval(self, serial_number): + """ + This method defines the removal event on the system. It prints out the + device serial number of the camera being removed and the number of cameras + currently connected. The argument is the serial number of the camera that + triggered the removal event. + + :param serial_number: gcstring representing the serial number of the removed camera. + :type serial_number: gcstring + :return: None + """ + cam_list = self.system.GetCameras() + count = cam_list.GetSize() + print 'System event handler:' + print '\tDevice %i was removed from the system.' % (serial_number) + print '\tThere %s %i %s on the system.' % ('is' if count == 1 else 'are', + count, + 'device' if count == 1 else 'devices') + + +def check_gev_enabled(system): + """ + This function checks if GEV enumeration is enabled on the system. + + :param system: Current system instance. + :type system: SystemPtr + + """ + + # Retrieve the System TL NodeMap and EnumerateGEVInterfaces node + system_node_map = system.GetTLNodeMap() + node_gev_enumeration = PySpin.CBooleanPtr(system_node_map.GetNode('EnumerateGEVInterfaces')) + + # Ensure the node is valid + if not PySpin.IsAvailable(node_gev_enumeration) or not PySpin.IsReadable(node_gev_enumeration): + print 'EnumerateGEVInterfaces node is unavailable or unreadable. Aborting...' + return + + # Check if node is enabled + gev_enabled = node_gev_enumeration.GetValue() + if not gev_enabled: + print '\nWARNING: GEV Enumeration is disabled.' + print 'If you intend to use GigE cameras please run the EnableGEVInterfaces shortcut\n' \ + 'or set EnumerateGEVInterfaces to true and relaunch your application.\n' + return + print 'GEV enumeration is enabled. Continuing..' + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :rtype: None + """ + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Check if GEV enumeration is enabled + check_gev_enabled(system) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cams = cam_list.GetSize() + + print 'Number of cameras detected: %i' % num_cams + + # Retrieve list of interfaces from the system + # + # *** NOTES *** + # MacOS interfaces are only registered if they are active. + # For this example to have the desired outcome all devices must be connected + # at the beginning and end of this example in order to register and deregister + # an event handler on each respective interface. + iface_list = system.GetInterfaces() + + num_ifaces = iface_list.GetSize() + + print 'Number of interfaces detected: %i' % num_ifaces + + print '*** CONFIGURING ENUMERATION EVENTS *** \n' + + # Create interface event handler for the system + # + # *** NOTES *** + # The SystemEventHandler has been constructed to accept a system object in + # order to print the number of cameras on the system. + system_event_handler = SystemEventHandler(system) + + # Register interface event handler for the system + # + # *** NOTES *** + # Arrival, removal, and interface event handlers can all be registered to + # interfaces or the system. Do not think that interface event handlers can only be + # registered to an interface. An interface event handler is merely a combination + # of an arrival and a removal event handler. + # + # *** LATER *** + # Arrival, removal, and interface event handlers must all be unregistered manually. + # This must be done prior to releasing the system and while they are still + # in scope. + system.RegisterInterfaceEventHandler(system_event_handler) + + # Wait for user to plug in and/or remove camera devices + raw_input('\nReady! Remove/Plug in cameras to test or press Enter to exit...\n') + + # Unregister system event handler from system object + # + # *** NOTES *** + # It is important to unregister all arrival, removal, and interface event handlers + # registered to the system. + system.UnregisterInterfaceEventHandler(system_event_handler) + + # Delete system event handler, which has a system reference + del system_event_handler + print 'Event handler unregistered from system...' + + # Clear camera list before releasing system + cam_list.Clear() + + # Clear interface list before releasing system + iface_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + +if __name__ == '__main__': + main() diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Enumeration_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Enumeration_QuickSpin.py new file mode 100644 index 0000000..0424fa5 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Enumeration_QuickSpin.py @@ -0,0 +1,259 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Enumeration_QuickSpin.py shows how to enumerate interfaces +# and cameras using the QuickSpin API. QuickSpin is a subset of the Spinnaker +# library that allows for simpler node access and control. This is a great +# example to start learning about QuickSpin. +# +# This example introduces the preparation, use, and cleanup of the system +# object, interface and camera lists, interfaces, and cameras. It also +# touches on retrieving information from pre-fetched nodes using QuickSpin. +# Retrieving node information is the only portion of the example that +# differs from Enumeration. +# +# A much wider range of topics is covered in the full Spinnaker examples than +# in the QuickSpin ones. There are only enough QuickSpin examples to +# demonstrate node access and to get started with the API; please see full +# Spinnaker examples for further or specific knowledge on a topic. + +import PySpin +import sys + + +def query_interface(interface): + """ + Queries an interface for its cameras and prints out device information. + + :param interface: InterfacePtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Print interface display name + # + # *** NOTES *** + # QuickSpin allows for the retrieval of interface information directly + # from an interface. Because interface information is made available + # on the transport layer, camera initialization is not required. + node_interface_display_name = interface.TLInterface.InterfaceDisplayName + if PySpin.IsAvailable(node_interface_display_name) and PySpin.IsReadable(node_interface_display_name): + + interface_display_name = node_interface_display_name.GetValue() + + print interface_display_name + + else: + print 'Interface display name not readable' + + # Update list of cameras on the interface + # + # *** NOTES *** + # Updating the cameras on each interface is especially important if + # there has been any device arrivals or removals since the last time + # that UpdateCameras() was called. + interface.UpdateCameras() + + # Retrieve list of cameras from the interface + # + # *** NOTES *** + # Camera lists can be retrieved from an interface or the system object. + # Camera lists retrieved from an interface, such as this one, only + # return cameras attached on that specific interface whereas camera + # lists retrieved from the system will return all cameras on all + # interfaces. + # + # *** LATER *** + # Camera lists must be cleared manually. This must be done prior to + # releasing the system and while the camera list is still in scope. + cam_list = interface.GetCameras() + + # Retrieve number of cameras + num_cams = cam_list.GetSize() + + # Return if no cameras detected + if num_cams == 0: + print '\tNo devices detected.\n' + return True + + # Print device vendor and model name for each camera on the interface + for i, cam in enumerate(cam_list): + + # Print device vendor name and device model name + # + # *** NOTES *** + # In QuickSpin, accessing nodes does not require first retrieving a + # nodemap. Instead, GenICam nodes are made available + # directly through the camera, and transport layer nodes are made + # available through the camera's TLDevice and TLStream properties. + # + # Most camera interaction happens through the GenICam nodemap, which + # requires the device to be initialized. Simpler reads, like the + # ones below, can often be accomplished at the transport layer, + # which does not require initialization; please see + # NodeMapInfo_QuickSpin for additional information on this topic. + # + # Readability/writability should be checked prior to interacting with + # nodes. Readability and writability are ensured by checking the + # access mode or by using the methods + if cam.TLDevice.DeviceVendorName.GetAccessMode() == PySpin.RO: + device_vendor_name = cam.TLDevice.DeviceVendorName.ToString() + + if cam.TLDevice.DeviceModelName.GetAccessMode() == PySpin.RO: + device_model_name = cam.TLDevice.DeviceModelName.GetValue() + + print '\tDevice %i %s %s \n' % (i, device_vendor_name, device_model_name) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before losing scope + # + # *** NOTES *** + # Camera lists (and interface lists) must be cleared manually while in + # the same scope that the system is released. However, in cases like this + # where scope is lost, camera lists (and interface lists) will be cleared + cam_list.Clear() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def main(): + """ + Example entry point. + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + # + # *** NOTES *** + # Everything originates with the system object. It is important to notice + # that it has a singleton implementation, so it is impossible to have + # multiple system objects at the same time. Users can only get a smart + # pointer (SystemPtr) to the system instance. + # + # *** LATER *** + # The system object should be cleared prior to program completion. If not + # released explicitly, it will be released automatically when all SystemPtr + # objects that point to the system go out of scope. + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of interfaces from the system + # + # *** NOTES *** + # Interface lists are retrieved from the system object. + # + # *** LATER *** + # Interface lists must be cleared manually. This must be done prior to + # releasing the system and while the interface list is still in scope. + iface_list = system.GetInterfaces() + + # Get number of interfaces + num_ifaces = iface_list.GetSize() + + print 'Number of interfaces detected: %i' % num_ifaces + + # Retrieve list of cameras from the system + # + # *** NOTES *** + # Camera lists can be retrieved from an interface or the system object. + # Camera lists retrieved from the system, such as this one, return all + # cameras available on the system. + # + # *** LATER *** + # Camera lists must be cleared manually. This must be done prior to + # releasing the system and while the camera list is still in scope. + cam_list = system.GetCameras() + + num_cams = cam_list.GetSize() + + print 'Number of cameras detected: %i' % num_cams + + # Finish if there are no cameras + if num_cams == 0 or num_ifaces == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Clear interface list before releasing system + iface_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + + print '\n*** QUERYING INTERFACES ***\n' + + for iface in iface_list: + + # Query interface + result &= query_interface(iface) + + # Release reference to interface + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del iface + + # Clear camera list before releasing system + # + # *** NOTES *** + # Camera lists must be cleared manually prior to a system release call. + cam_list.Clear() + + # Clear interface list before releasing system + # + # *** NOTES *** + # Interface lists must be cleared manually prior to a system release call. + iface_list.Clear() + + # Release system instance + # + # *** NOTES *** + # The system should be released, but if it is not, it will do so itself. + # It is often at the release of the system (whether manual or automatic) + # that unreleased resources and still registered events will throw an + # exception. + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Exposure_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Exposure_QuickSpin.py new file mode 100644 index 0000000..e48690d --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Exposure_QuickSpin.py @@ -0,0 +1,369 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Exposure_QuickSpin.py shows how to customize image exposure time +# using the QuickSpin API. QuickSpin is a subset of the Spinnaker library +# that allows for simpler node access and control. +# +# This example prepares the camera, sets a new exposure time, and restores +# the camera to its default state. Ensuring custom values fall within an +# acceptable range is also touched on. Retrieving and setting information +# is the only portion of the example that differs from Exposure. +# +# A much wider range of topics is covered in the full Spinnaker examples than +# in the QuickSpin ones. There are only enough QuickSpin examples to +# demonstrate node access and to get started with the API; please see full +# Spinnaker examples for further or specific knowledge on a topic. + +import PySpin +import sys + +NUM_IMAGES = 5 # number of images to save + + +def configure_exposure(cam): + """ + This function configures a custom exposure time. Automatic exposure is turned + off in order to allow for the customization, and then the custom setting is + applied. + + :param cam: Camera to configure exposure for. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '*** CONFIGURING EXPOSURE ***\n' + + try: + result = True + + # Turn off automatic exposure mode + # + # *** NOTES *** + # Automatic exposure prevents the manual configuration of exposure + # times and needs to be turned off for this example. Enumerations + # representing entry nodes have been added to QuickSpin. This allows + # for the much easier setting of enumeration nodes to new values. + # + # The naming convention of QuickSpin enums is the name of the + # enumeration node followed by an underscore and the symbolic of + # the entry node. Selecting "Off" on the "ExposureAuto" node is + # thus named "ExposureAuto_Off". + # + # *** LATER *** + # Exposure time can be set automatically or manually as needed. This + # example turns automatic exposure off to set it manually and back + # on to return the camera to its default state. + + if cam.ExposureAuto.GetAccessMode() != PySpin.RW: + print 'Unable to disable automatic exposure. Aborting...' + return False + + cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Off) + print 'Automatic exposure disabled...' + + # Set exposure time manually; exposure time recorded in microseconds + # + # *** NOTES *** + # Notice that the node is checked for availability and writability + # prior to the setting of the node. In QuickSpin, availability and + # writability are ensured by checking the access mode. + # + # Further, it is ensured that the desired exposure time does not exceed + # the maximum. Exposure time is counted in microseconds - this can be + # found out either by retrieving the unit with the GetUnit() method or + # by checking SpinView. + + if cam.ExposureTime.GetAccessMode() != PySpin.RW: + print 'Unable to set exposure time. Aborting...' + return False + + # Ensure desired exposure time does not exceed the maximum + exposure_time_to_set = 2000000.0 + exposure_time_to_set = min(cam.ExposureTime.GetMax(), exposure_time_to_set) + cam.ExposureTime.SetValue(exposure_time_to_set) + print 'Shutter time set to %s us...\n' % exposure_time_to_set + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def reset_exposure(cam): + """ + This function returns the camera to a normal state by re-enabling automatic exposure. + + :param cam: Camera to reset exposure on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Turn automatic exposure back on + # + # *** NOTES *** + # Automatic exposure is turned on in order to return the camera to its + # default state. + + if cam.ExposureAuto.GetAccessMode() != PySpin.RW: + print 'Unable to enable automatic exposure (node retrieval). Non-fatal error...' + return False + + cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Continuous) + + print 'Automatic exposure enabled...' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def print_device_info(cam): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param cam: Camera to get device information from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '*** DEVICE INFORMATION ***\n' + + try: + result = True + nodemap = cam.GetTLDeviceNodeMap() + + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex.message + return False + + return result + + +def acquire_images(cam): + """ + This function acquires and saves 10 images from a device; please see + Acquisition example for more in-depth comments on the acquisition of images. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + print '*** IMAGE ACQUISITION ***' + + try: + result = True + + # Set acquisition mode to continuous + if cam.AcquisitionMode.GetAccessMode() != PySpin.RW: + print 'Unable to set acquisition mode to continuous. Aborting...' + return False + + cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous) + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Get device serial number for filename + device_serial_number = '' + if cam.TLDevice.DeviceSerialNumber is not None and cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + device_serial_number = cam.TLDevice.DeviceSerialNumber.GetValue() + + print 'Device serial number retrieved as %s...' % device_serial_number + + # Get the value of exposure time to set an appropriate timeout for GetNextImage + timeout = 0 + if cam.ExposureTime.GetAccessMode() == PySpin.RW or cam.ExposureTime.GetAccessMode() == PySpin.RO: + # The exposure time is retrieved in µs so it needs to be converted to ms to keep consistency with the unit being used in GetNextImage + timeout = (int)(cam.ExposureTime.GetValue() / 1000 + 1000) + else: + print 'Unable to get exposure time. Aborting...' + return False + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + # Retrieve next received image and ensure image completion + # By default, GetNextImage will block indefinitely until an image arrives. + # In this example, the timeout value is set to [exposure time + 1000]ms to ensure that an image has enough time to arrive under normal conditions + image_result = cam.GetNextImage(timeout) + + if image_result.IsIncomplete(): + print 'Image incomplete with image status %d...' % image_result.GetImageStatus() + + else: + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print 'Grabbed Image %d, width = %d, height = %d' % (i, width, height) + + # Convert image to Mono8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8) + + # Create a unique filename + filename = 'ExposureQS-%s-%d.jpg' % (device_serial_number, i) + + # Save image + image_converted.Save(filename) + + print 'Image saved at %s' % filename + + # Release image + image_result.Release() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo_QuickSpin example for more + in-depth comments on setting up cameras. + + :param cam: Camera to run example on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + # Initialize camera + cam.Init() + + # Print device info + result = print_device_info(cam) + + # Configure exposure + if not configure_exposure(cam): + return False + + # Acquire images + result &= acquire_images(cam) + + # Reset exposure + result &= reset_exposure(cam) + + # Deinitialize camera + cam.DeInit() + + return result + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + +def main(): + """ + Example entry point; please see Enumeration_QuickSpin example for more + in-depth comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/FileAccess_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/FileAccess_QuickSpin.py new file mode 100644 index 0000000..25569ca --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/FileAccess_QuickSpin.py @@ -0,0 +1,692 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# FileAccess_QuickSpin.py shows shows how to read and write images using camera File Access function. +# +# This example uploads an image to the camera File Access storage and also +# downloads the image from the camera File Access storage and saves it to +# the disk. +# +# It also provides debug message when an additional argument `--verbose` is passed in, +# giving more detailed status of the progress to the users. +# +# Run with arguments in format (no quotes): "--mode --verbose (optional)" +# /d: Download saved image from camera and save it to the working directory. +# /u: Grab an image and store it on camera. +# + +import PySpin +import sys +import numpy as np +import os +import argparse + +parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) +subparsers = parser.add_subparsers() + +class ImageAcquisitionUtil: + @staticmethod + def check_node_readable(node): + return PySpin.IsAvailable(node) and PySpin.IsReadable(node) + + @staticmethod + def grab_reference_image(cam): + """ + This function first grabs 5 images to stablize the camera, + then it grabs a reference image and returns its pointer. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: Pointer to the reference image + :rtype: ImagePtr + """ + reference_image = PySpin.Image.Create() + + # Start capturing images + cam.BeginAcquisition() + + # Grab a couple of images to stabilize the camera + for image_count in range(5): + try: + result_image = cam.GetNextImage(1000) + if result_image.IsIncomplete(): + print 'Imgae incomplete with image status %s' % result_image.GetImageStatus() + else: + print 'Grabbed image %s' %str(image_count) + ', width = %s' % str(result_image.GetWidth())\ + + ', height = %s' % str(result_image.GetHeight()) + reference_image.DeepCopy(result_image) + result_image.Release() + except PySpin.SpinnakerException as ex: + print ex + continue + + cam.EndAcquisition() + + return reference_image + +class FileAccess: + @staticmethod + def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print '*** DEVICE INFORMATION ***\n' + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if ImageAcquisitionUtil.check_node_readable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + print '' + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + @staticmethod + def execute_delete_command(cam): + """ + This function executes delete operation on the camera. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Delete) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print 'Failed to delete file!' + return False + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + return True + + @staticmethod + def open_file_to_write(cam): + """ + This function opens the camera file for writing. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Open) + cam.FileOpenMode.SetValue(PySpin.FileOpenMode_Write) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print 'Failed to open file for writing!' + return False + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + return True + + @staticmethod + def execute_write_command(cam): + """ + This function executes write command on the camera. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Write) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print 'Failed to write to file!' + return False + except PySpin.SpinnakerException as ex: + print 'Unexpected exception : %s' % ex + return False + return True + + @staticmethod + def close_file(cam): + """ + This function closes the file. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Close) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print 'Failed to close file!' + return False + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + return True + + @staticmethod + def upload_image(cam, verbose=False): + """ + This function first acquires a reference image from the camera, + then it writes the image file to the camera with file selector UserFile1. + + :param cam: Camera used to download file from. + :param verbose: Prints additional details of file download (False by default) + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + success = True + + nodemap_tldevice = cam.GetTLDeviceNodeMap() + FileAccess.print_device_info(nodemap_tldevice) + + cam.Init() + + # Check file selector support + print 'Checking file selector support' + if cam.FileSelector.GetAccessMode() == PySpin.NA or cam.FileSelector.GetAccessMode() == PySpin.NI: + print 'File selector not supported on device!' + return False + + # Apply small pixel format + if ImageAcquisitionUtil.check_node_readable(cam.PixelFormat.GetEntry(PySpin.PixelFormat_Mono8)): + cam.PixelFormat.SetValue(PySpin.PixelFormat_Mono8) + else: + # Use Bayer8 if Mono8 is not available + cam.PixelFormat.SetValue(PySpin.PixelFormat_BayerGB8) + + # Display camera setup information + print 'Width: %s' % cam.Width.GetValue() + print 'Height: %s' % cam.Height.GetValue() + print 'offsetX: %s' % cam.OffsetX.GetValue() + print 'OffsetY: %s' % cam.OffsetY.GetValue() + print 'PixelFormat: %s' % cam.PixelFormat.GetValue() + + # Grab reference image + try: + reference_image = ImageAcquisitionUtil.grab_reference_image(cam) + except PySpin.SpinnakerException as ex: + cam.DeInit() + del cam + print 'Unexpected error grabbing reference image: %s' % ex + return False + + # Form file path + filename = "DeviceStreamWrite-" + if cam.DeviceSerialNumber.GetAccessMode() == PySpin.RW or cam.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + filename += "%s-" % cam.DeviceSerialNumber.ToString() + filename += ".bmp" + + # Save image + reference_image.Save(filename) + print 'Image saved at %s' % filename + + print '*** UPLOADING IMAGE ***' + + # Perform file stream write + selector_list = cam.FileSelector.GetEntries() + + for entry in selector_list: + # Get current enum entry node + node = PySpin.CEnumEntryPtr(entry) + + if verbose: + print '\nChecking FileSelector EnumEntry - %s' % node.GetSymbolic() + + # Check file selector entry support + if not node or not ImageAcquisitionUtil.check_node_readable(node): + # Go to next entry node + print '%s not supported!' % node.GetSymbolic() + continue + + if node.GetSymbolic() == "UserFile1": + # Set file selector + cam.FileSelector.SetIntValue(int(node.GetNumericValue())) + + # Delete file on camera before writing in case camera runs out of space + file_size = cam.FileSize.GetValue() + if file_size > 0: + if not FileAccess.execute_delete_command(cam): + print 'Failed to delete file!' + success = False + continue + + # Open file on camera for write + if not FileAccess.open_file_to_write(cam): + print 'Failed to open file!' + success = False + continue + + # Attempt to set FileAccessLength to FileAccessBufferNode length to speed up the write + if cam.FileAccessLength.GetValue() < cam.FileAccessBuffer.GetLength(): + try: + cam.FileAccessLength.SetValue(cam.FileAccessBuffer.GetLength()) + except PySpin.SpinnakerException as ex: + print 'Unable to set FileAccessLength to FileAccessBuffer length: %s' % ex + + # Set file access offset to zero if it's not + cam.FileAccessOffset.SetValue(0) + + # Compute number of write operations required + total_bytes_to_write = reference_image.GetBufferSize() + intermediate_buffer_size = cam.FileAccessLength.GetValue() + write_iterations = (total_bytes_to_write // intermediate_buffer_size) + \ + (0 if ((total_bytes_to_write % intermediate_buffer_size) == 0) else 1) + + if total_bytes_to_write == 0: + print 'Empty Image. No data will be written to camera.' + return False + + if verbose: + print '' + print 'Total bytes to write: %s' % total_bytes_to_write + print 'FileAccessLength: %s' % intermediate_buffer_size + print 'Write iterations: %s' % write_iterations + + bytes_left_to_write = total_bytes_to_write + total_bytes_written = 0 + + print 'Writing data to device' + + # Splitting the file into equal chunks (except the last chunk) + sections = [] + for index in range(write_iterations): + offset = index * intermediate_buffer_size + if offset == 0: + continue + sections.append(offset) + + # Get image data and split into equal chunks + image_data = reference_image.GetData() + split_data = np.array_split(image_data, sections) + + for i in range(len(split_data)): + # Setup data to write + tmp_buffer = split_data[i] + + # Write to AccessBufferNode + cam.FileAccessBuffer.Set(tmp_buffer) + + if intermediate_buffer_size > bytes_left_to_write: + # Update FileAccessLength, otherwise garbage data outside the range would be written to device + cam.FileAccessLength.SetValue(bytes_left_to_write) + + # Perform write command + if not FileAccess.execute_write_command(cam): + print 'Writing stream failed!' + success = False + break + + # Verify size of bytes written + size_written = cam.FileOperationResult.GetValue() + + # Log current file access offset + if verbose: + print 'File Access Offset: %s' % cam.FileAccessOffset.GetValue() + + # Keep track of total bytes written + total_bytes_written += size_written + if verbose: + print 'Bytes written: %s of %s' % (total_bytes_written, total_bytes_to_write) + + # Keep track of bytes left to write + bytes_left_to_write = total_bytes_to_write - total_bytes_written + + if verbose: + print 'Progress: (%s//%s)' % (i, write_iterations) + else: + print 'Progress: %s' % int((i*100 / write_iterations)) + "%" + + print 'Writing complete' + + if not FileAccess.close_file(cam): + success = False + + cam.DeInit() + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + return success + + @staticmethod + def open_file_to_read(cam): + """ + This function opens the file to read. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Open) + cam.FileOpenMode.SetValue(PySpin.FileOpenMode_Read) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print 'Failed to open file for reading!' + return False + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + return True + + @staticmethod + def execute_read_command(cam): + """ + This function executes read command on the camera. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Read) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print 'Failed to read file!' + return False + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + return True + + @staticmethod + def download_image(cam, verbose=False): + """ + This function reads the image file stored in the camera file selector UserFile1, + saving the file to the working directory of this example. + + :param cam: Camera used to download file from. + :param verbose: Prints additional details of file download (False by default) + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + success = True + + nodemap_tldevice = cam.GetTLDeviceNodeMap() + FileAccess.print_device_info(nodemap_tldevice) + + cam.Init() + + # Check file selector support + print 'Checking file selector support' + if cam.FileSelector.GetAccessMode() == PySpin.NA or cam.FileSelector.GetAccessMode() == PySpin.NI: + print 'File selector not supported on device!' + return False + + print '*** DOWNLOADING IMAGE ***' + + selector_list = cam.FileSelector.GetEntries() + + for entry in selector_list: + node = PySpin.CEnumEntryPtr(entry) + if verbose: + print '\nChecking FileSelector EnumEntry - %s' % node.GetSymbolic() + + # Check file selector entry support + if not node or not ImageAcquisitionUtil.check_node_readable(node): + # Go to next entry node + print '%s not supported!' % node.GetSymbolic() + continue + + # Use UserFile1 as the selector in this example. + # Available file selector entries varies across different cameras + if node.GetSymbolic() == "UserFile1": + # Set file selector + cam.FileSelector.SetIntValue(int(node.GetNumericValue())) + + # Get file size + total_bytes_to_read = cam.FileSize.GetValue() + if total_bytes_to_read == 0: + print '%s - No data available to read!' % node.GetSymbolic() + success = False + continue + + print 'Total data to download: %s' % total_bytes_to_read + + # Open file on camera for reading + if not FileAccess.open_file_to_read(cam): + print 'Failed to open file!' + success = False + continue + + # Attempt to set FileAccessLength to FileAccessBufferNode length to speed up the write + if cam.FileAccessLength.GetValue() < cam.FileAccessBuffer.GetLength(): + try: + cam.FileAccessLength.SetValue(cam.FileAccessBuffer.GetLength()) + except PySpin.SpinnakerException as ex: + print 'Unable to set FileAccessLength to FileAccessBuffer length: %s' % ex + + # Set file access offset to zero + cam.FileAccessOffset.SetValue(0) + + # Computer number of read operations required + intermediate_buffer_size = cam.FileAccessLength.GetValue() + read_iterations = (total_bytes_to_read // intermediate_buffer_size) + \ + (0 if ((total_bytes_to_read % intermediate_buffer_size) == 0) else 1) + + if verbose: + print '' + print 'Total bytes to read: %s' % total_bytes_to_read + print 'FileAccessLength: %s' % intermediate_buffer_size + print 'Write iterations: %s' % read_iterations + + print 'Fetching image from camera.' + + total_size_read = 0 + size_read = cam.FileOperationResult.GetValue() + image_data = np.array(size_read, dtype=np.uint8) + + for i in range(read_iterations): + if not FileAccess.execute_read_command(cam): + print 'Reading stream failed!' + success = False + break + + # Verify size of bytes read + size_read = cam.FileOperationResult.GetValue() + + # Read from buffer Node + buffer_read = cam.FileAccessBuffer.Get(size_read) + if i == 0: + image_data = buffer_read + else: + image_data = np.append(image_data, buffer_read) + + # Keep track of total bytes read + total_size_read += size_read + if verbose: + print 'Bytes read: %s of %s' % (total_size_read, total_bytes_to_read) + print 'Progress: (%s//%s)' % (i, read_iterations) + else: + print 'Progress: %s' % int((i*100 / read_iterations)) + "%" + + print 'Reading complete' + + if not FileAccess.close_file(cam): + success = False + + # Form file path + filename = "DeviceStreamRead-" + + if cam.DeviceSerialNumber.GetAccessMode() == PySpin.RW or cam.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + filename += "%s-" % cam.DeviceSerialNumber.ToString() + + filename += ".bmp" + + # Image should be captured with Mono8 or Bayer8, it sets camera to correct pixel format + # in order to grab image ROI + if ImageAcquisitionUtil.check_node_readable(cam.PixelFormat.GetEntry(PySpin.PixelFormat_Mono8)): + cam.PixelFormat.SetValue(PySpin.PixelFormat_Mono8) + elif ImageAcquisitionUtil.check_node_readable(cam.PixelFormat.GetEntry(PySpin.PixelFormat_BayerGB8)): + # Use Bayer8 if Mono8 is not available + cam.PixelFormat.SetValue(PySpin.PixelFormat_BayerGB8) + else: + print 'Failed to set camera pixel format.' + return False + + width = cam.Width.GetValue() + height = cam.Height.GetValue() + offset_x = cam.OffsetX.GetValue() + offset_y = cam.OffsetY.GetValue() + pixel_format = cam.PixelFormat.GetValue() + + # Form image and save data + print 'Width: %s' % width + print 'Height: %s' % height + print 'OffsetX: %s' % offset_x + print 'OffsetY: %s' % offset_y + print 'PixelFormat: %s' % pixel_format + + # Create image + image = PySpin.Image.Create(width, height, offset_x, offset_y, pixel_format, image_data) + + # Save image + image.Save(filename) + print 'Image saved at %s' % filename + + cam.DeInit() + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + return success + +def main(): + """ + Example entry point; please see Enumeration.py example for more in-depth + comments on preparing and cleaning up the system with PySpin. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = False + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + parser = argparse.ArgumentParser() + parser = subparsers.add_parser('stop', formatter_class=argparse.RawTextHelpFormatter) + + parser.add_argument('--mode', required=True, type=str, + help='/u : Grab an image and store it on camera.\n/d : Download saved image from camera and save it to the working directory.\n') + parser.add_argument('--verbose', default=False, action='store_true', + help='Enable verbose output.') + + args = parser.parse_args() + + cam_list = system.GetCameras() + num_cameras = cam_list.GetSize() + + # This example only works with 1 camera is connected. + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + elif num_cameras > 1: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'This example only works when 1 camera is connected.' + raw_input('Done! Press Enter to exit...') + return False + else: + if args.mode == '/u' or args.mode == '/U': + result = FileAccess.upload_image(cam_list[0], args.verbose) + elif args.mode == '/d' or args.mode == '/D': + result = FileAccess.download_image(cam_list[0], args.verbose) + else: + print "Invalid Argument! Use '--help' to learn available arguments." + raw_input('Done! Press Enter to exit...') + return False + + if not result: + print 'File Access failed' + else: + print 'File Access is successful!' + + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/HighDynamicRange.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/HighDynamicRange.py new file mode 100644 index 0000000..a67df50 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/HighDynamicRange.py @@ -0,0 +1,301 @@ +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# HighDynamicRange.py +# This example shows how to set High Dynamic Range (HDR) if it is available on the camera. + +import PySpin +import os +import sys + +NUM_IMAGES = 4 # number of images to grab + +K_HDR_SHUTTER1 = 1000 # us +K_HDR_SHUTTER2 = 5000 +K_HDR_SHUTTER3 = 15000 +K_HDR_SHUTTER4 = 30000 + +K_HDR_GAIN1 = 0 # dB +K_HDR_GAIN2 = 5 +K_HDR_GAIN3 = 10 +K_HDR_GAIN4 = 15 + + +def print_device_info(nodemap): + """ + Helper for outputting camera information + + :param nodemap: Transport layer device nodemap. + :type INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print '*** DEVICE INFORMATION ***' + + try: + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceControl')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return True + +def check_node_accessibility(node): + """ + Helper for checking GenICam node accessibility + + :param node: GenICam node being checked + :type node: CNodePtr + :return: True if accessible, False otherwise + :rtype: bool + """ + + return PySpin.IsAvailable(node) and (PySpin.IsReadable(node) or PySpin.IsWritable(node)) + +def toggle_hdr_mode(nodemap, hdr_on): + """ + Helper for toggling HDR mode on camera + + :param nodemap: Transport layer device nodemap. + :type: INodeMap + :param hdr_on: True if want to turn hdr mode on, False otherwise. + :type hdr_on: bool + :return: True if successful, False otherwise. + :rtype: bool + """ + + node_hdr_enabled = PySpin.CBooleanPtr(nodemap.GetNode("PGR_HDRModeEnabled")) + + if check_node_accessibility(node_hdr_enabled): + node_hdr_enabled.SetValue(hdr_on) + else: + return False + + print'HDR mode turned to', hdr_on + + return True + +def initialize_hdr_images(nodemap): + """ + Helper for initializing HDR images + + :param nodemap: Transport layer device nodemap. + :type: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + hdr_image_selector = PySpin.CEnumerationPtr(nodemap.GetNode("PGR_HDRImageSelector")) + hdr_exposure_abs = PySpin.CFloatPtr(nodemap.GetNode("PGR_HDR_ExposureTimeAbs")) + hdr_gain_abs = PySpin.CFloatPtr(nodemap.GetNode("PGR_HDR_GainAbs")) + + if not check_node_accessibility(hdr_image_selector): + return False + if not check_node_accessibility(hdr_exposure_abs): + return False + if not check_node_accessibility(hdr_gain_abs): + return False + + # Configure Image1 + hdr_image_selector.SetIntValue(hdr_image_selector.GetEntryByName("Image1").GetValue()) + hdr_exposure_abs.SetValue(K_HDR_SHUTTER1) + hdr_gain_abs.SetValue(K_HDR_GAIN1) + print'Initialized HDR Image1...' + + # Configure Image2 + hdr_image_selector.SetIntValue(hdr_image_selector.GetEntryByName("Image2").GetValue()) + hdr_exposure_abs.SetValue(K_HDR_SHUTTER2) + hdr_gain_abs.SetValue(K_HDR_GAIN2) + print'Initialized HDR Image2...' + + # Configure Image3 + hdr_image_selector.SetIntValue(hdr_image_selector.GetEntryByName("Image3").GetValue()) + hdr_exposure_abs.SetValue(K_HDR_SHUTTER3) + hdr_gain_abs.SetValue(K_HDR_GAIN3) + print'Initialized HDR Image3...' + + # Configure Image4 + hdr_image_selector.SetIntValue(hdr_image_selector.GetEntryByName("Image4").GetValue()) + hdr_exposure_abs.SetValue(K_HDR_SHUTTER4) + hdr_gain_abs.SetValue(K_HDR_GAIN4) + print'Initialized HDR Image4...' + + return True + +def run_single_camera(cam): + """ + Helper for running example on single camera + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Initialize camera + cam.Init() + + # Get GenICam NodeMap info from camera + nodemap = cam.GetNodeMap() + + # Get camera information through NodeMap + print_device_info(nodemap) + + # Verify whether HDR is supported on this device + node_hdr_enabled = PySpin.CBooleanPtr(nodemap.GetNode("PGR_HDRModeEnabled")) + if not PySpin.IsAvailable(node_hdr_enabled): + print'HDR is not supported! Exiting...' + return True + + # HDR needs to be enabled prior to configure individual HDR images + toggle_hdr_mode(nodemap, True) + + if not initialize_hdr_images(nodemap): + print'Error configuring HDR image! Exiting...' + return False + + # Retrieve Device ID + device_id = cam.GetTLDeviceNodeMap().GetNode("DeviceID") + + # Begin capturing images + print'Starting grabbing images...' + cam.BeginAcquisition() + + for i in range(NUM_IMAGES): + try: + # Retrieve the next received image + raw_image = cam.GetNextImage(1000) + width = raw_image.GetWidth() + height = raw_image.GetHeight() + print'Grabbed image %d, width = %d, height = %d' % (i, width, height) + + # Convert image to Mono8 + converted_image = raw_image.Convert(PySpin.PixelFormat_Mono8) + + # Create a unique filename + filename = 'HighDynamicRange-%s-%d.jpg' % (device_id, i) + + # Save image + converted_image.Save(filename) + + # Image need to be released after use + raw_image.Release() + + except PySpin.SpinnakerException as ex: + print'Error Retrieving Image: %s' % ex + result = False + continue + + # End capturing of images + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print'Error: %s' % ex + result = False + + print'' + + return result + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for cam in cam_list: + result &= run_single_camera(cam) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageChannelStatistics.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageChannelStatistics.py new file mode 100644 index 0000000..51e813f --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageChannelStatistics.py @@ -0,0 +1,302 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# ImageChannelStatisitcs.py shows how to get the image data and channel statistics, and then saves / displays them. +# This example relies on information provided in the Acquisition examples. +# +# This example demonstrates how to visualize the image histogram using Python, and display an image represented as +# a numpy array. +# +# NOTE: matplotlib must be installed on Python interpreter prior to running this example + +import os +import sys +import PySpin +import matplotlib.pyplot as plt + +NUM_IMAGES = 10 # number of images to grab + + +def acquire_and_display_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and displays the channel statistics of N images from a device. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '*** IMAGE ACQUISITION ***\n' + try: + result = True + + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (enum retrieval). Aborting...' + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (entry retrieval). Aborting...' + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print 'Acquisition mode set to continuous...' + + node_pixel_format = PySpin.CEnumerationPtr(nodemap.GetNode('PixelFormat')) + if not PySpin.IsAvailable(node_pixel_format) or not PySpin.IsWritable(node_pixel_format): + print 'Unable to set Pixel Format. Aborting...' + return False + + else: + # Retrieve entry node from enumeration node + node_pixel_format_mono8 = PySpin.CEnumEntryPtr(node_pixel_format.GetEntryByName('Mono8')) + if not PySpin.IsAvailable(node_pixel_format_mono8) or not PySpin.IsReadable(node_pixel_format_mono8): + print 'Unable to set Pixel Format to MONO8. Aborting...' + return False + + # Retrieve integer value from entry node + pixel_format_mono8 = node_pixel_format_mono8.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_pixel_format.SetIntValue(pixel_format_mono8) + + print 'Pixel Format set to MONO8 ...' + + cam.BeginAcquisition() + + print 'Acquiring images...' + + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print 'Device serial number retrieved as %s...' % device_serial_number + + plt.ion() + for i in range(NUM_IMAGES): + try: + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print 'Image incomplete with image status %d ...' % image_result.GetImageStatus() + else: + fig = plt.figure(1) + + try: + image_stats = image_result.CalculateChannelStatistics(PySpin.GREY) + # Getting the image data as a numpy array + image_data = image_result.GetNDArray() + + # Display Statistics + print 'SN%s image %d:' % (device_serial_number, i) + print '\tNumber pixel values : %d' % image_stats.num_pixel_values + print '\tRange: Min = %d, Max = %d' % (image_stats.range_min, + image_stats.range_max) + print '\tPixel Value: Min = %d, Max = %d, Mean = %.2f' % (image_stats.pixel_value_min, + image_stats.pixel_value_max, + image_stats.pixel_value_mean) + + # Using matplotlib, two subplots are created where the top subplot is the histogram and the + # bottom subplot is the image. + # + # Refer to https://matplotlib.org/2.0.2/api/pyplot_api.html#module-matplotlib.pyplot + + # Clear the figure to reuse for next plot + plt.clf() + + # Plot the histogram in the first subplot in a 2 row by 1 column grid + plt.subplot(211) + plt.cla() + plt.plot(image_stats.histogram, label='Grey') + plt.title('SN%s Histogram (%d)' % (device_serial_number, i)) + plt.legend() + + # Plot the image in the second subplot in a 2 row by 1 column grid + plt.subplot(212) + plt.cla() + plt.imshow(image_data, cmap='gray') + + # Show the image + plt.show() + plt.pause(0.01) + + # Create a unique filename + if device_serial_number: + filename = 'ImageChannelStatistics-%s-%d.png' % (device_serial_number, i) + else: # if serial number is empty + filename = 'ImageChannelStatistics-%d.png' % i + + fig.savefig(filename) + print '\tSave to %s' % filename + print + + except PySpin.SpinnakerException: + raise + + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + + except PySpin.SpinnakerException: + raise + + cam.EndAcquisition() + print 'End Acquisition' + + plt.close() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + #Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Acquire images + result &= acquire_and_display_images(cam, nodemap, nodemap_tldevice) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + +def main(): + """ + Example entry point; notice the volume of data that the logging event handler + prints out on debug despite the fact that very little really happens in this + example. Because of this, it may be better to have the logger set to lower + level in order to provide a more concise, focused log. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) + diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageEvents.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageEvents.py new file mode 100644 index 0000000..084e976 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageEvents.py @@ -0,0 +1,453 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# ImageEvents.py shows how to acquire images using the image event handler. +# It relies on information provided in the Enumeration, Acquisition, +# and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the NodeMapCallback +# example, as nodemap callbacks follow the same general procedure as +# events, but with a few less steps. +# +# This example creates a user-defined class, ImageEventHandler, that inherits +# from the Spinnaker class, ImageEventHandler. ImageEventHandler allows the user to +# define any properties, parameters, and the event handler itself while ImageEvent +# allows the child class to appropriately interface with Spinnaker. + +import os +import sys +import PySpin +from time import sleep + +SLEEP_DURATION = 200 # amount of time for main thread to sleep for (in milliseconds) until _NUM_IMAGES have been saved + + +class ImageEventHandler(PySpin.ImageEventHandler): + """ + This class defines the properties, parameters, and the event handler itself. Take a + moment to notice what parts of the class are mandatory, and what have been + added for demonstration purposes. First, any class used to define image events + must inherit from ImageEventHandler. Second, the method signature of OnImageEvent() + must also be consistent. Everything else - including the constructor, + destructor, properties, body of OnImageEvent(), and other functions - + is particular to the example. + """ + _NUM_IMAGES = 10 + + def __init__(self, cam): + """ + Constructor. Retrieves serial number of given camera and sets image counter to 0. + + :param cam: Camera instance, used to get serial number for unique image filenames. + :type cam: CameraPtr + :rtype: None + """ + super(ImageEventHandler, self).__init__() + + nodemap = cam.GetTLDeviceNodeMap() + + # Retrieve device serial number + node_device_serial_number = PySpin.CStringPtr(nodemap.GetNode('DeviceSerialNumber')) + + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + self._device_serial_number = node_device_serial_number.GetValue() + + # Initialize image counter to 0 + self._image_count = 0 + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + def OnImageEvent(self, image): + """ + This method defines an image event. In it, the image that triggered the + event is converted and saved before incrementing the count. Please see + Acquisition example for more in-depth comments on the acquisition + of images. + + :param image: Image from event. + :type image: ImagePtr + :rtype: None + """ + # Save max of _NUM_IMAGES Images + if self._image_count < self._NUM_IMAGES: + print 'Image event occurred...' + + # Check if image is incomplete + if image.IsIncomplete(): + print 'Image incomplete with image status %i...' % image.GetImageStatus() + + else: + # Print image info + print 'Grabbed image %i, width = %i, height = %i' % (self._image_count, + image.GetWidth(), + image.GetHeight()) + + # Convert to mono8 + image_converted = image.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create unique filename and save image + if self._device_serial_number: + filename = 'ImageEvents-%s-%i.jpg' % (self._device_serial_number, self._image_count) + + else: # if serial number is empty + filename = 'ImageEvents-%i.jpg' % self._image_count + + image_converted.Save(filename) + + print 'Image saved at %s\n' % filename + + # Increment image counter + self._image_count += 1 + + def get_image_count(self): + """ + Getter for image count. + + :return: Number of images saved. + :rtype: int + """ + return self._image_count + + def get_max_images(self): + """ + Getter for maximum images. + + :return: Total number of images to save. + :rtype: int + """ + return self._NUM_IMAGES + + +def configure_image_events(cam): + """ + This function configures the example to execute image event by preparing and + registering an image event handler. + + :param cam: Camera instance to configure image event. + :return: tuple(result, image_event_handler) + WHERE + result is True if successful, False otherwise + image_event_handler is the event handler + :rtype: (bool, ImageEventHandler) + """ + try: + result = True + + # Create image event handler + # + # *** NOTES *** + # The class has been constructed to accept a camera pointer in order + # to allow the saving of images with the device serial number. + image_event_handler = ImageEventHandler(cam) + + # Register image event handler + # + # *** NOTES *** + # Image event handlers are registered to cameras. If there are multiple + # cameras, each camera must have the image event handlers registered to it + # separately. Also, multiple image event handlers may be registered to a + # single camera. + # + # *** LATER *** + # Image event handlers must be unregistered manually. This must be done prior + # to releasing the system and while the image event handlers are still in + # scope. + cam.RegisterEventHandler(image_event_handler) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result, image_event_handler + + +def wait_for_images(image_event_handler): + """ + This function waits for the appropriate amount of images. Notice that + whereas most examples actively retrieve images, the acquisition of images is + handled passively in this example. + + :param image_event_handler: Image event handler. + :type image_event_handler: ImageEventHandler + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Wait for images + # + # *** NOTES *** + # In order to passively capture images using image events and + # automatic polling, the main thread sleeps in increments of SLEEP_DURATION ms + # until _MAX_IMAGES images have been acquired and saved. + while image_event_handler.get_image_count() < image_event_handler.get_max_images(): + print '\t//\n\t// Sleeping for %i ms. Grabbing images...' % SLEEP_DURATION + sleep(SLEEP_DURATION / 1000.0) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def reset_image_events(cam, image_event_handler): + """ + This functions resets the example by unregistering the image event handler. + + :param cam: Camera instance. + :param image_event_handler: Image event handler for cam. + :type cam: CameraPtr + :type image_event_handler: ImageEventHandler + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Unregister image event handler + # + # *** NOTES *** + # It is important to unregister all image event handlers from all cameras they are registered to. + # Unlike SystemEventHandler and InterfaceEventHandler in the EnumerationEvents example, + # there is no need to explicitly delete the ImageEventHandler here as it does not store + # an instance of the camera (it gets deleted in the constructor already). + cam.UnregisterEventHandler(image_event_handler) + + print 'Image events unregistered...' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap from camera. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print '*** DEVICE INFORMATION ***' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex.message + result = False + + return result + + +def acquire_images(cam, nodemap, image_event_handler): + """ + This function passively waits for images by calling wait_for_images(). Notice that + this function is much shorter than the acquire_images() function of other examples. + This is because most of the code has been moved to the image event's OnImageEvent() + method. + + :param cam: Camera instance to grab images from. + :param nodemap: Device nodemap. + :param image_event_handler: Image event handler. + :type cam: CameraPtr + :type nodemap: INodeMap + :type image_event_handler: ImageEventHandler + :return: True if successful, False otherwise. + :rtype: bool + """ + print '*** IMAGE ACQUISITION ***\n' + try: + result = True + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (enum retrieval). Aborting...' + return False + + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable(node_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (entry retrieval). Aborting...' + return False + + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Retrieve images using image event handler + wait_for_images(image_event_handler) + + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure image event handlers + err, image_event_handler = configure_image_events(cam) + if not err: + return err + + # Acquire images using the image event handler + result &= acquire_images(cam, nodemap, image_event_handler) + + # Reset image event handlers + result &= reset_image_events(cam, image_event_handler) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for additional + comments on the steps in this function. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cams = cam_list.GetSize() + + print 'Number of cameras detected: %i' % num_cams + + # Finish if there are no cameras + if num_cams == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %i...' % i) + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + raw_input('Done! Press Enter to exit...') + + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) + diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageFormatControl.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageFormatControl.py new file mode 100644 index 0000000..f682c4e --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageFormatControl.py @@ -0,0 +1,501 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# ImageFormatControl.py shows how to apply custom image settings to +# the camera. It relies on information provided in the Enumeration, +# Acquisition, and NodeMapInfo examples. +# +# This example demonstrates setting minimums to offsets, X and Y, and maximums +# to width and height. It also shows the setting of a new pixel format, which +# is an enumeration type node. +# +# Following this, we suggest familiarizing yourself with the Exposure example +# if you haven't already. Exposure is another example on camera customization +# that is shorter and simpler than many of the others. Once comfortable with +# Exposure and ImageFormatControl, we suggest checking out any of the longer, +# more complicated examples related to camera configuration: ChunkData, +# LookupTable, Sequencer, or Trigger. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def configure_custom_image_settings(nodemap): + """ + Configures a number of settings on the camera including offsets X and Y, width, + height, and pixel format. These settings must be applied before BeginAcquisition() + is called; otherwise, they will be read only. Also, it is important to note that + settings are applied immediately. This means if you plan to reduce the width and + move the x offset accordingly, you need to apply such changes in the appropriate order. + + :param nodemap: GenICam nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print '\n*** CONFIGURING CUSTOM IMAGE SETTINGS *** \n' + + try: + result = True + + # Apply mono 8 pixel format + # + # *** NOTES *** + # Enumeration nodes are slightly more complicated to set than other + # nodes. This is because setting an enumeration node requires working + # with two nodes instead of the usual one. + # + # As such, there are a number of steps to setting an enumeration node: + # retrieve the enumeration node from the nodemap, retrieve the desired + # entry node from the enumeration node, retrieve the integer value from + # the entry node, and set the new value of the enumeration node with + # the integer value from the entry node. + # + # Retrieve the enumeration node from the nodemap + node_pixel_format = PySpin.CEnumerationPtr(nodemap.GetNode('PixelFormat')) + if PySpin.IsAvailable(node_pixel_format) and PySpin.IsWritable(node_pixel_format): + + # Retrieve the desired entry node from the enumeration node + node_pixel_format_mono8 = PySpin.CEnumEntryPtr(node_pixel_format.GetEntryByName('Mono8')) + if PySpin.IsAvailable(node_pixel_format_mono8) and PySpin.IsReadable(node_pixel_format_mono8): + + # Retrieve the integer value from the entry node + pixel_format_mono8 = node_pixel_format_mono8.GetValue() + + # Set integer as new value for enumeration node + node_pixel_format.SetIntValue(pixel_format_mono8) + + print 'Pixel format set to %s...' % node_pixel_format.GetCurrentEntry().GetSymbolic() + + else: + print 'Pixel format mono 8 not available...' + + else: + print 'Pixel format not available...' + + # Apply minimum to offset X + # + # *** NOTES *** + # Numeric nodes have both a minimum and maximum. A minimum is retrieved + # with the method GetMin(). Sometimes it can be important to check + # minimums to ensure that your desired value is within range. + node_offset_x = PySpin.CIntegerPtr(nodemap.GetNode('OffsetX')) + if PySpin.IsAvailable(node_offset_x) and PySpin.IsWritable(node_offset_x): + + node_offset_x.SetValue(node_offset_x.GetMin()) + print 'Offset X set to %i...' % node_offset_x.GetMin() + + else: + print 'Offset X not available...' + + # Apply minimum to offset Y + # + # *** NOTES *** + # It is often desirable to check the increment as well. The increment + # is a number of which a desired value must be a multiple of. Certain + # nodes, such as those corresponding to offsets X and Y, have an + # increment of 1, which basically means that any value within range + # is appropriate. The increment is retrieved with the method GetInc(). + node_offset_y = PySpin.CIntegerPtr(nodemap.GetNode('OffsetY')) + if PySpin.IsAvailable(node_offset_y) and PySpin.IsWritable(node_offset_y): + + node_offset_y.SetValue(node_offset_y.GetMin()) + print 'Offset Y set to %i...' % node_offset_y.GetMin() + + else: + print 'Offset Y not available...' + + # Set maximum width + # + # *** NOTES *** + # Other nodes, such as those corresponding to image width and height, + # might have an increment other than 1. In these cases, it can be + # important to check that the desired value is a multiple of the + # increment. However, as these values are being set to the maximum, + # there is no reason to check against the increment. + node_width = PySpin.CIntegerPtr(nodemap.GetNode('Width')) + if PySpin.IsAvailable(node_width) and PySpin.IsWritable(node_width): + + width_to_set = node_width.GetMax() + node_width.SetValue(width_to_set) + print 'Width set to %i...' % node_width.GetValue() + + else: + print 'Width not available...' + + # Set maximum height + # + # *** NOTES *** + # A maximum is retrieved with the method GetMax(). A node's minimum and + # maximum should always be a multiple of its increment. + node_height = PySpin.CIntegerPtr(nodemap.GetNode('Height')) + if PySpin.IsAvailable(node_height) and PySpin.IsWritable(node_height): + + height_to_set = node_height.GetMax() + node_height.SetValue(height_to_set) + print 'Height set to %i...' % node_height.GetValue() + + else: + print 'Height not available...' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print '*** DEVICE INFORMATION ***\n' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '*** IMAGE ACQUISITION ***\n' + try: + result = True + + # Set acquisition mode to continuous + # + # *** NOTES *** + # Because the example acquires and saves 10 images, setting acquisition + # mode to continuous lets the example finish. If set to single frame + # or multiframe (at a lower number of images), the example would just + # hang. This would happen because the example has been written to + # acquire 10 images while the camera would have been programmed to + # retrieve less than that. + # + # Setting the value of an enumeration node is slightly more complicated + # than other node types. Two nodes must be retrieved: first, the + # enumeration node is retrieved from the nodemap; and second, the entry + # node is retrieved from the enumeration node. The integer value of the + # entry node is then set as the new value of the enumeration node. + # + # Notice that both the enumeration and the entry nodes are checked for + # availability and readability/writability. Enumeration nodes are + # generally readable and writable whereas their entry nodes are only + # ever readable. + # + # Retrieve enumeration node from nodemap + + # In order to access the node entries, they have to be casted to a pointer type (CEnumerationPtr here) + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (enum retrieval). Aborting...' + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (entry retrieval). Aborting...' + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + # + # *** NOTES *** + # What happens when the camera begins acquiring images depends on the + # acquisition mode. Single frame captures only a single image, multi + # frame catures a set number of images, and continuous captures a + # continuous stream of images. Because the example calls for the + # retrieval of 10 images, continuous mode has been set. + # + # *** LATER *** + # Image acquisition must be ended when no more images are needed. + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Retrieve device serial number for filename + # + # *** NOTES *** + # The device serial number is retrieved in order to keep cameras from + # overwriting one another. Grabbing image IDs could also accomplish + # this. + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print 'Device serial number retrieved as %s...' % device_serial_number + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve next received image + # + # *** NOTES *** + # Capturing an image houses images on the camera buffer. Trying + # to capture an image that does not exist will hang the camera. + # + # *** LATER *** + # Once an image from the buffer is saved and/or no longer + # needed, the image must be released in order to keep the + # buffer from filling up. + image_result = cam.GetNextImage(1000) + + # Ensure image completion + # + # *** NOTES *** + # Images can easily be checked for completion. This should be + # done whenever a complete image is expected or required. + # Further, check image status for a little more insight into + # why an image is incomplete. + if image_result.IsIncomplete(): + print 'Image incomplete with image status %d ...' % image_result.GetImageStatus() + + else: + + # Print image information; height and width recorded in pixels + # + # *** NOTES *** + # Images have quite a bit of available metadata including + # things such as CRC, image status, and offset values, to + # name a few. + width = image_result.GetWidth() + height = image_result.GetHeight() + print 'Grabbed Image %d, width = %d, height = %d' % (i, width, height) + + # Convert image to mono 8 + # + # *** NOTES *** + # Images can be converted between pixel formats by using + # the appropriate enumeration value. Unlike the original + # image, the converted one does not need to be released as + # it does not affect the camera buffer. + # + # When converting images, color processing algorithm is an + # optional parameter. + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'ImageFormatControl-%s-%d.jpg' % (device_serial_number, i) + else: # if serial number is empty + filename = 'ImageFormatControl-%d.jpg' % i + + # Save image + # + # *** NOTES *** + # The standard practice of the examples is to use device + # serial numbers to keep images of one device from + # overwriting those of another. + image_converted.Save(filename) + print 'Image saved at %s' % filename + + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + print '' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + # End acquisition + # + # *** NOTES *** + # Ending acquisition appropriately helps ensure that devices clean up + # properly and do not need to be power-cycled to maintain integrity. + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure custom image settings + if not configure_custom_image_settings(nodemap): + return False + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageFormatControl_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageFormatControl_QuickSpin.py new file mode 100644 index 0000000..d01f4b9 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/ImageFormatControl_QuickSpin.py @@ -0,0 +1,358 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# ImageFormatControl_QuickSpin.py shows how to apply custom image +# settings to the camera using the QuickSpin API. QuickSpin is a subset of +# the Spinnaker library that allows for simpler node access and control. +# +# This example demonstrates customizing offsets X and Y, width and height, +# and the pixel format. Ensuring custom values fall within an acceptable +# range is also touched on. Retrieving and setting node values using +# QuickSpin is the only portion of the example that differs from +# ImageFormatControl. +# +# A much wider range of topics is covered in the full Spinnaker examples than +# in the QuickSpin ones. There are only enough QuickSpin examples to +# demonstrate node access and to get started with the API; please see full +# Spinnaker examples for further or specific knowledge on a topic. + +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def configure_custom_image_settings(cam): + """ + Configures a number of settings on the camera including offsets X and Y, + width, height, and pixel format. These settings must be applied before + BeginAcquisition() is called; otherwise, those nodes would be read only. + Also, it is important to note that settings are applied immediately. + This means if you plan to reduce the width and move the x offset accordingly, + you need to apply such changes in the appropriate order. + + :param cam: Camera to configure settings on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + print '\n*** CONFIGURING CUSTOM IMAGE SETTINGS ***\n' + + try: + result = True + + # Apply mono 8 pixel format + # + # *** NOTES *** + # In QuickSpin, enumeration nodes are as easy to set as other node + # types. This is because enum values representing each entry node + # are added to the API. + if cam.PixelFormat.GetAccessMode() == PySpin.RW: + cam.PixelFormat.SetValue(PySpin.PixelFormat_Mono8) + print 'Pixel format set to %s...' % cam.PixelFormat.GetCurrentEntry().GetSymbolic() + + else: + print 'Pixel format not available...' + result = False + + # Apply minimum to offset X + # + # *** NOTES *** + # Numeric nodes have both a minimum and maximum. A minimum is retrieved + # with the method GetMin(). Sometimes it can be important to check + # minimums to ensure that your desired value is within range. + if cam.OffsetX.GetAccessMode() == PySpin.RW: + cam.OffsetX.SetValue(cam.OffsetX.GetMin()) + print 'Offset X set to %d...' % cam.OffsetX.GetValue() + + else: + print 'Offset X not available...' + result = False + + # Apply minimum to offset Y + # + # *** NOTES *** + # It is often desirable to check the increment as well. The increment + # is a number of which a desired value must be a multiple. Certain + # nodes, such as those corresponding to offsets X and Y, have an + # increment of 1, which basically means that any value within range + # is appropriate. The increment is retrieved with the method GetInc(). + if cam.OffsetY.GetAccessMode() == PySpin.RW: + cam.OffsetY.SetValue(cam.OffsetY.GetMin()) + print 'Offset Y set to %d...' % cam.OffsetY.GetValue() + + else: + print 'Offset Y not available...' + result = False + + # Set maximum width + # + # *** NOTES *** + # Other nodes, such as those corresponding to image width and height, + # might have an increment other than 1. In these cases, it can be + # important to check that the desired value is a multiple of the + # increment. + # + # This is often the case for width and height nodes. However, because + # these nodes are being set to their maximums, there is no real reason + # to check against the increment. + if cam.Width.GetAccessMode() == PySpin.RW and cam.Width.GetInc() != 0 and cam.Width.GetMax != 0: + cam.Width.SetValue(cam.Width.GetMax()) + print 'Width set to %i...' % cam.Width.GetValue() + + else: + print 'Width not available...' + result = False + + # Set maximum height + # + # *** NOTES *** + # A maximum is retrieved with the method GetMax(). A node's minimum and + # maximum should always be a multiple of its increment. + if cam.Height.GetAccessMode() == PySpin.RW and cam.Height.GetInc() != 0 and cam.Height.GetMax != 0: + cam.Height.SetValue(cam.Height.GetMax()) + print 'Height set to %i...' % cam.Height.GetValue() + + else: + print 'Height not available...' + result = False + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_device_info(cam): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param cam: Camera to get device information from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '\n*** DEVICE INFORMATION ***\n' + + try: + result = True + nodemap = cam.GetTLDeviceNodeMap() + + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex.message + return False + + return result + + +def acquire_images(cam): + """ + This function acquires and saves 10 images from a device; please see + Acquisition example for more in-depth comments on the acquisition of images. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + print '\n*** IMAGE ACQUISITION ***\n' + + try: + result = True + + # Set acquisition mode to continuous + if cam.AcquisitionMode.GetAccessMode() != PySpin.RW: + print 'Unable to set acquisition mode to continuous. Aborting...' + return False + + cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous) + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Get device serial number for filename + device_serial_number = '' + if cam.TLDevice.DeviceSerialNumber is not None and cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + device_serial_number = cam.TLDevice.DeviceSerialNumber.GetValue() + + print 'Device serial number retrieved as %s...' % device_serial_number + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + + try: + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print 'Image incomplete with image status %d...' % image_result.GetImageStatus() + + else: + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print 'Grabbed Image %d, width = %d, height = %d' % (i, width, height) + + # Convert image to Mono8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8) + + # Create a unique filename + if device_serial_number: + filename = 'ImageFormatControlQS-%s-%d.jpg' % (device_serial_number, i) + else: + filename = 'ImageFormatControlQS-%d.jpg' % i + + # Save image + image_converted.Save(filename) + + print 'Image saved at %s' % filename + + # Release image + image_result.Release() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo_QuickSpin example for more + in-depth comments on setting up cameras. + + :param cam: Camera to run example on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + # Initialize camera + cam.Init() + + # Print device info + result = print_device_info(cam) + + # Configure exposure + if not configure_custom_image_settings(cam): + return False + + # Acquire images + result &= acquire_images(cam) + + # Deinitialize camera + cam.DeInit() + + return result + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + +def main(): + """ + Example entry point; please see Enumeration_QuickSpin example for more + in-depth comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Inference.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Inference.py new file mode 100644 index 0000000..ad28a11 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Inference.py @@ -0,0 +1,1218 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Inference.py shows how to perform the following: +# - Upload custom inference neural networks to the camera (DDR or Flash) +# - Inject sample test image +# - Enable/Configure chunk data +# - Enable/Configure trigger inference ready sync +# - Acquire images +# - Display inference data from acquired image chunk data +# - Disable previously configured camera configurations +# +# Inference is only available for Firefly deep learning cameras. +# See the related content section on the Firefly DL product page for relevant +# documentation. +# https://www.flir.com/products/firefly-dl/ +# It can also be helpful to familiarize yourself with the Acquisition, +# ChunkData and FileAccess_QuickSpin examples. + +import PySpin +import numpy as np +import os +import sys +from enum import Enum + +# Use the following enum and global constant to select whether inference network +# type is Detection or Classification. + +class InferenceNetworkType(Enum): + # This network determines the most likely class given a set of predetermined, + # trained options. Object detection can also provide a location within the + # image (in the form of a "bounding box" surrounding the class), and can + # detect multiple objects. + DETECTION = 1 + # This network determines the best option from a list of predetermined options; + # the camera gives a percentage that determines the likelihood of the currently + # perceived image being one of the classes it has been trained to recognize. + CLASSIFICATION = 2 + +CHOSEN_INFERENCE_NETWORK_TYPE = InferenceNetworkType.DETECTION + +# Use the following enum and global constant to select whether uploaded inference +# network and injected image should be written to camera flash or DDR +class FileUploadPersistence(Enum): + FLASH = 1 # Slower upload but data persists after power cycling the camera + DDR = 2 # Faster upload but data clears after power cycling the camera + +CHOSEN_FILE_UPLOAD_PERSISTENCE = FileUploadPersistence.DDR + +# The example provides two existing custom networks that can be uploaded +# on to the camera to demonstrate classification and detection capabilities. +# "Network_Classification" file is created with Tensorflow using a mobilenet +# neural network for classifying flowers. +# "Network_Detection" file is created with Caffe using mobilenet SSD network +# for people object detection. +# Note: Make sure these files exist on the system and are accessible by the example +NETWORK_FILE_PATH = ("Network_Classification" if ((CHOSEN_INFERENCE_NETWORK_TYPE) \ + == InferenceNetworkType.CLASSIFICATION) \ + else "Network_Detection") + +# The example provides two raw images that can be injected into the camera +# to demonstrate camera inference classification and detection capabilities. Jpeg +# representation of the raw images can be found packaged with the example with +# the names "Injected_Image_Classification_Daisy.jpg" and "Injected_Image_Detection_Aeroplane.jpg". +# Note: Make sure these files exist on the system and are accessible by the example +INJECTED_IMAGE_FILE_PATH = ("Injected_Image_Classification.raw" if ((CHOSEN_INFERENCE_NETWORK_TYPE) \ + == InferenceNetworkType.CLASSIFICATION) \ + else "Injected_Image_Detection.raw") + +# The injected images have different ROI sizes so the camera needs to be +# configured to the appropriate width and height to match the injected image +INJECTED_IMAGE_WIDTH = 640 if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.CLASSIFICATION else 720 +INJECTED_IMAGE_HEIGHT = 400 if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.CLASSIFICATION else 540 + +# Use the following enum to represent the inference bounding box type +class InferenceBoundingBoxType(Enum): + INFERENCE_BOX_TYPE_RECTANGLE = 0 + INFERENCE_BOX_TYPE_CIRCLE = 1 + INFERENCE_BOX_TYPE_ROTATED_RECTANGLE = 2 + +# The sample classification inference network file was trained with the following +# data set labels +# Note: This list should match the list of labels used during the training +# stage of the network file +LABEL_CLASSIFICATION = ["daisy", "dandelion", "roses", "sunflowers", "tulips"] + +# The sample detection inference network file was trained with the following +# data set labels +# Note: This list should match the list of labels used during the training +# stage of the network file +LABEL_DETECTION = ["background", "aeroplane", "bicycle", "bird", "boat", "bottle", "bus", + "car", "cat", "chair", "cow", "diningtable", "dog", "horse", + "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "monitor"] + +# This function prints the device information of the camera from the transport +# layer; please see NodeMapInfo example for more in-depth comments on printing +# device information from the nodemap. +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print '*** DEVICE INFORMATION ***\n' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + +# This function executes a file delete operation on the camera. +def camera_delete_file(nodemap): + ptr_file_size = PySpin.CIntegerPtr(nodemap.GetNode("FileSize")) + if not PySpin.IsReadable(ptr_file_size): + print 'Unable to query FileSize. Aborting...' + return False + + if ptr_file_size.GetValue() == 0: + # No file uploaded yet. Skip delete + print 'No files found, skipping file deletion.' + return True + + print 'Deleting file...' + try: + ptr_file_operation_selector = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationSelector")) + if not PySpin.IsWritable(ptr_file_operation_selector): + print 'Unable to configure FileOperationSelector. Aborting...' + return False + + ptr_file_operation_delete = PySpin.CEnumEntryPtr(ptr_file_operation_selector.GetEntryByName("Delete")) + if not PySpin.IsReadable(ptr_file_operation_delete): + print 'Unable to configure FileOperationSelector Delete. Aborting...' + return False + + ptr_file_operation_selector.SetIntValue(int(ptr_file_operation_delete.GetNumericValue())) + + ptr_file_operation_execute = PySpin.CCommandPtr(nodemap.GetNode("FileOperationExecute")) + if not PySpin.IsWritable(ptr_file_operation_execute): + print 'Unable to configure FileOperationExecute. Aborting...' + return False + + ptr_file_operation_execute.Execute() + + ptr_file_operation_status = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationStatus")) + if not PySpin.IsReadable(ptr_file_operation_status): + print 'Unable to query FileOperationStatus. Aborting...' + return False + + ptr_file_operation_status_success = PySpin.CEnumEntryPtr(ptr_file_operation_status.GetEntryByName("Success")) + if not PySpin.IsReadable(ptr_file_operation_status_success): + print 'Unable to query FileOperationStatus. Aborting...' + return False + + if ptr_file_operation_status.GetCurrentEntry().GetNumericValue() != ptr_file_operation_status_success.GetNumericValue(): + print 'Failed to delete file! File Operation Status : %s' %ptr_file_operation_status.GetCurrentEntry().GetSymbolic() + return False + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return True + +# This function executes file open/write on the camera, sets the uploaded file persistence +# and attempt to set FileAccessLength to FileAccessBufferNode length to speed up the write. +def camera_open_file(nodemap): + print 'Opening file for writing...' + try: + ptr_file_operation_selector = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationSelector")) + if not PySpin.IsWritable(ptr_file_operation_selector): + print 'Unable to configure FileOperationSelector. Aborting...' + return False + + ptr_file_operation_open = PySpin.CEnumEntryPtr(ptr_file_operation_selector.GetEntryByName("Open")) + if not PySpin.IsReadable(ptr_file_operation_open): + print 'Unable to configure FileOperationSelector Open. Aborting...' + return False + + ptr_file_operation_selector.SetIntValue(int(ptr_file_operation_open.GetNumericValue())) + + ptr_file_open_mode = PySpin.CEnumerationPtr(nodemap.GetNode("FileOpenMode")) + if not PySpin.IsWritable(ptr_file_open_mode): + print 'Unable to configure ptr_file_open_mode. Aborting...' + return False + + ptr_file_open_mode_write = PySpin.CEnumEntryPtr(ptr_file_open_mode.GetEntryByName("Write")) + if not PySpin.IsReadable(ptr_file_open_mode_write): + print 'Unable to configure FileOperationSelector Write. Aborting...' + return False + + ptr_file_open_mode.SetIntValue(int(ptr_file_open_mode_write.GetNumericValue())) + + ptr_file_operation_execute = PySpin.CCommandPtr(nodemap.GetNode("FileOperationExecute")) + if not PySpin.IsWritable(ptr_file_operation_execute): + print 'Unable to configure FileOperationExecute. Aborting...' + return False + + ptr_file_operation_execute.Execute() + + ptr_file_operation_status = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationStatus")) + if not PySpin.IsReadable(ptr_file_operation_status): + print 'Unable to query FileOperationStatus. Aborting...' + return False + + ptr_file_operation_status_success = PySpin.CEnumEntryPtr(ptr_file_operation_status.GetEntryByName("Success")) + if not PySpin.IsReadable(ptr_file_operation_status_success): + print 'Unable to query FileOperationStatus. Aborting...' + return False + + if ptr_file_operation_status.GetCurrentEntry().GetNumericValue() != ptr_file_operation_status_success.GetNumericValue(): + print 'Failed to open file for writing! File Operation Status : %s' %ptr_file_operation_status.GetCurrentEntry().GetSymbolic() + return False + + # Set file upload persistence settings + ptr_file_write_to_flash = PySpin.CBooleanPtr(nodemap.GetNode("FileWriteToFlash")) + if PySpin.IsWritable(ptr_file_write_to_flash): + if CHOSEN_FILE_UPLOAD_PERSISTENCE == FileUploadPersistence.FLASH: + ptr_file_write_to_flash.SetValue(True) + print 'FileWriteToFlash is set to true' + else: + ptr_file_write_to_flash.SetValue(False) + print 'FileWriteToFlash is set to false' + + # Attempt to set FileAccessLength to FileAccessBufferNode length to speed up the write + ptr_file_access_length = PySpin.CIntegerPtr(nodemap.GetNode("FileAccessLength")) + if not PySpin.IsReadable(ptr_file_access_length) or not PySpin.IsWritable(ptr_file_access_length): + print 'Unable to query/configure FileAccessLength. Aborting...' + return False + + # Attempt to set FileAccessLength to FileAccessBufferNode length to speed up the write + ptr_file_access_buffer = PySpin.CRegisterPtr(nodemap.GetNode("FileAccessBuffer")) + if not PySpin.IsReadable(ptr_file_access_buffer): + print 'Unable to query FileAccessBuffer. Aborting...' + return False + + if ptr_file_access_length.GetValue() < ptr_file_access_buffer.GetLength(): + try: + ptr_file_access_length.SetValue(ptr_file_access_buffer.GetLength()) + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + + # Set File Access Offset to zero + ptr_file_access_offset = PySpin.CIntegerPtr(nodemap.GetNode("FileAccessOffset")) + if not PySpin.IsReadable(ptr_file_access_offset) or not PySpin.IsWritable(ptr_file_access_offset): + print 'Unable to query/configure ptrFileAccessOffset. Aborting...' + return False + ptr_file_access_offset.SetValue(0) + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return True + +# This function executes a file write operation on the camera. +def camera_write_to_file(nodemap): + try: + ptr_file_operation_selector = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationSelector")) + if not PySpin.IsWritable(ptr_file_operation_selector): + print 'Unable to configure FileOperationSelector. Aborting...' + return False + + ptr_file_operation_write = PySpin.CEnumEntryPtr(ptr_file_operation_selector.GetEntryByName("Write")) + if not PySpin.IsReadable(ptr_file_operation_write): + print 'Unable to configure FileOperationSelector Write. Aborting...' + return False + + ptr_file_operation_selector.SetIntValue(int(ptr_file_operation_write.GetNumericValue())) + + ptr_file_operation_execute = PySpin.CCommandPtr(nodemap.GetNode("FileOperationExecute")) + if not PySpin.IsWritable(ptr_file_operation_execute): + print 'Unable to configure FileOperationExecute. Aborting...' + return False + + ptr_file_operation_execute.Execute() + + ptr_file_operation_status = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationStatus")) + if not PySpin.IsReadable(ptr_file_operation_status): + print 'Unable to query FileOperationStatus. Aborting...' + return False + + ptr_file_operation_status_success = PySpin.CEnumEntryPtr(ptr_file_operation_status.GetEntryByName("Success")) + if not PySpin.IsReadable(ptr_file_operation_status_success): + print 'Unable to query FileOperationStatus Success. Aborting...' + return False + + if ptr_file_operation_status.GetCurrentEntry().GetNumericValue() != ptr_file_operation_status_success.GetNumericValue(): + print 'Failed to write to file! File Operation Status : %s' %ptr_file_operation_status.GetCurrentEntry().GetSymbolic() + return False + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return True + +# This function executes a file close operation on the camera. +def camera_close_file(nodemap): + print 'Closing file...' + try: + ptr_file_operation_selector = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationSelector")) + if not PySpin.IsWritable(ptr_file_operation_selector): + print 'Unable to configure FileOperationSelector. Aborting...' + return False + + ptr_file_operation_close = PySpin.CEnumEntryPtr(ptr_file_operation_selector.GetEntryByName("Close")) + if not PySpin.IsReadable(ptr_file_operation_close): + print 'Unable to configure FileOperationSelector Close. Aborting...' + return False + + ptr_file_operation_selector.SetIntValue(int(ptr_file_operation_close.GetNumericValue())) + + ptr_file_operation_execute = PySpin.CCommandPtr(nodemap.GetNode("FileOperationExecute")) + if not PySpin.IsWritable(ptr_file_operation_execute): + print 'Unable to configure FileOperationExecute. Aborting...' + return False + + ptr_file_operation_execute.Execute() + + ptr_file_operation_status = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationStatus")) + if not PySpin.IsReadable(ptr_file_operation_status): + print 'Unable to query FileOperationStatus. Aborting...' + return False + + ptr_file_operation_status_success = PySpin.CEnumEntryPtr(ptr_file_operation_status.GetEntryByName("Success")) + if not PySpin.IsReadable(ptr_file_operation_status_success): + print 'Unable to query FileOperationStatus. Aborting...' + return False + + if ptr_file_operation_status.GetCurrentEntry().GetNumericValue() != ptr_file_operation_status_success.GetNumericValue(): + print 'Failed to close the file! File Operation Status : %s' %ptr_file_operation_status.GetCurrentEntry().GetSymbolic() + return False + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return True + +# This function uploads a file on the system to the camera given the selected +# file selector entry. +def upload_file_to_camera(nodemap, file_selector_entry_name, file_path): + print '\n*** CONFIGURING FILE SELECTOR ***' + + ptr_file_selector = PySpin.CEnumerationPtr(nodemap.GetNode('FileSelector')) + if not PySpin.IsWritable(ptr_file_selector): + print 'Unable to configure FileSelector. Aborting...' + return False + + ptr_inference_selector_entry = PySpin.CEnumEntryPtr(ptr_file_selector.GetEntryByName(file_selector_entry_name)) + if not PySpin.IsReadable(ptr_inference_selector_entry): + print 'Unable to query FileSelector entry %s ' %file_selector_entry_name + '. Aborting...' + return False + + # Set file selector to entry + print 'Setting FileSelector to %s ' %ptr_inference_selector_entry.GetSymbolic() + '...\n' + ptr_file_selector.SetIntValue(int(ptr_inference_selector_entry.GetNumericValue())) + + # Delete file on camera before writing in case camera runs out of space + if camera_delete_file(nodemap) != True: + print 'Failed to delete existing file for selector entry %s' %ptr_inference_selector_entry.GetSymbolic() + '. Aborting...' + return False + + # Open file on camera for write + if camera_open_file(nodemap) != True: + if not camera_close_file(nodemap): + print 'Problem opening file node. Aborting...' + return False + if not camera_open_file(nodemap): + print 'Problem opening file node. Aborting...' + return False + + # check node + ptr_file_access_length = PySpin.CIntegerPtr(nodemap.GetNode('FileAccessLength')) + if not PySpin.IsReadable(ptr_file_access_length) or not PySpin.IsWritable(ptr_file_access_length): + print 'Unable to query FileAccessLength. Aborting...' + return False + + ptr_file_access_buffer = PySpin.CRegisterPtr(nodemap.GetNode('FileAccessBuffer')) + if not PySpin.IsReadable(ptr_file_access_buffer) or not PySpin.IsWritable(ptr_file_access_buffer): + print 'Unable to query FileAccessBuffer. Aborting...' + return False + + ptr_file_access_offset = PySpin.CIntegerPtr(nodemap.GetNode('FileAccessOffset')) + if not PySpin.IsReadable(ptr_file_access_offset) or not PySpin.IsWritable(ptr_file_access_offset): + print 'Unable to query FileAccessOffset. Aborting...' + return False + + ptr_file_access_result = PySpin.CIntegerPtr(nodemap.GetNode('FileOperationResult')) + if not PySpin.IsReadable(ptr_file_access_result): + print 'Unable to query FileOperationResult. Aborting...' + return False + + # Load network file from path depending on network type + with open(file_path, 'rb') as fd: + fd.seek(0, os.SEEK_END) + num_bytes = fd.tell() + fd.seek(0,0) + file_bytes = np.fromfile(fd, dtype=np.ubyte, count=num_bytes) + + if len(file_bytes) == 0: + print 'Failed to load file path : %s' %file_path + '. Aborting...' + return False + + total_bytes_to_write = len(file_bytes) + intermediate_buffer_size = ptr_file_access_length.GetValue() + write_iterations = (total_bytes_to_write // intermediate_buffer_size) + \ + (0 if ((total_bytes_to_write % intermediate_buffer_size) == 0) else 1) + + if total_bytes_to_write == 0: + print 'Empty Image. No data will be written to camera. Aborting...' + return False + + print 'Start uploading %s' %file_path + ' to device...' + + print 'Total bytes to write: %s' % total_bytes_to_write + print 'FileAccessLength: %s' % intermediate_buffer_size + print 'Write iterations: %s' % write_iterations + + bytes_left_to_write = total_bytes_to_write + total_bytes_written = 0 + + print 'Writing data to device...' + + # Splitting the file into equal chunks (except the last chunk) + sections = [] + for index in range(write_iterations): + num = index * intermediate_buffer_size + if num == 0: + continue + sections.append(num) + split_data = np.array_split(file_bytes, sections) + + # Writing split data to camera + for i in range(write_iterations): + # Set up data to write + tmp_buffer = split_data[i] + + # Write to AccessBufferNode + ptr_file_access_buffer.Set(tmp_buffer) + + if intermediate_buffer_size > bytes_left_to_write: + ptr_file_access_length.SetValue(bytes_left_to_write) + + # Perform Write command + if not camera_write_to_file(nodemap): + print 'Writing to stream failed. Aborting...' + return False + + # Verify size of bytes written + size_written = ptr_file_access_result.GetValue() + + # Keep track of total bytes written + total_bytes_written += size_written + + # Keep track of bytes left to write + bytes_left_to_write = total_bytes_to_write - total_bytes_written + + sys.stdout.write('\r') + sys.stdout.write('Progress: %s' % int((i*100 / write_iterations)) + '%' ) + sys.stdout.flush() + + print '\nWriting complete' + + if not camera_close_file(nodemap): + print 'Failed to close file!' + + return True + +# This function deletes the file uploaded to the camera given the selected +# file selector entry. +def delete_file_on_camera(nodemap, file_selector_entry_name): + print '\n*** CLEANING UP FILE SELECTOR **' + + ptr_file_selector = PySpin.CEnumerationPtr(nodemap.GetNode("FileSelector")) + if not PySpin.IsWritable(ptr_file_selector): + print 'Unable to configure FileSelector. Aborting...' + return False + + ptr_inference_selector_entry = PySpin.CEnumEntryPtr(ptr_file_selector.GetEntryByName(file_selector_entry_name)) + if not PySpin.IsReadable(ptr_inference_selector_entry): + print 'Unable to query FileSelector entry ' + file_selector_entry_name + '. Aborting...' + return False + + # Set file Selector entry + print 'Setting FileSelector to %s ' %ptr_inference_selector_entry.GetSymbolic() + '...\n' + ptr_file_selector.SetIntValue(int(ptr_inference_selector_entry.GetNumericValue())) + + if camera_delete_file(nodemap) != True: + print 'Failed to delete existing file for selector entry' + return False + + return True + +# This function enables or disables the given chunk data type based on +# the specified entry name. +def set_chunk_enable(nodemap, entry_name, enable): + result = True + ptr_chunk_selector = PySpin.CEnumerationPtr(nodemap.GetNode("ChunkSelector")) + + ptr_entry = PySpin.CEnumEntryPtr(ptr_chunk_selector.GetEntryByName(entry_name)) + if not PySpin.IsReadable(ptr_entry): + print 'Unable to find ' + entry_name + ' in ChunkSelector...' + return False + + ptr_chunk_selector.SetIntValue(ptr_entry.GetValue()) + + # Enable the boolean, thus enabling the corresponding chunk data + print 'Enabling ' + entry_name + '...' + ptr_chunk_enable = PySpin.CBooleanPtr(nodemap.GetNode("ChunkEnable")) + if not PySpin.IsAvailable(ptr_chunk_enable): + print 'not available' + return False + + if enable: + if ptr_chunk_enable.GetValue(): + print 'enabled' + elif PySpin.IsWritable(ptr_chunk_enable): + ptr_chunk_enable.SetValue(True) + print 'enabled' + else: + print 'not writable' + result = False + else: + if not ptr_chunk_enable.GetValue(): + print 'disabled' + elif PySpin.IsWritable(ptr_chunk_enable): + ptr_chunk_enable.SetValue(False) + print 'disabled' + else: + print 'not writable' + result = False + + return result + +# This function configures the camera to add inference chunk data to each image. +# When chunk data is turned on, the data is made available in both the nodemap +# and each image. +def configure_chunk_data(nodemap): + result = True + print '\n*** CONFIGURING CHUNK DATA ***' + + try: + # Activate chunk mode + # + # *** NOTES *** + # Once enabled, chunk data will be available at the end of the payload + # of every image captured until it is disabled. Chunk data can also be + # retrieved from the nodemap. + + ptr_chunk_mode_active = PySpin.CBooleanPtr(nodemap.GetNode("ChunkModeActive")) + if not PySpin.IsWritable(ptr_chunk_mode_active): + print 'Unable to active chunk mode. Aborting...' + return False + + ptr_chunk_mode_active.SetValue(True) + print 'Chunk mode activated...' + + # Enable inference related chunks in chunk data + + # Retrieve the chunk data selector node + ptr_chunk_selector = PySpin.CEnumerationPtr(nodemap.GetNode("ChunkSelector")) + if not PySpin.IsReadable(ptr_chunk_selector): + print 'Unable to retrieve chunk selector (enum retrieval). Aborting...' + return False + + # Enable chunk data inference Frame Id + result = set_chunk_enable(nodemap, "InferenceFrameId", True) + if result == False: + print "Unable to enable Inference Frame Id chunk data. Aborting..." + return result + + if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.DETECTION: + # Detection network type + + # Enable chunk data inference bounding box + result = set_chunk_enable(nodemap, "InferenceBoundingBoxResult", True) + if result == False: + print "Unable to enable Inference Bounding Box chunk data. Aborting..." + return result + else: + # Enable chunk data inference result + result = set_chunk_enable(nodemap, "InferenceResult", True) + if result == False: + print "Unable to enable Inference Result chunk data. Aborting..." + return result + + # Enable chunk data inference confidence + result = set_chunk_enable(nodemap, "InferenceConfidence", True) + if result == False: + print "Unable to enable Inference Confidence chunk data. Aborting..." + return result + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return result + +# This function disables each type of chunk data before disabling chunk data mode. +def disable_chunk_data(nodemap): + print '\n*** DISABLING CHUNK DATA ***' + + result = True + try: + ptr_chunk_selector = PySpin.CEnumerationPtr(nodemap.GetNode("ChunkSelector")) + + if not PySpin.IsReadable(ptr_chunk_selector): + print 'Unable to retrieve chunk selector. Aborting...' + return False + + result = set_chunk_enable(nodemap, "InferenceFrameId", False) + if result == False: + print 'Unable to disable Inference Frame Id chunk data. Aborting...' + return result + + if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.DETECTION: + # Detection network type + + # Disable chunk data inference bounding box + result = set_chunk_enable(nodemap, "InferenceBoundingBoxResult", False) + if result == False: + print 'Unable to disable Inference Bounding Box chunk data. Aborting...' + return result + else: + # Classification network type + + # Disable chunk data inference result + result = set_chunk_enable(nodemap, "InferenceResult", False) + if result == False: + print 'Unable to disable Inference Result chunk data. Aborting...' + return result + + # Disable chunk data inference confidence + result = set_chunk_enable(nodemap, "InferenceConfidence", False) + if result == False: + print 'Unable to disable Inference Confidence chunk data. Aborting...' + return result + + # Deactivate ChunkMode + ptr_chunk_mode_active = PySpin.CBooleanPtr(nodemap.GetNode("ChunkModeActive")) + if not PySpin.IsWritable(ptr_chunk_mode_active): + print 'Unable to deactivate chunk mode. Aborting...' + return False + + ptr_chunk_mode_active.SetValue(False) + print 'Chunk mode deactivated...' + + # Disable Inference + ptr_inference_enable = PySpin.CBooleanPtr(nodemap.GetNode("InferenceEnable")) + if not PySpin.IsWritable(ptr_inference_enable): + print 'Unable to disable inference. Aborting...' + return False + + ptr_inference_enable.SetValue(False) + print 'Inference disabled...' + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return result + +# This function displays the inference-related chunk data from the image. +def display_chunk_data(image): + result = True + print 'Printing chunk data from image...' + + try: + chunk_data = image.GetChunkData() + + inference_frame_ID = chunk_data.GetInferenceFrameId() + print '\tInference Frame ID: %s' % inference_frame_ID + + if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.DETECTION: + box_result = chunk_data.GetInferenceBoundingBoxResult() + box_count = box_result.GetBoxCount() + + print('\tInference Bounding Box Result:') + if box_count == 0: + print('\t No bounding box') + + for i in range(box_count): + box = box_result.GetBoxAt(i) + if box.boxType == InferenceBoundingBoxType.INFERENCE_BOX_TYPE_RECTANGLE.value: + print('\t\tBox {0}: Class {1} ({2}): - {3:.4f}% - {4} (X={5} Y={6} W={7} H={8})' + .format(i+1, + box.classId, + LABEL_DETECTION[box.classId] if box.classId < len(LABEL_DETECTION) else "N/A", + box.confidence * 100, + "Rectangle", + box.rect.topLeftXCoord, + box.rect.topLeftYCoord, + box.rect.bottomRightXCoord - box.rect.topLeftXCoord, + box.rect.bottomRightYCoord - box.rect.topLeftYCoord)) + elif box.boxType == InferenceBoundingBoxType.INFERENCE_BOX_TYPE_CIRCLE.value: + print('\t\tBox {0}: Class {1} ({2}): - {3:.4f}% - {4} (X={5} Y={6} R={7})' + .format(i+1, + box.classId, + LABEL_DETECTION[box.classId] if box.classId < len(LABEL_DETECTION) else "N/A", + box.confidence * 100, + "Circle", + box.rect.topLeftXCoord, + box.rect.topLeftYCoord, + box.circle.radius)) + elif box.boxType == InferenceBoundingBoxType.INFERENCE_BOX_TYPE_ROTATED_RECTANGLE.value: + print('\t\tBox {0}: Class {1} ({2}): - {3:.4f}% - {4} (X1={5} Y1={6} X2={7} Y2={8} angle={9})' + .format(i+1, + box.classId, + LABEL_DETECTION[box.classId] if box.classId < len(LABEL_DETECTION) else "N/A", + box.confidence * 100, + "Rotated Rectangle", + box.rotatedRect.topLeftXCoord, + box.rotatedRect.topLeftYCoord, + box.rotatedRect.bottomRightXCoord, + box.rotatedRect.bottomRightYCoord, + box.rotatedRect.rotationAngle)) + else: + print('\t\tBox {0}: Class {1} ({2}): - {3:.4f}% - {4})' + .format(i+1, + box.classId, + LABEL_DETECTION[box.classId] if box.classId < len(LABEL_DETECTION) else "N/A", + box.confidence * 100, + "Unknown bounding box type (not supported)")) + else: + inference_result = chunk_data.GetInferenceResult() + print '\t Inference Result: %s' %inference_result, + print ' (%s)' % LABEL_CLASSIFICATION[inference_result] if inference_result < len(LABEL_CLASSIFICATION) else "N/A" + + inference_confidence = chunk_data.GetInferenceConfidence() + print '\t Inference Confidence: %.6f' %inference_confidence + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return result + +# This function disables trigger mode on the camera. +def disable_trigger(nodemap): + print '\n*** IMAGE ACQUISITION ***' + + try: + ptr_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode("TriggerMode")) + if not PySpin.IsWritable(ptr_trigger_mode): + print 'Unable to configure TriggerMode. Aborting...' + return False + + ptr_trigger_off = PySpin.CEnumEntryPtr(ptr_trigger_mode.GetEntryByName("Off")) + if not PySpin.IsReadable(ptr_trigger_off): + print 'Unable to query TriggerMode Off. Aborting...' + return False + + print 'Configure TriggerMode to ' + ptr_trigger_off.GetSymbolic() + ptr_trigger_mode.SetIntValue(int(ptr_trigger_off.GetNumericValue())) + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return True + +# This function configures camera to run in "inference sync" trigger mode. +def configure_trigger(nodemap): + print '\n*** CONFIGURING TRIGGER ***' + + try: + # Configure TriggerSelector + ptr_trigger_selector = PySpin.CEnumerationPtr(nodemap.GetNode("TriggerSelector")) + if not PySpin.IsWritable(ptr_trigger_selector): + print 'Unable to configure TriggerSelector. Aborting...' + return False + + ptr_frame_start = PySpin.CEnumEntryPtr(ptr_trigger_selector.GetEntryByName("FrameStart")) + if not PySpin.IsReadable(ptr_frame_start): + print 'Unable to query TriggerSelector FrameStart. Aborting...' + return False + + print 'Configure TriggerSelector to ' + ptr_frame_start.GetSymbolic() + ptr_trigger_selector.SetIntValue(int(ptr_frame_start.GetNumericValue())) + + # Configure TriggerSource + ptr_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode("TriggerSource")) + if not PySpin.IsWritable(ptr_trigger_source): + print 'Unable to configure TriggerSource. Aborting...' + return False + + ptr_inference_ready = PySpin.CEnumEntryPtr(ptr_trigger_source.GetEntryByName("InferenceReady")) + if not PySpin.IsReadable(ptr_inference_ready): + print 'Unable to query TriggerSource InferenceReady. Aborting...' + return False + + print 'Configure TriggerSource to ' + ptr_inference_ready.GetSymbolic() + ptr_trigger_source.SetIntValue(int(ptr_inference_ready.GetNumericValue())) + + # Configure TriggerMode + ptr_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode("TriggerMode")) + if not PySpin.IsWritable(ptr_trigger_mode): + print 'Unable to configure TriggerMode. Aborting...' + return False + + ptr_trigger_on = PySpin.CEnumEntryPtr(ptr_trigger_mode.GetEntryByName("On")) + if not PySpin.IsReadable(ptr_trigger_on): + print 'Unable to query TriggerMode On. Aborting...' + return False + + print 'Configure TriggerMode to ' + ptr_trigger_on.GetSymbolic() + ptr_trigger_mode.SetIntValue(int(ptr_trigger_on.GetNumericValue())) + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return True + +# This function enables/disables inference on the camera and configures the inference network type +def configure_inference(nodemap, is_enabled): + if is_enabled: + print '\n*** CONFIGURING INFERENCE (' + ("DETECTION" if ((CHOSEN_INFERENCE_NETWORK_TYPE) \ + == InferenceNetworkType.DETECTION) \ + else 'CLASSIFICATION') + ') ***' + else: + print '\n*** DISABLING INFERENCE ***' + + try: + if is_enabled: + ptr_inference_network_type_selector = PySpin.CEnumerationPtr(nodemap.GetNode("InferenceNetworkTypeSelector")) + if not PySpin.IsWritable(ptr_inference_network_type_selector): + print 'Unable to query InferenceNetworkTypeSelector. Aborting...' + return False + + network_type_string = ("Detection" if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.DETECTION + else "Classification") + + # Retrieve entry node from enumeration node + ptr_inference_network_type = PySpin.CEnumEntryPtr(ptr_inference_network_type_selector.GetEntryByName(network_type_string)) + if not PySpin.IsReadable(ptr_inference_network_type): + print 'Unable to set inference network type to %s' %network_type_string + ' (entry retrieval). Aborting...' + return False + + inference_network_value = ptr_inference_network_type.GetNumericValue() + ptr_inference_network_type_selector.SetIntValue(int(inference_network_value)) + + print 'Inference network type set to' + network_type_string + '...' + + print ('Enabling' if is_enabled else 'Disabling') + ' inference...' + ptr_inference_enable = PySpin.CBooleanPtr(nodemap.GetNode("InferenceEnable")) + if not PySpin.IsWritable(ptr_inference_enable): + print 'Unable to enable inference. Aborting...' + return False + + ptr_inference_enable.SetValue(is_enabled) + print 'Inference '+'enabled...' if is_enabled else 'disabled...' + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return True + +# This function configures camera test pattern to make use of the injected test image for inference +def configure_test_pattern(nodemap, is_enabled): + if is_enabled: + print '\n*** CONFIGURING TEST PATTERN ***' + else: + print '\n*** DISABLING TEST PATTERN ***' + + try: + # Set TestPatternGeneratorSelector to PipelineStart + ptr_test_pattern_generator_selector = PySpin.CEnumerationPtr(nodemap.GetNode("TestPatternGeneratorSelector")) + if not PySpin.IsWritable(ptr_test_pattern_generator_selector): + print 'Unable to query TestPatternGeneratorSelector. Aborting...' + return False + + if is_enabled: + ptr_test_pattern_generator_pipeline_start = PySpin.CEnumEntryPtr(ptr_test_pattern_generator_selector.GetEntryByName("PipelineStart")) + if not PySpin.IsReadable(ptr_test_pattern_generator_pipeline_start): + print 'Unable to query TestPatternGeneratorSelector PipelineStart. Aborting...' + return False + + ptr_test_pattern_generator_selector.SetIntValue(int(ptr_test_pattern_generator_pipeline_start.GetNumericValue())) + print 'TestPatternGeneratorSelector set to ' + ptr_test_pattern_generator_pipeline_start.GetSymbolic() + '...' + + else: + ptr_test_pattern_generator_sensor = PySpin.CEnumEntryPtr(ptr_test_pattern_generator_selector.GetEntryByName("Sensor")) + if not PySpin.IsReadable(ptr_test_pattern_generator_sensor): + print 'Unable to query TestPatternGeneratorSelector Sensor. Aborting...' + return False + + ptr_test_pattern_generator_selector.SetIntValue(int(ptr_test_pattern_generator_sensor.GetNumericValue())) + print 'TestPatternGeneratorSelector set to ' + ptr_test_pattern_generator_sensor.GetSymbolic() + '...' + + # Set TestPattern to InjectedImage + ptr_test_pattern = PySpin.CEnumerationPtr(nodemap.GetNode("TestPattern")) + if not PySpin.IsWritable(ptr_test_pattern): + print 'Unable to query TestPattern. Aborting...' + return False + + if is_enabled: + ptr_injected_image = PySpin.CEnumEntryPtr(ptr_test_pattern.GetEntryByName("InjectedImage")) + if not PySpin.IsReadable(ptr_injected_image): + print 'Unable to query TestPattern InjectedImage. Aborting...' + return False + + ptr_test_pattern.SetIntValue(int(ptr_injected_image.GetNumericValue())) + print 'TestPattern set to ' + ptr_injected_image.GetSymbolic() + '...' + else: + ptr_test_pattern_off = PySpin.CEnumEntryPtr(ptr_test_pattern.GetEntryByName("Off")) + if not PySpin.IsReadable(ptr_test_pattern_off): + print 'Unable to query TestPattern Off. Aborting...' + return False + + ptr_test_pattern.SetIntValue(int(ptr_test_pattern_off.GetNumericValue())) + print 'TestPattern set to ' + ptr_test_pattern_off.GetSymbolic() + '...' + + if is_enabled: + # The inject images have different ROI sizes so camera needs to be configured to the appropriate + # injected width and height + ptr_injected_width = PySpin.CIntegerPtr(nodemap.GetNode("InjectedWidth")) + if not PySpin.IsWritable(ptr_injected_width): + print 'Unable to query InjectedWidth. Aborting...' + return False + + ptr_injected_width.SetValue(INJECTED_IMAGE_WIDTH if is_enabled else ptr_injected_width.GetMax()) + + ptr_injected_height = PySpin.CIntegerPtr(nodemap.GetNode("InjectedHeight")) + if not PySpin.IsWritable(ptr_injected_height): + print 'Unable to query InjectedHeight. Aborting...' + return False + + ptr_injected_height.SetValue(INJECTED_IMAGE_HEIGHT if is_enabled else ptr_injected_height.GetMax()) + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return True + +# This function acquires and saves 10 images from a device; please see +# Acquisition example for more in-depth comments on acquiring images. +def acquire_images(cam, nodemap, nodemap_tldevice): + result = True + print '\n*** IMAGE ACQUISITION ***' + + try: + # Set acquisition mode to continuous + ptr_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode("AcquisitionMode")) + if not PySpin.IsWritable(ptr_acquisition_mode): + print 'Unable to set acquisition mode to continuous (node retrieval). Aborting...' + return False + + ptr_acquisition_mode_continuous = PySpin.CEnumEntryPtr(ptr_acquisition_mode.GetEntryByName("Continuous")) + if not PySpin.IsReadable(ptr_acquisition_mode_continuous): + print "'Unable to set acquisition mode to continuous (entry 'continuous' retrieval). Aborting..." + return False + + acquisition_mode_continuous = ptr_acquisition_mode_continuous.GetValue() + + ptr_acquisition_mode.SetIntValue(int(acquisition_mode_continuous)) + + # Begin acquiring images + cam.BeginAcquisition() + + print 'Acquiring images...' + + ptr_string_serial = PySpin.CStringPtr(nodemap.GetNode("DeviceSerialNumber")) + if PySpin.IsReadable(ptr_string_serial): + device_serial_number = ptr_string_serial.GetValue() + print 'Device serial number retrieved as %s' %device_serial_number + print '\n' + + # Retrieve, convert, and save images + num_images = 10 + + for i in range(num_images): + try: + result_image = cam.GetNextImage(1000) + + if result_image.IsIncomplete(): + print 'Image incomplete with image status %d ...' % result_image.GetImageStatus() + else: + print 'Grabbed Image %d, width = %d, height = %d' \ + % (i, result_image.GetWidth(), result_image.GetHeight()) + + result = display_chunk_data(result_image) + + # Release image + result_image.Release() + print '' + + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + result = False + + cam.EndAcquisition() + except PySpin.SpinnakerException as ex: + print 'Unexpected exception: %s' % ex + return False + + return result + +# This function acts as the body of the example; please see NodeMapInfo example +# for more in-depth comments on setting up cameras. +def run_single_camera(cam): + result = False + err = 0 + + try: + nodemap_tldevice = cam.GetTLDeviceNodeMap() + result = print_device_info(nodemap_tldevice) + + cam.Init() + + nodemap = cam.GetNodeMap() + + # Check to make sure camera supports inference + print 'Checking camera inference support...' + ptr_inference_enable = PySpin.CBooleanPtr(nodemap.GetNode('InferenceEnable')) + if not PySpin.IsWritable(ptr_inference_enable): + print 'Inference is not supported on this camera. Aborting...' + return False + + # Upload custom inference network onto the camera + # The inference network file is in a movidius specific neural network format. + # Uploading the network to the camera allows for "inference on the edge" where + # camera can apply deep learning on a live stream. Refer to "Getting Started + # with Firefly-DL" for information on how to create your own custom inference + # network files using pre-existing neural network. + err = upload_file_to_camera(nodemap, "InferenceNetwork", NETWORK_FILE_PATH) + if err != True: + return err + + # Upload injected test image + # Instead of applying deep learning on a live stream, the camera can be + # tested with an injected test image. + err = upload_file_to_camera(nodemap, "InjectedImage", INJECTED_IMAGE_FILE_PATH) + if err != True: + return err + + # Configure inference + err = configure_inference(nodemap, True) + if err != True: + return err + + # Configure test pattern to make use of the injected image + err = configure_test_pattern(nodemap, True) + if err != True: + return err + + # Configure trigger + # When enabling inference results via chunk data, the results that accompany a frame + # will likely not be the frame that inference was run on. In order to guarantee that + # the chunk inference results always correspond to the frame that they are sent with, + # the camera needs to be put into the "inference sync" trigger mode. + # Note: Enabling this setting will limit frame rate so that every frame contains new + # inference dataset. To not limit the frame rate, you can enable InferenceFrameID + # chunk data to help determine which frame is associated with a particular + # inference data. + err = configure_trigger(nodemap) + if err != True: + return err + + # Configure chunk data + err = configure_chunk_data(nodemap) + if err != True: + return err + + # Acquire images and display chunk data + result = result | acquire_images(cam, nodemap, nodemap_tldevice) + + # Disable chunk data + err = disable_chunk_data(nodemap) + if err != True: + return err + + # Disable trigger + err = disable_trigger(nodemap) + if err != True: + return err + + # Disable test pattern + err = configure_test_pattern(nodemap, False) + if err != True: + return err + + # Disable inference + err = configure_inference(nodemap, False) + if err != True: + return err + + # Clear injected test image + err = delete_file_on_camera(nodemap, "InjectedImage") + if err != True: + return err + + # Clear uploaded inference network + err = delete_file_on_camera(nodemap, "InferenceNetwork") + if err != True: + return err + + # Deinitialize camera + cam.DeInit() + except PySpin.SpinnakerException as ex: + print'Unexpected exception: %s' % ex + result = False + + return result + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = False + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %s\n' % num_cameras + + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + for i, cam in enumerate(cam_list): + print 'Running example for camera %d...' % i + result = result | run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Classification.raw b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Classification.raw new file mode 100644 index 0000000..e79db8f Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Classification.raw differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Classification_Daisy.jpg b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Classification_Daisy.jpg new file mode 100644 index 0000000..128f332 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Classification_Daisy.jpg differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Detection.raw b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Detection.raw new file mode 100644 index 0000000..e1c3100 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Detection.raw differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Detection_Aeroplane.jpg b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Detection_Aeroplane.jpg new file mode 100644 index 0000000..8e3cefc Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Injected_Image_Detection_Aeroplane.jpg differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Logging.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Logging.py new file mode 100644 index 0000000..0494d17 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Logging.py @@ -0,0 +1,130 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Logging.py shows how to create a handler to access logging events. +# It relies on information provided in the Enumeration, Acquisition, and +# NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the NodeMapCallback +# example, as nodemap callbacks follow the same general procedure as +# events, but with a few less steps. +# +# This example creates a user-defined class, LoggingEventHandler, that inherits +# from the Spinnaker class, LoggingEventHandler. The child class allows the user to +# define any properties, parameters, and the event handler itself while LoggingEventHandler +# allows the child class to appropriately interface with the Spinnaker SDK. + +import PySpin + + +# Define callback priority threshold; please see documentation for additional +# information on logging level philosophy. +LOGGING_LEVEL = PySpin.LOG_LEVEL_DEBUG # change to any LOG_LEVEL_* constant + + +class LoggingEventHandler(PySpin.LoggingEventHandler): + """ + Although logging events are just as flexible and extensible as other events, + they are generally only used for logging purposes, which is why a number of + helpful functions that provide logging information have been added. Generally, + if the purpose is not logging, one of the other event types is probably more + appropriate. + """ + + def __init__(self): + super(LoggingEventHandler, self).__init__() + + def OnLogEvent(self, logging_event_data): + """ + This function displays readily available logging information. + + :param logging_event_data: Logging data. + :type logging_event_data: LoggingEventData + :rtype: None + """ + print '--------Log Event Received----------' + print 'Category: %s' % logging_event_data.GetCategoryName() + print 'Priority Value: %s' % logging_event_data.GetPriority() + print 'Priority Name: %s' % logging_event_data.GetPriorityName() + print 'Timestamp: %s' % logging_event_data.GetTimestamp() + print 'NDC: %s' % logging_event_data.GetNDC() + print 'Thread: %s' % logging_event_data.GetThreadName() + print 'Message: %s' % logging_event_data.GetLogMessage() + print '------------------------------------\n' + + +def main(): + """ + Example entry point; notice the volume of data that the logging event handler + prints out on debug despite the fact that very little really happens in this + example. Because of this, it may be better to have the logger set to lower + level in order to provide a more concise, focused log. + + :rtype: None + """ + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Create and register the logging event handler + # + # *** NOTES *** + # Logging event handlers are registered to the system. Take note that a logging + # event handler is very verbose when the logging level is set to debug. + # + # *** LATER *** + # Logging event handlers must be unregistered manually. This must be done prior to + # releasing the system and while the logging event handlers are still in scope. + logging_event_handler = LoggingEventHandler() + system.RegisterLoggingEventHandler(logging_event_handler) + + # Set callback priority level + # + # *** NOTES *** + # Please see documentation for up-to-date information on the logging + # philosophies of the Spinnaker SDK. + system.SetLoggingEventPriorityLevel(LOGGING_LEVEL) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cams = cam_list.GetSize() + + print 'Number of cameras detected: %i' % num_cams + + # Clear camera list before releasing system + cam_list.Clear() + + # Unregister logging event handler + # + # *** NOTES *** + # It is important to unregister all logging event handlers from the system. + system.UnregisterLoggingEventHandler(logging_event_handler) + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/LookupTable.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/LookupTable.py new file mode 100644 index 0000000..01375c9 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/LookupTable.py @@ -0,0 +1,439 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= + +# LookupTable.py +# +# LookupTable.py shows how to configure lookup tables on the camera. +# It relies on information provided in the Enumeration, Acquisition, and +# NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the ImageFormatControl +# and Exposure examples. As they are somewhat shorter and simpler, either +# provides a strong introduction to camera customization. +# +# Lookup tables allow for the customization and control of individual pixels. +# This can be a very powerful and deeply useful tool; however, because use +# cases are context dependent, this example only explores lookup table +# configuration. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def print_retrieve_node_failure(node, name): + """" + This function handles the error prints when a node or entry is unavailable or + not readable on the connected camera. + + :param node: Node type. "Node" or "Entry" + :param name: Node name. + :type node: String + :type name: String + :rtype: None + """ + print "Unable to get {} ({} {} retrieval failed.)".format(node, name, node) + print "The {} may not be available on all camera models...".format(node) + print "Please try a Blackfly S camera." + + +def configure_lookup_tables(nodemap): + """ + This function configures lookup tables linearly. This involves selecting the + type of lookup table, finding the appropriate increment calculated from the + maximum value, and enabling lookup tables on the camera. + + :param nodemap: Device nodemap + :type nodemap: INodeMap + :return: return True if successful, False otherwise + :rtype: bool + """ + result = True + print "***CONFIGURING LOOKUP TABLES***\n" + + # Select lookup table type + # + # ***NOTES *** + # Setting the lookup table selector. It is important to note that this + # does not enable lookup tables. + + try: + lut_selector = PySpin.CEnumerationPtr(nodemap.GetNode("LUTSelector")) + if not PySpin.IsAvailable(lut_selector) or not PySpin.IsWritable(lut_selector): + print_retrieve_node_failure("node", "LUTSelector") + return False + + lut_selector_lut1 = lut_selector.GetEntryByName("LUT1") + if not PySpin.IsAvailable(lut_selector_lut1) or not PySpin.IsReadable(lut_selector_lut1): + print_retrieve_node_failure("entry", "LUTSelector LUT1") + return False + + lut_selector.SetIntValue(lut_selector_lut1.GetValue()) + print "Lookup table selector set to LUT 1...\n" + + # Determine pixel increment and set indexes and values as desired + # + # *** NOTES *** + # To get the pixel increment, the maximum range of the value node must + # first be retrieved. The value node represents an index, so its value + # should be one less than a power of 2 (e.g. 511, 1023, etc.). Add 1 to + # this index to get the maximum range. Divide the maximum range by 512 + # to calculate the pixel increment. + # + # Finally, all values (in the value node) and their corresponding + # indexes (in the index node) need to be set. The goal of this example + # is to set the lookup table linearly. As such, the slope of the values + # should be set according to the increment, but the slope of the + # indexes is inconsequential. + + # Retrieve value node + lut_value = PySpin.CIntegerPtr(nodemap.GetNode("LUTValue")) + if not PySpin.IsAvailable(lut_value) or not PySpin.IsWritable(lut_value): + print_retrieve_node_failure("node", "LUTValue") + return False + + # Retrieve maximum range + max_range = lut_value.GetMax() + 1 + print "\tMaximum Range: {}".format(max_range) + + # Calculate increment + increment = max_range / 512 + print "\tIncrement: {}".format(increment) + + # Retrieve index node + lut_index = PySpin.CIntegerPtr(nodemap.GetNode("LUTIndex")) + if not PySpin.IsAvailable(lut_index) or not PySpin.IsWritable(lut_index): + print_retrieve_node_failure("node", "LUTIndex") + return False + + # Set values and indexes + i = 0 + while i < max_range: + lut_index.SetValue(int(i)) + lut_value.SetValue(int(i)) + i += increment + + print "All lookup table values set...\n" + + # Enable lookup tables + # + # *** NOTES *** + # Once lookup tables have been configured, don"t forget to enable them + # with the appropriate node. + # + # *** LATER *** + # Once the images with lookup tables have been collected, turn the + # feature off with the same node. + + lut_enable = PySpin.CBooleanPtr(nodemap.GetNode("LUTEnable")) + if not PySpin.IsAvailable(lut_enable) or not PySpin.IsWritable(lut_enable): + print_retrieve_node_failure("node", "LUTEnable") + return False + + lut_enable.SetValue(True) + print "Lookup tables enabled...\n" + + except PySpin.SpinnakerException as ex: + print "Error: {}".format(ex) + result = False + + return result + + +def reset_lookup_tables(nodemap): + """ + This function resets the camera by disabling lookup tables. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: return True if successful, False otherwise + :rtype: bool + """ + result = True + + # Disable lookup tables + # + # *** NOTES *** + # Turn lookup tables off when they are not needed to reduce overhead + + try: + lut_enable = PySpin.CBooleanPtr(nodemap.GetNode("LUTEnable")) + if not PySpin.IsAvailable(lut_enable) or not PySpin.IsWritable(lut_enable): + print "Unable to disable lookup tables. Non-fatal error...\n" + return False + + lut_enable.SetValue(False) + print "Lookup tables disabled...\n" + + except PySpin.SpinnakerException as ex: + print "Error: {}".format(ex) + result = False + + return result + + +def print_device_info(nodemap): + """ + # This function prints the device information of the camera from the transport + # layer; please see NodeMapInfo example for more in-depth comments on printing + # device information from the nodemap. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: return True if successful, False otherwise + :rtype: bool + """ + result = True + print "*** DEVICE INFORMATION ***\n" + + try: + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + if PySpin.IsReadable(node_feature): + feature_string = node_feature.ToString() + else: + feature_string = "Node not readable" + + print "{}: {}".format(node_feature.GetName(), feature_string) + + else: + print "Device control information not available." + + except PySpin.SpinnakerException as ex: + print "Error: {}".format(ex) + result = False + + return result + + +def acquire_images(cam, nodemap, nodemap_tl_device): + """ + This function acquires and saves 10 images from a device; please see + Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from + :param nodemap: Device nodemap + :param nodemap_tl_device: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tl_device: INodeMap + :return: return True if successful, False otherwise + :rtype: bool + """ + result = True + print "*** IMAGE ACQUISITION ***\n" + + # Set acquisition mode to continuous + try: + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode("AcquisitionMode")) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print "Unable to set acquisition mode to continuous (node retrieval). Aborting...\n" + return False + + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName("Continuous") + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or \ + not PySpin.IsReadable(node_acquisition_mode_continuous): + print "Unable to set acquisition mode to continuous (entry 'continuous' retrieval). Aborting...\n" + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + print "Acquisition mode set to continuous...\n" + + # Begin acquiring images + cam.BeginAcquisition() + print "Acquiring images...\n" + + # Retrieve device serial number for filename + device_serial_number = "" + node_device_serial_number = PySpin.CStringPtr(nodemap_tl_device.GetNode("DeviceSerialNumber")) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print "Device serial number retrieved as {}...".format(device_serial_number) + + print "" + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print "Image incomplete with image status {}...".format(image_result.GetImageStatus()) + + else: + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print "Grabbed image {}, width = {}, height = {}".format(i, width, height) + + # Convert image to mono 8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = "LookupTable-{}-{}.jpg".format(device_serial_number, i) + else: # if serial number is empty + filename = "LookupTable-{}.jpg".format(i) + + # Save image + image_converted.Save(filename) + print "Image saved at {}".format(filename) + + # Release image + image_result.Release() + print "" + except PySpin.SpinnakerException as ex: + print "Error: {}".format(ex) + result = False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print "Error: {}".format(ex) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: return True if successful, False otherwise + :rtype: bool + """ + result = True + + try: + # Retrieve TL device nodemap and print device information + nodemap_tl_device = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tl_device) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure lookup tables + result &= configure_lookup_tables(nodemap) + if not result: + return result + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tl_device) + + # Reset lookup tables + result &= reset_lookup_tables(nodemap) + + # Deinitialize camera + cam.DeInit() + except PySpin.SpinnakerException as ex: + print "Error: {}".format(ex) + result = False + + return result + + +def main(): + """ + Since this application saves images in the current folder + we must ensure that we have permission to write to this folder. + If we do not have permission, fail right away. + + :return: return True if successful, False otherwise + :rtype: bool + """ + try: + test_file = open("test.txt", "w+") + except IOError: + print "Unable to write to current directory. Please check permissions.\n" + raw_input("Press Enter to exit...") + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print "Library version: {}.{}.{}.{}\n".format(version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print "Number of cameras detected: {}\n".format(num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + # Release system instance + system.ReleaseInstance() + print "Not enough cameras!\n" + raw_input("Done! Press Enter to exit...") + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + print "Running example for camera {}...\n".format(i) + + result &= run_single_camera(cam) + print "Camera {} example complete...\n".format(i) + + # Release reference to camera + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input("Done! Press Enter to exit...") + return result + + +if __name__ == "__main__": + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Network_Classification b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Network_Classification new file mode 100644 index 0000000..a7a5513 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Network_Classification differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Network_Detection b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Network_Detection new file mode 100644 index 0000000..838b384 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Network_Detection differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/NodeMapCallback.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/NodeMapCallback.py new file mode 100644 index 0000000..11bb576 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/NodeMapCallback.py @@ -0,0 +1,424 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# NodeMapCallback.py shows how to use nodemap callbacks. It relies +# on information provided in the Enumeration, Acquisition, and NodeMapInfo +# examples. As callbacks are very similar to events, it may be a good idea to +# explore this example prior to tackling the events examples. +# +# This example focuses on creating, registering, using, and unregistering +# callbacks. A callback requires a callback class with a callback function signature, +# which allows it to be registered to and access a node. Events follow this same pattern. +# +# Once comfortable with NodeMapCallback, we suggest checking out any of the +# events examples: DeviceEvents, EnumerationEvents, ImageEvents, or Logging. + +import PySpin +import sys + + +class HeightNodeCallback(PySpin.NodeCallback): + """ + This is the first of two callback classes. This callback will be registered to the height node. + Node callbacks must inherit from NodeCallback, and must implement CallbackFunction with the same function signature. + + NOTE: Instances of callback classes must not go out of scope until they are deregistered, otherwise segfaults + will occur. + """ + def __init__(self): + super(HeightNodeCallback, self).__init__() + + def CallbackFunction(self, node): + """ + This function gets called when the height node changes and triggers a callback. + + :param node: Height node. + :type node: INode + :rtype: None + """ + node_height = PySpin.CIntegerPtr(node) + print 'Height callback message:\n\tLook! Height changed to %f...\n' % node_height.GetValue() + + +class GainNodeCallback(PySpin.NodeCallback): + """ + This is the second callback class, registered to the gain node. + """ + def __init__(self): + super(GainNodeCallback, self).__init__() + + def CallbackFunction(self, node): + """ + This function gets called when the gain node changes and triggers a callback. + + :param node: Gain node. + :type node: INode + :rtype: None + """ + node_gain = PySpin.CFloatPtr(node) + print 'Gain callback message:\n\tLook! Gain changed to %f...\n' % node_gain.GetValue() + + +def configure_callbacks(nodemap): + """ + This function sets up the example by disabling automatic gain, creating the callbacks, and registering them to + their specific nodes. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :returns: tuple (result, callback_height, callback_gain) + WHERE + result is True if successful, False otherwise + callback_height is the HeightNodeCallback instance registered to the height node + callback_gain is the GainNodeCallback instance registered to the gain node + :rtype: (bool, HeightNodeCallback, GainNodeCallback) + """ + print '\n*** CONFIGURING CALLBACKS ***\n' + try: + result = True + + # Turn off automatic gain + # + # *** NOTES *** + # Automatic gain prevents the manual configuration of gain and needs to + # be turned off for this example. + # + # *** LATER *** + # Automatic exposure is turned off at the end of the example in order + # to restore the camera to its default state. + node_gain_auto = PySpin.CEnumerationPtr(nodemap.GetNode('GainAuto')) + if not PySpin.IsAvailable(node_gain_auto) or not PySpin.IsWritable(node_gain_auto): + print 'Unable to disable automatic gain (node retrieval). Aborting...' + return False + + node_gain_auto_off = PySpin.CEnumEntryPtr(node_gain_auto.GetEntryByName('Off')) + if not PySpin.IsAvailable(node_gain_auto_off) or not PySpin.IsReadable(node_gain_auto_off): + print 'Unable to disable automatic gain (enum entry retrieval). Aborting...' + return False + + node_gain_auto.SetIntValue(node_gain_auto_off.GetValue()) + print 'Automatic gain disabled...' + + # Register callback to height node + # + # *** NOTES *** + # Callbacks need to be registered to nodes, which should be writable + # if the callback is to ever be triggered. Also ensure that the callback + # instance does not go out of scope, as it will get garbage-collected + # and a segfault will result once the callback actually occurs. + # + # *** LATER *** + # Each callback needs to be unregistered individually before releasing + # the system or an exception will be thrown. + node_height = PySpin.CIntegerPtr(nodemap.GetNode('Height')) + if not PySpin.IsAvailable(node_height) or not PySpin.IsWritable(node_height): + print 'Unable to retrieve height. Aborting...\n' + return False + + print 'Height ready...' + + callback_height = HeightNodeCallback() + PySpin.RegisterNodeCallback(node_height.GetNode(), callback_height) + + print 'Height callback registered...' + + # Register callback to gain node + # + # *** NOTES *** + # Depending on the specific goal of the function, it can be important + # to notice the node type that a callback is registered to. Notice in + # the callback functions above that the callback registered to height + # casts its node as an integer whereas the callback registered to gain + # casts as a float. + # + # *** LATER *** + # Each callback needs to be unregistered individually before releasing + # the system or an exception will be thrown. + node_gain = PySpin.CFloatPtr(nodemap.GetNode('Gain')) + if not PySpin.IsAvailable(node_gain) or not PySpin.IsWritable(node_gain): + print 'Unable to retrieve gain. Aborting...\n' + return False + + print 'Gain ready...' + + callback_gain = GainNodeCallback() + PySpin.RegisterNodeCallback(node_gain.GetNode(), callback_gain) + print 'Gain callback registered...\n' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result, callback_height, callback_gain + + +def change_height_and_gain(nodemap): + """ + This function demonstrates the triggering of the nodemap callbacks. First it + changes height, which executes the callback registered to the height node, and + then it changes gain, which executes the callback registered to the gain node. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print '\n***CHANGE HEIGHT & GAIN ***\n' + + try: + result = True + + # Change height to trigger height callback + # + # *** NOTES *** + # Notice that changing the height only triggers the callback function + # registered to the height node. + node_height = PySpin.CIntegerPtr(nodemap.GetNode('Height')) + if not PySpin.IsAvailable(node_height) or not PySpin.IsWritable(node_height) \ + or node_height.GetInc() == 0 or node_height.GetMax() == 0: + + print 'Unable to retrieve height. Aborting...' + return False + + height_to_set = node_height.GetMax() + + print 'Regular function message:\n\tHeight about to be changed to %i...\n' % height_to_set + + node_height.SetValue(height_to_set) + + # Change gain to trigger gain callback + # + # *** NOTES *** + # The same is true of changing the gain node; changing a node will + # only ever trigger the callback function (or functions) currently + # registered to it. + node_gain = PySpin.CFloatPtr(nodemap.GetNode('Gain')) + if not PySpin.IsAvailable(node_gain) or not PySpin.IsWritable(node_gain) or node_gain.GetMax() == 0: + print 'Unable to retrieve gain...' + return False + + gain_to_set = node_gain.GetMax() / 2.0 + + print 'Regular function message:\n\tGain about to be changed to %f...\n' % gain_to_set + node_gain.SetValue(gain_to_set) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def reset_callbacks(nodemap, callback_height, callback_gain): + """ + This function cleans up the example by deregistering the callbacks and + turning automatic gain back on. + + :param nodemap: Device nodemap. + :param callback_height: Height node callback instance to deregister. + :param callback_gain: Gain node callback instance to deregister. + :type nodemap: INodeMap + :type callback_height: HeightNodeCallback + :type callback_gain: GainNodeCallback + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Deregister callbacks + # + # *** NOTES *** + # It is important to deregister each callback function from each node + # that it is registered to. + PySpin.DeregisterNodeCallback(callback_height) + PySpin.DeregisterNodeCallback(callback_gain) + + print 'Callbacks deregistered...' + + # Turn automatic gain back on + # + # *** NOTES *** + # Automatic gain is turned back on in order to restore the camera to + # its default state. + node_gain_auto = PySpin.CEnumerationPtr(nodemap.GetNode('GainAuto')) + if not PySpin.IsAvailable(node_gain_auto) or not PySpin.IsWritable(node_gain_auto): + print 'Unable to enable automatic gain (node retrieval). Aborting...' + return False + + node_gain_auto_continuous = PySpin.CEnumEntryPtr(node_gain_auto.GetEntryByName('Continuous')) + if not PySpin.IsAvailable(node_gain_auto_continuous) or not PySpin.IsReadable(node_gain_auto_continuous): + print 'Unable to enable automatic gain (enum entry retrieval). Aborting...' + return False + + node_gain_auto.SetIntValue(node_gain_auto_continuous.GetValue()) + print 'Automatic gain disabled...' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print '*** DEVICE INFORMATION ***\n' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to setup and run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure callbacks + err, callback_height, callback_gain = configure_callbacks(nodemap) + if not err: + return err + + # Change height and gain to trigger callbacks + result &= change_height_and_gain(nodemap) + + # Reset callbacks + result &= reset_callbacks(nodemap, callback_height, callback_gain) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/NodeMapInfo.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/NodeMapInfo.py new file mode 100644 index 0000000..4c92dce --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/NodeMapInfo.py @@ -0,0 +1,576 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# NodeMapInfo.py shows how to retrieve node map information. It relies +# on information provided in the Enumeration example. Also, check out the +# Acquisition and ExceptionHandling examples if you haven't already. +# Acquisition demonstrates image acquisition while ExceptionHandling shows the +# handling of standard and Spinnaker exceptions. +# +# This example explores retrieving information from all major node types on the +# camera. This includes string, integer, float, boolean, command, enumeration, +# category, and value types. Looping through multiple child nodes is also +# covered. A few node types are not covered - base, port, and register - as +# they are not fundamental. The final node type - enumeration entry - is +# explored only in terms of its parent node type - enumeration. +# +# Once comfortable with NodeMapInfo, we suggest checking out ImageFormatControl +# and Exposure. ImageFormatControl explores customizing image settings on a +# camera while Exposure introduces the standard structure of configuring a +# device, acquiring some images, and then returning the device to a default +# state. + +import PySpin +import sys + +# Defines max number of characters that will be printed out for any node information +MAX_CHARS = 35 + + +class ReadType: + """ + Use the following constants to determine whether nodes are read + as Value nodes or their individual types. + """ + VALUE = 0, + INDIVIDUAL = 1 + +CHOSEN_READ = ReadType.INDIVIDUAL + + +def print_with_indent(level, text): + """ + Helper function for printing a string prefix with a specifc number of indents. + :param level: Number of indents to generate + :type level: int + :param text: String to print after indent + :type text: str + """ + ind = '' + for i in range(level): + ind += ' ' + print '%s%s' % (ind, text) + + +def print_value_node(node, level): + """ + Retrieves and prints the display name and value of all node types as value nodes. + A value node is a general node type that allows for the reading and writing of any node type as a string. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create value node + node_value = PySpin.CValuePtr(node) + + # Retrieve display name + # + # *** NOTES *** + # A node's 'display name' is generally more appropriate for output and + # user interaction whereas its 'name' is what the camera understands. + # Generally, its name is the same as its display name but without + # spaces - for instance, the name of the node that houses a camera's + # serial number is 'DeviceSerialNumber' while its display name is + # 'Device Serial Number'. + display_name = node_value.GetDisplayName() + + # Retrieve value of any node type as string + # + # *** NOTES *** + # Because value nodes return any node type as a string, it can be much + # easier to deal with nodes as value nodes rather than their actual + # individual types. + value = node_value.ToString() + + # Cap length at MAX_CHARS + value = value[:MAX_CHARS] + '...' if len(value) > MAX_CHARS else value + + # Print value + print_with_indent(level, '%s: %s' % (display_name, value)) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_string_node(node, level): + """ + Retrieves and prints the display name and value of a string node. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create string node + node_string = PySpin.CStringPtr(node) + + # Retrieve string node value + # + # *** NOTES *** + # Functions in Spinnaker C++ that use gcstring types + # are substituted with Python strings in PySpin. + # The only exception is shown in the DeviceEvents example, where + # the callback function still uses a wrapped gcstring type. + display_name = node_string.GetDisplayName() + + # Ensure that the value length is not excessive for printing + value = node_string.GetValue() + value = value[:MAX_CHARS] + '...' if len(value) > MAX_CHARS else value + + # Print value; 'level' determines the indentation level of output + print_with_indent(level, '%s: %s' % (display_name, value)) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_integer_node(node, level): + """ + Retrieves and prints the display name and value of an integer node. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create integer node + node_integer = PySpin.CIntegerPtr(node) + + # Get display name + display_name = node_integer.GetDisplayName() + + # Retrieve integer node value + # + # *** NOTES *** + # All node types except base nodes have a ToString() + # method which returns a value as a string. + value = node_integer.GetValue() + + # Print value + print_with_indent(level, '%s: %s' % (display_name, value)) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_float_node(node, level): + """ + Retrieves and prints the display name and value of a float node. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create float node + node_float = PySpin.CFloatPtr(node) + + # Get display name + display_name = node_float.GetDisplayName() + + # Retrieve float value + value = node_float.GetValue() + + # Print value + print_with_indent(level, '%s: %s' % (display_name, value)) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_boolean_node(node, level): + """ + Retrieves and prints the display name and value of a Boolean node. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create Boolean node + node_boolean = PySpin.CBooleanPtr(node) + + # Get display name + display_name = node_boolean.GetDisplayName() + + # Retrieve Boolean value + value = node_boolean.GetValue() + + # Print Boolean value + # NOTE: In Python a Boolean will be printed as "True" or "False". + print_with_indent(level, '%s: %s' % (display_name, value)) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_command_node(node, level): + """ + This function retrieves and prints the display name and tooltip of a command + node, limiting the number of printed characters to a macro-defined maximum. + The tooltip is printed below because command nodes do not have an intelligible + value. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create command node + node_command = PySpin.CCommandPtr(node) + + # Get display name + display_name = node_command.GetDisplayName() + + # Retrieve tooltip + # + # *** NOTES *** + # All node types have a tooltip available. Tooltips provide useful + # information about nodes. Command nodes do not have a method to + # retrieve values as their is no intelligible value to retrieve. + tooltip = node_command.GetToolTip() + + # Ensure that the value length is not excessive for printing + tooltip = tooltip[:MAX_CHARS] + '...' if len(tooltip) > MAX_CHARS else tooltip + + # Print display name and tooltip + print_with_indent(level, '%s: %s' % (display_name, tooltip)) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_enumeration_node_and_current_entry(node, level): + """ + This function retrieves and prints the display names of an enumeration node + and its current entry (which is actually housed in another node unto itself). + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create enumeration node + node_enumeration = PySpin.CEnumerationPtr(node) + + # Retrieve current entry as enumeration node + # + # *** NOTES *** + # Enumeration nodes have three methods to differentiate between: first, + # GetIntValue() returns the integer value of the current entry node; + # second, GetCurrentEntry() returns the entry node itself; and third, + # ToString() returns the symbolic of the current entry. + node_enum_entry = PySpin.CEnumEntryPtr(node_enumeration.GetCurrentEntry()) + + # Get display name + display_name = node_enumeration.GetDisplayName() + + # Retrieve current symbolic + # + # *** NOTES *** + # Rather than retrieving the current entry node and then retrieving its + # symbolic, this could have been taken care of in one step by using the + # enumeration node's ToString() method. + entry_symbolic = node_enum_entry.GetSymbolic() + + # Print current entry symbolic + print_with_indent(level, '%s: %s' % (display_name, entry_symbolic)) + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_category_node_and_all_features(node, level): + """ + This function retrieves and prints out the display name of a category node + before printing all child nodes. Child nodes that are also category nodes are + printed recursively. + + :param node: Category node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create category node + node_category = PySpin.CCategoryPtr(node) + + # Get and print display name + display_name = node_category.GetDisplayName() + print_with_indent(level, display_name) + + # Retrieve and iterate through all children + # + # *** NOTES *** + # The two nodes that typically have children are category nodes and + # enumeration nodes. Throughout the examples, the children of category nodes + # are referred to as features while the children of enumeration nodes are + # referred to as entries. Keep in mind that enumeration nodes can be cast as + # category nodes, but category nodes cannot be cast as enumerations. + for node_feature in node_category.GetFeatures(): + + # Ensure node is available and readable + if not PySpin.IsAvailable(node_feature) or not PySpin.IsReadable(node_feature): + continue + + # Category nodes must be dealt with separately in order to retrieve subnodes recursively. + if node_feature.GetPrincipalInterfaceType() == PySpin.intfICategory: + result &= print_category_node_and_all_features(node_feature, level + 1) + + # Cast all non-category nodes as value nodes + # + # *** NOTES *** + # If dealing with a variety of node types and their values, it may be + # simpler to cast them as value nodes rather than as their individual types. + # However, with this increased ease-of-use, functionality is sacrificed. + elif CHOSEN_READ == ReadType.VALUE: + result &= print_value_node(node_feature, level + 1) + + # Cast all non-category nodes as actual types + elif CHOSEN_READ == ReadType.INDIVIDUAL: + if node_feature.GetPrincipalInterfaceType() == PySpin.intfIString: + result &= print_string_node(node_feature, level + 1) + elif node_feature.GetPrincipalInterfaceType() == PySpin.intfIInteger: + result &= print_integer_node(node_feature, level + 1) + elif node_feature.GetPrincipalInterfaceType() == PySpin.intfIFloat: + result &= print_float_node(node_feature, level + 1) + elif node_feature.GetPrincipalInterfaceType() == PySpin.intfIBoolean: + result &= print_boolean_node(node_feature, level + 1) + elif node_feature.GetPrincipalInterfaceType() == PySpin.intfICommand: + result &= print_command_node(node_feature, level + 1) + elif node_feature.GetPrincipalInterfaceType() == PySpin.intfIEnumeration: + result &= print_enumeration_node_and_current_entry(node_feature, level + 1) + + print '' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example. First nodes from the TL + device and TL stream nodemaps are retrieved and printed. Following this, + the camera is initialized and then nodes from the GenICam nodemap are + retrieved and printed. + + :param cam: Camera to get nodemaps from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + level = 0 + + # Retrieve TL device nodemap + # + # *** NOTES *** + # The TL device nodemap is available on the transport layer. As such, + # camera initialization is unnecessary. It provides mostly immutable + # information fundamental to the camera such as the serial number, + # vendor, and model. + print '\n*** PRINTING TRANSPORT LAYER DEVICE NODEMAP *** \n' + + nodemap_gentl = cam.GetTLDeviceNodeMap() + + result &= print_category_node_and_all_features(nodemap_gentl.GetNode('Root'), level) + + # Retrieve TL stream nodemap + # + # *** NOTES *** + # The TL stream nodemap is also available on the transport layer. Camera + # initialization is again unnecessary. As you can probably guess, it + # provides information on the camera's streaming performance at any + # given moment. Having this information available on the transport layer + # allows the information to be retrieved without affecting camera performance. + print '*** PRINTING TL STREAM NODEMAP ***\n' + + nodemap_tlstream = cam.GetTLStreamNodeMap() + + result &= print_category_node_and_all_features(nodemap_tlstream.GetNode('Root'), level) + + # Initialize camera + # + # *** NOTES *** + # The camera becomes connected upon initialization. This provides + # access to configurable options and additional information, accessible + # through the GenICam nodemap. + # + # *** LATER *** + # Cameras should be deinitialized when no longer needed. + print '*** PRINTING GENICAM NODEMAP ***\n' + + cam.Init() + + # Retrieve GenICam nodemap + # + # *** NOTES *** + # The GenICam nodemap is the primary gateway to customizing + # and configuring the camera to suit your needs. Configuration options + # such as image height and width, trigger mode enabling and disabling, + # and the sequencer are found on this nodemap. + nodemap_applayer = cam.GetNodeMap() + + result &= print_category_node_and_all_features(nodemap_applayer.GetNode('Root'), level) + + # Deinitialize camera + # + # *** NOTES *** + # Camera deinitialization helps ensure that devices clean up properly + # and do not need to be power-cycled to maintain integrity. + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return True + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/NodeMapInfo_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/NodeMapInfo_QuickSpin.py new file mode 100644 index 0000000..7fdc063 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/NodeMapInfo_QuickSpin.py @@ -0,0 +1,359 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# NodeMapInfo_QuickSpin.py shows how to interact with nodes +# using the QuickSpin API. QuickSpin is a subset of the Spinnaker library +# that allows for simpler node access and control. +# +# This example demonstrates the retrieval of information from both the +# transport layer and the camera. Because the focus of this example is node +# access, which is where QuickSpin and regular Spinnaker differ, this +# example differs from NodeMapInfo quite a bit. +# +# A much wider range of topics is covered in the full Spinnaker examples than +# in the QuickSpin ones. There are only enough QuickSpin examples to +# demonstrate node access and to get started with the API; please see full +# Spinnaker examples for further or specific knowledge on a topic. + +import PySpin +import sys + + +def print_transport_layer_device_info(cam): + """ + Prints device information from the transport layer. + + *** NOTES *** + In QuickSpin, accessing device information on the transport layer is + accomplished via a camera's TLDevice property. The TLDevice property + houses nodes related to general device information such as the three + demonstrated below, device access status, XML and GUI paths and + locations, and GEV information to name a few. The TLDevice property + allows access to nodes that would generally be retrieved through the + TL device nodemap in full Spinnaker. + + Notice that each node is checked for availability and readability + prior to value retrieval. Checking for availability and readability + (or writability when applicable) whenever a node is accessed is + important in terms of error handling. If a node retrieval error + occurs but remains unhandled, an exception is thrown. + + :param cam: Camera to get information from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Print device serial number + if cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + print 'Device serial number: %s' % cam.TLDevice.DeviceSerialNumber.ToString() + + else: + print 'Device serial number: unavailable' + result = False + + # Print device vendor name + # + # *** NOTE *** + # To check node readability/writability, you can either + # compare its access mode with RO, RW, etc. or you can use + # the IsReadable/IsWritable functions on the node. + if PySpin.IsReadable(cam.TLDevice.DeviceVendorName): + print 'Device vendor name: %s' % cam.TLDevice.DeviceVendorName.ToString() + else: + print 'Device vendor name: unavailable' + result = False + + # Print device display name + if PySpin.IsReadable(cam.TLDevice.DeviceDisplayName): + print 'Device display name: %s' % cam.TLDevice.DeviceDisplayName.ToString() + else: + print 'Device display name: unavailable' + result = False + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_transport_layer_stream_info(cam): + """ + Prints stream information from transport layer. + + *** NOTES *** + In QuickSpin, accessing stream information on the transport layer is + accomplished via a camera's TLStream property. The TLStream property + houses nodes related to streaming such as the two demonstrated below, + buffer information, and GEV packet information to name a few. The + TLStream property allows access to nodes that would generally be + retrieved through the TL stream nodemap in full Spinnaker. + + :param cam: Camera to get information from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Print stream ID + if cam.TLStream.StreamID.GetAccessMode() == PySpin.RO: + print 'Stream ID: %s' % cam.TLStream.StreamID.ToString() + else: + print 'Stream ID: unavailable' + result = False + + # Print stream type + if PySpin.IsReadable(cam.TLStream.StreamType): + print 'Stream type: %s' % cam.TLStream.StreamType.ToString() + else: + print 'Stream type: unavailable' + result = False + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_transport_layer_interface_info(interface): + """ + Prints stream information from the transport layer. + + *** NOTES *** + In QuickSpin, accessing interface information is accomplished via an + interface's TLInterface property. The TLInterface property houses + nodes that hold information about the interface such as the three + demonstrated below, other general interface information, and + GEV addressing information. The TLInterface property allows access to + nodes that would generally be retrieved through the interface nodemap + in full Spinnaker. + + Interface nodes should also always be checked for availability and + readability (or writability when applicable). If a node retrieval + error occurs but remains unhandled, an exception is thrown. + + :param interface: Interface to get information from. + :type interface: InterfacePtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Print interface display name + if interface.TLInterface.InterfaceDisplayName.GetAccessMode() == PySpin.RO: + print 'Interface display name: %s' % interface.TLInterface.InterfaceDisplayName.ToString() + else: + print 'Interface display name: unavailable' + result = False + + # Print interface ID + if interface.TLInterface.InterfaceID.GetAccessMode() == PySpin.RO: + print 'Interface ID: %s' % interface.TLInterface.InterfaceID.ToString() + else: + print 'Interface ID: unavailable' + result = False + + # Print interface type + if PySpin.IsReadable(interface.TLInterface.InterfaceType.GetAccessMode()): + print 'Interface type: %s' % interface.TLInterface.InterfaceType.ToString() + else: + print 'Interface type: unavailable' + result = False + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_genicam_device_info(cam): + """ + Prints device information from the camera. + + *** NOTES *** + Most camera interaction happens through GenICam nodes. The + advantages of these nodes is that there is a lot more of them, they + allow for a much deeper level of interaction with a camera, and no + intermediate property (i.e. TLDevice or TLStream) is required. The + disadvantage is that they require initialization. + + :param cam: Camera to get information from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Print exposure time + if cam.ExposureTime.GetAccessMode() == PySpin.RO or cam.ExposureTime.GetAccessMode() == PySpin.RW: + print 'Exposure time: %s' % cam.ExposureTime.ToString() + else: + print 'Exposure time: unavailable' + result = False + + # Print black level + if PySpin.IsReadable(cam.BlackLevel): + print 'Black level: %s' % cam.BlackLevel.ToString() + else: + print 'Black level: unavailable' + result = False + + # Print height + if PySpin.IsReadable(cam.Height): + print 'Height: %s' % cam.Height.ToString() + else: + print 'Height: unavailable' + result = False + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def main(): + """ + Example entry point; this function prints transport layer information from + each interface and transport and GenICam information from each camera. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + sys = PySpin.System.GetInstance() + + # Get current library version + version = sys.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = sys.GetCameras() + + num_cams = cam_list.GetSize() + + print 'Number of cameras detected: %i \n' % num_cams + + # Finish if there are no cameras + if num_cams == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + sys.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('\nDone! Press Enter to exit...') + return False + + # Retrieve list of interfaces from the system + iface_list = sys.GetInterfaces() + + num_ifaces = iface_list.GetSize() + + print 'Number of interfaces detected: %i \n' % num_ifaces + + # Print information on each interface + # + # *** NOTES *** + # All USB 3 Vision and GigE Vision interfaces should enumerate for + # Spinnaker. + print '\n*** PRINTING INTERFACE INFORMATION ***\n' + + for iface in iface_list: + result &= print_transport_layer_interface_info(iface) + + # Release reference to interface + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del iface + + # Print general device information on each camera from transport layer + # + # *** NOTES *** + # Transport layer nodes do not require initialization in order to interact + # with them. + print '\n*** PRINTING TRANSPORT LAYER DEVICE INFORMATION ***\n' + + for cam in cam_list: + result &= print_transport_layer_device_info(cam) + + # Print streaming information on each camera from transport layer + # + # *** NOTES *** + # Again, initialization is not required to print information from the + # transport layer; this is equally true of streaming information. + print '\n*** PRINTING TRANSPORT LAYER STREAMING INFORMATION ***\n' + + for cam in cam_list: + result &= print_transport_layer_stream_info(cam) + + # Print device information on each camera from GenICam nodemap + # + # *** NOTES *** + # GenICam nodes require initialization in order to interact with + # them; as such, this loop initializes the camera, prints some information + # from the GenICam nodemap, and then deinitializes it. If the camera were + # not initialized, node availability would fail. + print '\n*** PRINTING GENICAM INFORMATION ***\n' + + for cam in cam_list: + # Initialize camera + cam.Init() + + # Print info + result &= print_genicam_device_info(cam) + + # Deinitialize camera + cam.DeInit() + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Clear interface list before releasing system + iface_list.Clear() + + # Release system instance + sys.ReleaseInstance() + + raw_input('\nDone! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/SaveToAvi.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/SaveToAvi.py new file mode 100644 index 0000000..338b834 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/SaveToAvi.py @@ -0,0 +1,378 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# SaveToAvi.py shows how to create an AVI video from a vector of +# images. It relies on information provided in the Enumeration, Acquisition, +# and NodeMapInfo examples. +# +# This example introduces the SpinVideo class, which is used to quickly and +# easily create various types of AVI videos. It demonstrates the creation of +# three types: uncompressed, MJPG, and H264. + +import PySpin +import sys + + +class AviType: + """'Enum' to select AVI video type to be created and saved""" + UNCOMPRESSED = 0 + MJPG = 1 + H264 = 2 + +chosenAviType = AviType.UNCOMPRESSED # change me! +NUM_IMAGES = 10 # number of images to use in AVI file + + +def save_list_to_avi(nodemap, nodemap_tldevice, images): + """ + This function prepares, saves, and cleans up an AVI video from a vector of images. + + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :param images: List of images to save to an AVI video. + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :type images: list of ImagePtr + :return: True if successful, False otherwise. + :rtype: bool + """ + print '*** CREATING VIDEO ***' + + try: + result = True + + # Retrieve device serial number for filename + device_serial_number = '' + node_serial = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + + if PySpin.IsAvailable(node_serial) and PySpin.IsReadable(node_serial): + device_serial_number = node_serial.GetValue() + print 'Device serial number retrieved as %s...' % device_serial_number + + # Get the current frame rate; acquisition frame rate recorded in hertz + # + # *** NOTES *** + # The video frame rate can be set to anything; however, in order to + # have videos play in real-time, the acquisition frame rate can be + # retrieved from the camera. + + node_acquisition_framerate = PySpin.CFloatPtr(nodemap.GetNode('AcquisitionFrameRate')) + + if not PySpin.IsAvailable(node_acquisition_framerate) and not PySpin.IsReadable(node_acquisition_framerate): + print 'Unable to retrieve frame rate. Aborting...' + return False + + framerate_to_set = node_acquisition_framerate.GetValue() + + print 'Frame rate to be set to %d...' % framerate_to_set + + # Select option and open AVI filetype with unique filename + # + # *** NOTES *** + # Depending on the filetype, a number of settings need to be set in + # an object called an option. An uncompressed option only needs to + # have the video frame rate set whereas videos with MJPG or H264 + # compressions should have more values set. + # + # Once the desired option object is configured, open the AVI file + # with the option in order to create the image file. + # + # Note that the filename does not need to be appended to the + # name of the file. This is because the AVI recorder object takes care + # of the file extension automatically. + # + # *** LATER *** + # Once all images have been added, it is important to close the file - + # this is similar to many other standard file streams. + + avi_recorder = PySpin.SpinVideo() + + if chosenAviType == AviType.UNCOMPRESSED: + avi_filename = 'SaveToAvi-Uncompressed-%s' % device_serial_number + + option = PySpin.AVIOption() + option.frameRate = framerate_to_set + + elif chosenAviType == AviType.MJPG: + avi_filename = 'SaveToAvi-MJPG-%s' % device_serial_number + + option = PySpin.MJPGOption() + option.frameRate = framerate_to_set + option.quality = 75 + + elif chosenAviType == AviType.H264: + avi_filename = 'SaveToAvi-H264-%s' % device_serial_number + + option = PySpin.H264Option() + option.frameRate = framerate_to_set + option.bitrate = 1000000 + option.height = images[0].GetHeight() + option.width = images[0].GetWidth() + + else: + print 'Error: Unknown AviType. Aborting...' + return False + + avi_recorder.Open(avi_filename, option) + + # Construct and save AVI video + # + # *** NOTES *** + # Although the video file has been opened, images must be individually + # appended in order to construct the video. + print 'Appending %d images to AVI file: %s.avi...' % (len(images), avi_filename) + + for i in range(len(images)): + avi_recorder.Append(images[i]) + print 'Appended image %d...' % i + + # Close AVI file + # + # *** NOTES *** + # Once all images have been appended, it is important to close the + # AVI file. Notice that once an AVI file has been closed, no more + # images can be added. + + avi_recorder.Close() + print 'Video saved at %s.avi' % avi_filename + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print '\n*** DEVICE INFORMATION ***\n' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def acquire_images(cam, nodemap): + """ + This function acquires 10 images from a device, stores them in a list, and returns the list. + please see the Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print '*** IMAGE ACQUISITION ***\n' + try: + result = True + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (enum retrieval). Aborting...' + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable(node_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (entry retrieval). Aborting...' + return False + + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Retrieve, convert, and save images + images = list() + + for i in range(NUM_IMAGES): + try: + # Retrieve next received image + image_result = cam.GetNextImage(1000) + + # Ensure image completion + if image_result.IsIncomplete(): + print 'Image incomplete with image status %d...' % image_result.GetImageStatus() + + else: + # Print image information; height and width recorded in pixels + width = image_result.GetWidth() + height = image_result.GetHeight() + print 'Grabbed Image %d, width = %d, height = %d' % (i, width, height) + + # Convert image to mono 8 and append to list + images.append(image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR)) + + # Release image + image_result.Release() + print '' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result, images + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run example on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Acquire list of images + err, images = acquire_images(cam, nodemap) + if err < 0: + return err + + result &= save_list_to_avi(nodemap, nodemap_tldevice, images) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected:', num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Sequencer.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Sequencer.py new file mode 100644 index 0000000..1f8e97c --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Sequencer.py @@ -0,0 +1,873 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Sequencer.py shows how to use the sequencer to grab images with +# various settings. It relies on information provided in the Enumeration, +# Acquisition, and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the ImageFormatControl +# and Exposure examples as these examples provide a strong introduction to +# camera customization. +# +# The sequencer is another very powerful tool, which can be used to create +# and store multiple states of customized image settings. A very useful +# application of the sequencer is creating high dynamic range images. +# +# This example is probably the most complex and definitely the longest. As +# such, the configuration has been split between three functions. The first +# prepares the camera to set the sequences, the second sets the settings for +# a single state (it is run five times), and the third configures the +# camera to use the sequencer when it acquires images. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def print_retrieve_node_failure(node, name): + """" + This function handles the error prints when a node or entry is unavailable or + not readable on the connected camera. + + :param node: Node type. "Node' or 'Entry' + :param name: Node name. + :type node: String + :type name: String + :rtype: None + """ + print 'Unable to get {} ({} {} retrieval failed.)'.format(node, name, node) + print 'The {} may not be available on all camera models...'.format(node) + print 'Please try a Blackfly S camera.' + + +def configure_sequencer_part_one(nodemap): + """" + This function prepares the sequencer to accept custom configurations by + ensuring sequencer mode is off (this is a requirement to the enabling of + sequencer configuration mode), disabling automatic gain and exposure, and + turning sequencer configuration mode on. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '*** CONFIGURING SEQUENCER ***\n' + try: + result = True + + # Ensure sequencer is off for configuration + # + # *** NOTES *** + # In order to configure a new sequence, sequencer configuration mode + # needs to be turned on. To do this, sequencer mode must be disabled. + # However, simply disabling sequencer mode might throw an exception if + # the current sequence is an invalid configuration. + # + # Thus, in order to ensure that sequencer mode is disabled, we first + # check whether the current sequence is valid. If it + # isn't, then we know that sequencer mode is off and we can move on; + # if it is, then we can manually disable sequencer mode. + # + # Also note that sequencer configuration mode needs to be off in order + # to manually disable sequencer mode. It should be off by default, so + # the example skips checking this. + # + # Validate sequencer configuration + node_sequencer_configuration_valid = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerConfigurationValid')) + if not PySpin.IsAvailable(node_sequencer_configuration_valid) \ + or not PySpin.IsReadable(node_sequencer_configuration_valid): + print_retrieve_node_failure('node', 'SequencerConfigurationValid') + return False + + sequencer_configuration_valid_yes = node_sequencer_configuration_valid.GetEntryByName('Yes') + if not PySpin.IsAvailable(sequencer_configuration_valid_yes) \ + or not PySpin.IsReadable(sequencer_configuration_valid_yes): + print_retrieve_node_failure('entry', 'SequencerConfigurationValid Yes') + return False + + # If valid, disable sequencer mode; otherwise, do nothing + node_sequencer_mode = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerMode')) + if node_sequencer_configuration_valid.GetCurrentEntry().GetValue() == \ + sequencer_configuration_valid_yes.GetValue(): + if not PySpin.IsAvailable(node_sequencer_mode) or not PySpin.IsWritable(node_sequencer_mode): + print_retrieve_node_failure('node', 'SequencerMode') + return False + + sequencer_mode_off = node_sequencer_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(sequencer_mode_off) or not PySpin.IsReadable(sequencer_mode_off): + print_retrieve_node_failure('entry', 'SequencerMode Off') + return False + + node_sequencer_mode.SetIntValue(sequencer_mode_off.GetValue()) + + print 'Sequencer mode disabled...' + + # Turn off automatic exposure + # + # *** NOTES *** + # Automatic exposure prevents the manual configuration of exposure + # times and needs to be turned off for this example. + # + # *** LATER *** + # Automatic exposure is turned back on at the end of the example in + # order to restore the camera to its default state. + node_exposure_auto = PySpin.CEnumerationPtr(nodemap.GetNode('ExposureAuto')) + if not PySpin.IsAvailable(node_exposure_auto) or not PySpin.IsWritable(node_exposure_auto): + print_retrieve_node_failure('node', 'ExposureAuto') + return False + + exposure_auto_off = node_exposure_auto.GetEntryByName('Off') + if not PySpin.IsAvailable(exposure_auto_off) or not PySpin.IsReadable(exposure_auto_off): + print_retrieve_node_failure('entry', 'ExposureAuto Off') + return False + + node_exposure_auto.SetIntValue(exposure_auto_off.GetValue()) + + print 'Automatic exposure disabled...' + + # Turn off automatic gain + # + # *** NOTES *** + # Automatic gain prevents the manual configuration of gain and needs + # to be turned off for this example. + # + # *** LATER *** + # Automatic gain is turned back on at the end of the example in + # order to restore the camera to its default state. + node_gain_auto = PySpin.CEnumerationPtr(nodemap.GetNode('GainAuto')) + if not PySpin.IsAvailable(node_gain_auto) or not PySpin.IsWritable(node_gain_auto): + print_retrieve_node_failure('node', 'GainAuto') + return False + + gain_auto_off = node_gain_auto.GetEntryByName('Off') + if not PySpin.IsAvailable(gain_auto_off) or not PySpin.IsReadable(gain_auto_off): + print_retrieve_node_failure('entry', 'GainAuto Off') + return False + + node_gain_auto.SetIntValue(gain_auto_off.GetValue()) + + print 'Automatic gain disabled...' + + # Turn configuration mode on + # + # *** NOTES *** + # Once sequencer mode is off, enabling sequencer configuration mode + # allows for the setting of each state. + # + # *** LATER *** + # Before sequencer mode is turned back on, sequencer configuration + # mode must be turned back off. + node_sequencer_configuration_mode = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerConfigurationMode')) + if not PySpin.IsAvailable(node_sequencer_configuration_mode) \ + or not PySpin.IsWritable(node_sequencer_configuration_mode): + print_retrieve_node_failure('node', 'SequencerConfigurationMode') + return False + + sequencer_configuration_mode_on = node_sequencer_configuration_mode.GetEntryByName('On') + if not PySpin.IsAvailable(sequencer_configuration_mode_on)\ + or not PySpin.IsReadable(sequencer_configuration_mode_on): + print_retrieve_node_failure('entry', 'SequencerConfigurationMode On') + return False + + node_sequencer_configuration_mode.SetIntValue(sequencer_configuration_mode_on.GetValue()) + + print 'Sequencer configuration mode enabled...\n' + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + result = False + + return result + + +def set_single_state(nodemap, sequence_number, width_to_set, height_to_set, exposure_time_to_set, gain_to_set): + """ + This function sets a single state. It sets the sequence number, applies + custom settings, selects the trigger type and next state number, and saves + the state. The custom values that are applied are all calculated in the + function that calls this one, run_single_camera(). + + :param nodemap: Device nodemap. + :param sequence_number: Sequence number. + :param width_to_set: Width to set for sequencer. + :param height_to_set: Height to set fpr sequencer. + :param exposure_time_to_set: Exposure time to set for sequencer. + :param gain_to_set: Gain to set for sequencer. + :type nodemap: INodeMap + :type sequence_number: int + :type width_to_set: int + :type height_to_set: int + :type exposure_time_to_set: float + :type gain_to_set: float + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Select the current sequence number + # + # *** NOTES *** + # Select the index of the state to be set. + # + # *** LATER *** + # The next state - i.e. the state to be linked to - + # also needs to be set before saving the current state. + node_sequencer_set_selector = PySpin.CIntegerPtr(nodemap.GetNode('SequencerSetSelector')) + if not PySpin.IsAvailable(node_sequencer_set_selector) or not PySpin.IsWritable(node_sequencer_set_selector): + print_retrieve_node_failure('node', 'SequencerSetSelector') + return False + + node_sequencer_set_selector.SetValue(sequence_number) + + print 'Setting state {}...'.format(sequence_number) + + # Set desired settings for the current state + # + # *** NOTES *** + # Width, height, exposure time, and gain are set in this example. If + # the sequencer isn't working properly, it may be important to ensure + # that each feature is enabled on the sequencer. Features are enabled + # by default, so this is not explored in this example. + # + # Changing the height and width for the sequencer is not available + # for all camera models. + # + # Set width; width recorded in pixels + node_width = PySpin.CIntegerPtr(nodemap.GetNode('Width')) + if PySpin.IsAvailable(node_width) and PySpin.IsWritable(node_width): + width_inc = node_width.GetInc() + + if width_to_set % width_inc != 0: + width_to_set = (width_to_set / width_inc) * width_inc + + node_width.SetValue(width_to_set) + + print '\tWidth set to {}...'.format(node_width.GetValue()) + + else: + print '\tUnable to set width; width for sequencer not available on all camera models...' + + # Set height; height recorded in pixels + node_height = PySpin.CIntegerPtr(nodemap.GetNode('Height')) + if PySpin.IsAvailable(node_height) and PySpin.IsWritable(node_height): + height_inc = node_height.GetInc() + + if height_to_set % height_inc != 0: + height_to_set = (height_to_set / height_inc) * height_inc + + node_height.SetValue(height_to_set) + + print '\tHeight set to %d...' % node_height.GetValue() + + else: + print '\tUnable to set height; height for sequencer not available on all camera models...' + + # Set exposure time; exposure time recorded in microseconds + node_exposure_time = PySpin.CFloatPtr(nodemap.GetNode('ExposureTime')) + if not PySpin.IsAvailable(node_exposure_time) or not PySpin.IsWritable(node_exposure_time): + print_retrieve_node_failure('node', 'ExposureTime') + return False + + exposure_time_max = node_exposure_time.GetMax() + + if exposure_time_to_set > exposure_time_max: + exposure_time_to_set = exposure_time_max + + node_exposure_time.SetValue(exposure_time_to_set) + + print '\tExposure set to {0:.0f}...'.format(node_exposure_time.GetValue()) + + # Set gain; gain recorded in decibels + node_gain = PySpin.CFloatPtr(nodemap.GetNode('Gain')) + if not PySpin.IsAvailable(node_gain) or not PySpin.IsWritable(node_gain): + print_retrieve_node_failure('node', 'Gain') + return False + + gain_max = node_gain.GetMax() + + if gain_to_set > gain_max: + gain_to_set = gain_max + + node_gain.SetValue(gain_to_set) + + print '\tGain set to {0:.5f}...'.format(node_gain.GetValue()) + + # Set the trigger type for the current state + # + # *** NOTES *** + # It is a requirement of every state to have its trigger source set. + # The trigger source refers to the moment when the sequencer changes + # from one state to the next. + node_sequencer_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerTriggerSource')) + if not PySpin.IsAvailable(node_sequencer_trigger_source) or not PySpin.IsWritable(node_sequencer_trigger_source): + print_retrieve_node_failure('node', 'SequencerTriggerSource') + return False + + sequencer_trigger_source_frame_start = node_sequencer_trigger_source.GetEntryByName('FrameStart') + if not PySpin.IsAvailable(sequencer_trigger_source_frame_start) or \ + not PySpin.IsReadable(sequencer_trigger_source_frame_start): + print_retrieve_node_failure('entry', 'SequencerTriggerSource FrameStart') + return False + + node_sequencer_trigger_source.SetIntValue(sequencer_trigger_source_frame_start.GetValue()) + + print '\tTrigger source set to start of frame...' + + # Set the next state in the sequence + # + # *** NOTES *** + # When setting the next state in the sequence, ensure it does not + # exceed the maximum and that the states loop appropriately. + final_sequence_index = 4 + + node_sequencer_set_next = PySpin.CIntegerPtr(nodemap.GetNode('SequencerSetNext')) + if not PySpin.IsAvailable(node_sequencer_set_next) or not PySpin.IsWritable(node_sequencer_set_next): + print 'Unable to select next state. Aborting...\n' + return False + + if sequence_number == final_sequence_index: + node_sequencer_set_next.SetValue(0) + else: + node_sequencer_set_next.SetValue(sequence_number + 1) + + print '\tNext state set to {}...'.format(node_sequencer_set_next.GetValue()) + + # Save current state + # + # *** NOTES *** + # Once all appropriate settings have been configured, make sure to + # save the state to the sequence. Notice that these settings will be + # lost when the camera is power-cycled. + node_sequencer_set_save = PySpin.CCommandPtr(nodemap.GetNode('SequencerSetSave')) + if not PySpin.IsAvailable(node_sequencer_set_save) or not PySpin.IsWritable(node_sequencer_set_save): + print 'Unable to save state. Aborting...\n' + return False + + node_sequencer_set_save.Execute() + + print 'Current state saved...\n' + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + result = False + + return result + + +def configure_sequencer_part_two(nodemap): + """" + Now that the states have all been set, this function readies the camera + to use the sequencer during image acquisition. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Turn configuration mode off + # + # *** NOTES *** + # Once all desired states have been set, turn sequencer + # configuration mode off in order to turn sequencer mode on. + node_sequencer_configuration_mode = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerConfigurationMode')) + if not PySpin.IsAvailable(node_sequencer_configuration_mode) \ + or not PySpin.IsWritable(node_sequencer_configuration_mode): + print_retrieve_node_failure('node', 'SequencerConfigurationMode') + return False + + sequencer_configuration_mode_off = node_sequencer_configuration_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(sequencer_configuration_mode_off)\ + or not PySpin.IsReadable(sequencer_configuration_mode_off): + print_retrieve_node_failure('entry', 'SequencerConfigurationMode Off') + return False + + node_sequencer_configuration_mode.SetIntValue(sequencer_configuration_mode_off.GetValue()) + + print 'Sequencer configuration mode disabled...' + + # Turn sequencer mode on + # + # *** NOTES *** + # After sequencer mode has been turned on, the camera will begin using the + # saved states in the order that they were set. + # + # *** LATER *** + # Once all images have been captured, disable the sequencer in order + # to restore the camera to its initial state. + node_sequencer_mode = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerMode')) + if not PySpin.IsAvailable(node_sequencer_mode) or not PySpin.IsWritable(node_sequencer_mode): + print_retrieve_node_failure('node', 'SequencerMode') + return False + + sequencer_mode_on = node_sequencer_mode.GetEntryByName('On') + if not PySpin.IsAvailable(sequencer_mode_on) or not PySpin.IsReadable(sequencer_mode_on): + print_retrieve_node_failure('entry', 'SequencerMode On') + return False + + node_sequencer_mode.SetIntValue(sequencer_mode_on.GetValue()) + + print 'Sequencer mode enabled...' + + # Validate sequencer settings + # + # *** NOTES *** + # Once all states have been set, it is a good idea to + # validate them. Although this node cannot ensure that the states + # have been set up correctly, it does ensure that the states have + # been set up in such a way that the camera can function. + node_sequencer_configuration_valid = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerConfigurationValid')) + if not PySpin.IsAvailable(node_sequencer_configuration_valid) \ + or not PySpin.IsReadable(node_sequencer_configuration_valid): + print_retrieve_node_failure('node', 'SequencerConfigurationValid') + return False + + sequencer_configuration_valid_yes = node_sequencer_configuration_valid.GetEntryByName('Yes') + if not PySpin.IsAvailable(sequencer_configuration_valid_yes) \ + or not PySpin.IsReadable(sequencer_configuration_valid_yes): + print_retrieve_node_failure('entry', 'SequencerConfigurationValid Yes') + return False + + if node_sequencer_configuration_valid.GetCurrentEntry().GetValue() != \ + sequencer_configuration_valid_yes.GetValue(): + print 'Sequencer configuration not valid. Aborting...\n' + return False + + print 'Sequencer configuration valid...\n' + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + result = False + + return result + + +def reset_sequencer(nodemap): + """" + This function restores the camera to its default state by turning sequencer mode + off and re-enabling automatic exposure and gain. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Turn sequencer mode back off + # + # *** NOTES *** + # The sequencer is turned off in order to return the camera to its default state. + node_sequencer_mode = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerMode')) + if not PySpin.IsAvailable(node_sequencer_mode) or not PySpin.IsWritable(node_sequencer_mode): + print_retrieve_node_failure('node', 'SequencerMode') + return False + + sequencer_mode_off = node_sequencer_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(sequencer_mode_off) or not PySpin.IsReadable(sequencer_mode_off): + print_retrieve_node_failure('entry', 'SequencerMode Off') + return False + + node_sequencer_mode.SetIntValue(sequencer_mode_off.GetValue()) + + print 'Turning off sequencer mode...' + + # Turn automatic exposure back on + # + # *** NOTES *** + # Automatic exposure is turned on in order to return the camera to its default state. + node_exposure_auto = PySpin.CEnumerationPtr(nodemap.GetNode('ExposureAuto')) + if PySpin.IsAvailable(node_exposure_auto) and PySpin.IsWritable(node_exposure_auto): + exposure_auto_continuous = node_exposure_auto.GetEntryByName('Continuous') + if PySpin.IsAvailable(exposure_auto_continuous) and PySpin.IsReadable(exposure_auto_continuous): + node_exposure_auto.SetIntValue(exposure_auto_continuous.GetValue()) + print 'Turning automatic exposure back on...' + + # Turn automatic gain back on + # + # *** NOTES *** + # Automatic gain is turned on in order to return the camera to its default state. + node_gain_auto = PySpin.CEnumerationPtr(nodemap.GetNode('GainAuto')) + if PySpin.IsAvailable(node_gain_auto) and PySpin.IsWritable(node_gain_auto): + gain_auto_continuous = node_exposure_auto.GetEntryByName('Continuous') + if PySpin.IsAvailable(gain_auto_continuous) and PySpin.IsReadable(gain_auto_continuous): + node_gain_auto.SetIntValue(gain_auto_continuous.GetValue()) + print 'Turning automatic gain mode back on...\n' + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print '*** DEVICE INFORMATION ***\n' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + feature_string = node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable' + print '{}: {}'.format(node_feature.GetName(), feature_string) + + else: + print 'Device control information not available.' + + print '' + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + return False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice, timeout): + """ + This function acquires and saves 10 images from a device. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :param timeout: Timeout for image acquisition. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :type timeout: int + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '*** IMAGE ACQUISITION ***\n' + try: + result = True + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or \ + not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (enum retrieval). Aborting...' + return False + + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or \ + not PySpin.IsReadable(node_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (entry retrieval). Aborting...' + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Retrieve device serial number for filename + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print 'Device serial number retrieved as {}...'.format(device_serial_number) + + print '' + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(timeout) + + if image_result.IsIncomplete(): + print 'Image incomplete with image status {}...'.format(image_result.GetImageStatus()) + + else: + + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print 'Grabbed image {}, width = {}, height = {}'.format(i, width, height) + + # Convert image to mono 8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'Sequencer-{}-{}.jpg'.format(device_serial_number, i) + else: # if serial number is empty + filename = 'Sequencer-{}.jpg'.format(i) + + # Save image + image_converted.Save(filename) + print 'Image saved at {}'.format(filename) + + # Release image + image_result.Release() + print '' + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + return False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts very similarly to the run_single_camera() functions of other + examples, except that the values for the sequences are also calculated here; + please see NodeMapInfo example for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure sequencer to be ready to set sequences + result &= configure_sequencer_part_one(nodemap) + if not result: + return result + + # Set sequences + # + # *** NOTES *** + # In the following section, the sequencer values are calculated. This + # section does not appear in the configuration, as the values + # calculated are somewhat arbitrary: width and height are both set to + # 25% of their maximum values, incrementing by 10%; exposure time is + # set to its minimum, also incrementing by 10% of its maximum; and gain + # is set to its minimum, incrementing by 2% of its maximum. + num_sequences = 5 + + # Retrieve maximum width; width recorded in pixels + node_width = PySpin.CIntegerPtr(nodemap.GetNode('Width')) + if not PySpin.IsAvailable(node_width) or not PySpin.IsReadable(node_width): + print 'Unable to retrieve maximum width. Aborting...\n' + return False + + width_max = node_width.GetMax() + + # Retrieve maximum height; height recorded in pixels + node_height = PySpin.CIntegerPtr(nodemap.GetNode('Height')) + if not PySpin.IsAvailable(node_height) or not PySpin.IsReadable(node_height): + print 'Unable to retrieve maximum height. Aborting...\n' + return False + + height_max = node_height.GetMax() + + # Retrieve maximum exposure time; exposure time recorded in microseconds + exposure_time_max_to_set = 2000000 + + node_exposure_time = PySpin.CFloatPtr(nodemap.GetNode('ExposureTime')) + if not PySpin.IsAvailable(node_exposure_time) or not PySpin.IsReadable(node_exposure_time): + print 'Unable to retrieve maximum exposure time. Aborting...\n' + return False + + exposure_time_max = node_exposure_time.GetMax() + + if exposure_time_max > exposure_time_max_to_set: + exposure_time_max = exposure_time_max_to_set + + # Retrieve maximum gain; gain recorded in decibels + node_gain = PySpin.CFloatPtr(nodemap.GetNode('Gain')) + if not PySpin.IsAvailable(node_exposure_time) or not PySpin.IsReadable(node_exposure_time): + print 'Unable to retrieve maximum gain. Aborting...\n' + return False + + gain_max = node_gain.GetMax() + + # Set initial values + width_to_set = width_max / 4 + height_to_set = height_max / 4 + exposure_time_to_set = node_exposure_time.GetMin() + gain_to_set = node_gain.GetMin() + + # Set custom values of each sequence + for sequence_num in range(num_sequences): + result &= set_single_state(nodemap, + sequence_num, + int(width_to_set), + int(height_to_set), + exposure_time_to_set, + gain_to_set) + if not result: + return result + + # Increment values + width_to_set += width_max / 10 + height_to_set += height_max / 10 + exposure_time_to_set += exposure_time_max / 10.0 + gain_to_set += gain_max / 50.0 + + # Calculate appropriate acquisition grab timeout window based on exposure time + # Note: exposure_time_to_set is in microseconds and needs to be converted to milliseconds + timeout = (exposure_time_to_set / 1000) + 1000 + + # Configure sequencer to acquire images + result &= configure_sequencer_part_two(nodemap) + if not result: + return result + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice, int(timeout)) + + # Reset sequencer + result &= reset_sequencer(nodemap) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: {}'.format(ex) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: {}.{}.{}.{}\n'.format(version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: {}\n'.format(num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera {}...\n'.format(i) + + result &= run_single_camera(cam) + print 'Camera {} example complete...\n'.format(i) + + # Release reference to camera + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/SpinUpdate.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/SpinUpdate.py new file mode 100644 index 0000000..deda1ef --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/SpinUpdate.py @@ -0,0 +1,89 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# SpinUpdate.py is a sample firmware updater application that takes in +# command line arguments. The example also demonstrates usage of callback +# functions to keep track of current update progress. +# +# Run with arguments in format (no quotes): "-R -P -UU " + +import PySpin +import sys + + +last_action = '' + + +def progress_callback(action, address, global_percent, curr_percent): + """ + Example progress callback function. + NOTE: This function must take exactly 4 arguments, + otherwise the update process will hang/crash! + + :param action: Current action being done in firmware update. + :param address: Address in camera being written to. + :param global_percent: Global completion percentage of update. + :param curr_percent: Completion percentage of current action. + :type action: str + :type address: int + :type global_percent: int + :type curr_percent: int + :rtype: int + """ + global last_action + if action != last_action: + # Prints action only if changed from previous one + print 'Action: %s' % action + last_action = action + + return 1 + + +def message_callback(message): + """ + Example message callback function. + NOTE: This function must take exactly 1 argument, + otherwise the update process will hang/crash! + + :param message: Message from updator. + :type message: str + :rtype: None + """ + print 'Message: %s' % message + + return 1 + + +def main(): + # Register callbacks + PySpin.SetProgressCallback(progress_callback) + PySpin.SetMessageCallback(message_callback) + + # Example usage for firmware update: + # Use either UpdateFirmware() or UpdateFirmwareConsole(): + # + # cmd = "-R3932019 C:\\firmware\\bfly2_u3_python1300.zim" # Add -P to argument list for callbacks + # return UpdateFirmware(cmd); + + return PySpin.UpdateFirmwareConsole(sys.argv) # uses command line args + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Trigger.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Trigger.py new file mode 100644 index 0000000..6c4a60b --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Trigger.py @@ -0,0 +1,519 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Trigger.py shows how to trigger the camera. It relies on information +# provided in the Enumeration, Acquisition, and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the ImageFormatControl +# and Exposure examples. As they are somewhat shorter and simpler, either +# provides a strong introduction to camera customization. +# +# This example shows the process of configuring, using, and cleaning up a +# camera for use with both a software and a hardware trigger. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +class TriggerType: + SOFTWARE = 1 + HARDWARE = 2 + + +CHOSEN_TRIGGER = TriggerType.SOFTWARE + + +def configure_trigger(cam): + """ + This function configures the camera to use a trigger. First, trigger mode is + set to off in order to select the trigger source. Once the trigger source + has been selected, trigger mode is then enabled, which has the camera + capture only a single image upon the execution of the chosen trigger. + + :param cam: Camera to configure trigger for. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + print '*** CONFIGURING TRIGGER ***\n' + + print 'Note that if the application / user software triggers faster than frame time, the trigger may be dropped / skipped by the camera.\n' + print 'If several frames are needed per trigger, a more reliable alternative for such case, is to use the multi-frame mode.\n\n' + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + print 'Software trigger chosen ...' + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + print 'Hardware trigger chose ...' + + try: + # Ensure trigger mode off + # The trigger must be disabled in order to configure whether the source + # is software or hardware. + nodemap = cam.GetNodeMap() + node_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(node_trigger_mode) or not PySpin.IsReadable(node_trigger_mode): + print 'Unable to disable trigger mode (node retrieval). Aborting...' + return False + + node_trigger_mode_off = node_trigger_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(node_trigger_mode_off) or not PySpin.IsReadable(node_trigger_mode_off): + print 'Unable to disable trigger mode (enum entry retrieval). Aborting...' + return False + + node_trigger_mode.SetIntValue(node_trigger_mode_off.GetValue()) + + print 'Trigger mode disabled...' + + # Set TriggerSelector to FrameStart + # For this example, the trigger selector should be set to frame start. + # This is the default for most cameras. + node_trigger_selector= PySpin.CEnumerationPtr(nodemap.GetNode('TriggerSelector')) + if not PySpin.IsAvailable(node_trigger_selector) or not PySpin.IsWritable(node_trigger_selector): + print 'Unable to get trigger selector (node retrieval). Aborting...' + return False + + node_trigger_selector_framestart = node_trigger_selector.GetEntryByName('FrameStart') + if not PySpin.IsAvailable(node_trigger_selector_framestart) or not PySpin.IsReadable( + node_trigger_selector_framestart): + print 'Unable to set trigger selector (enum entry retrieval). Aborting...' + return False + node_trigger_selector.SetIntValue(node_trigger_selector_framestart.GetValue()) + + print 'Trigger selector set to frame start...' + + # Select trigger source + # The trigger source must be set to hardware or software while trigger + # mode is off. + node_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerSource')) + if not PySpin.IsAvailable(node_trigger_source) or not PySpin.IsWritable(node_trigger_source): + print 'Unable to get trigger source (node retrieval). Aborting...' + return False + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + node_trigger_source_software = node_trigger_source.GetEntryByName('Software') + if not PySpin.IsAvailable(node_trigger_source_software) or not PySpin.IsReadable( + node_trigger_source_software): + print 'Unable to set trigger source (enum entry retrieval). Aborting...' + return False + node_trigger_source.SetIntValue(node_trigger_source_software.GetValue()) + print 'Trigger source set to software...' + + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + node_trigger_source_hardware = node_trigger_source.GetEntryByName('Line0') + if not PySpin.IsAvailable(node_trigger_source_hardware) or not PySpin.IsReadable( + node_trigger_source_hardware): + print 'Unable to set trigger source (enum entry retrieval). Aborting...' + return False + node_trigger_source.SetIntValue(node_trigger_source_hardware.GetValue()) + print 'Trigger source set to hardware...' + + # Turn trigger mode on + # Once the appropriate trigger source has been set, turn trigger mode + # on in order to retrieve images using the trigger. + node_trigger_mode_on = node_trigger_mode.GetEntryByName('On') + if not PySpin.IsAvailable(node_trigger_mode_on) or not PySpin.IsReadable(node_trigger_mode_on): + print 'Unable to enable trigger mode (enum entry retrieval). Aborting...' + return False + + node_trigger_mode.SetIntValue(node_trigger_mode_on.GetValue()) + print 'Trigger mode turned back on...' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def grab_next_image_by_trigger(nodemap, cam): + """ + This function acquires an image by executing the trigger node. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + # Use trigger to capture image + # The software trigger only feigns being executed by the Enter key; + # what might not be immediately apparent is that there is not a + # continuous stream of images being captured; in other examples that + # acquire images, the camera captures a continuous stream of images. + # When an image is retrieved, it is plucked from the stream. + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + # Get user input + raw_input('Press the Enter key to initiate software trigger.') + + # Execute software trigger + node_softwaretrigger_cmd = PySpin.CCommandPtr(nodemap.GetNode('TriggerSoftware')) + if not PySpin.IsAvailable(node_softwaretrigger_cmd) or not PySpin.IsWritable(node_softwaretrigger_cmd): + print 'Unable to execute trigger. Aborting...' + return False + + node_softwaretrigger_cmd.Execute() + + # TODO: Blackfly and Flea3 GEV cameras need 2 second delay after software trigger + + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + print 'Use the hardware to trigger image acquisition.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device. + Please see Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '*** IMAGE ACQUISITION ***\n' + try: + result = True + + # Set acquisition mode to continuous + # In order to access the node entries, they have to be casted to a pointer type (CEnumerationPtr here) + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print 'Unable to set acquisition mode to continuous (enum retrieval). Aborting...' + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print 'Unable to set acquisition mode to continuous (entry retrieval). Aborting...' + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Retrieve device serial number for filename + # + # *** NOTES *** + # The device serial number is retrieved in order to keep cameras from + # overwriting one another. Grabbing image IDs could also accomplish + # this. + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print 'Device serial number retrieved as %s...' % device_serial_number + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve the next image from the trigger + result &= grab_next_image_by_trigger(nodemap, cam) + + # Retrieve next received image + image_result = cam.GetNextImage(1000) + + # Ensure image completion + if image_result.IsIncomplete(): + print 'Image incomplete with image status %d ...' % image_result.GetImageStatus() + + else: + + # Print image information; height and width recorded in pixels + # + # *** NOTES *** + # Images have quite a bit of available metadata including + # things such as CRC, image status, and offset values, to + # name a few. + width = image_result.GetWidth() + height = image_result.GetHeight() + print 'Grabbed Image %d, width = %d, height = %d' % (i, width, height) + + # Convert image to mono 8 + # + # *** NOTES *** + # Images can be converted between pixel formats by using + # the appropriate enumeration value. Unlike the original + # image, the converted one does not need to be released as + # it does not affect the camera buffer. + # + # When converting images, color processing algorithm is an + # optional parameter. + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'Trigger-%s-%d.jpg' % (device_serial_number, i) + else: # if serial number is empty + filename = 'Trigger-%d.jpg' % i + + # Save image + # + # *** NOTES *** + # The standard practice of the examples is to use device + # serial numbers to keep images of one device from + # overwriting those of another. + image_converted.Save(filename) + print 'Image saved at %s\n' % filename + + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + # End acquisition + # + # *** NOTES *** + # Ending acquisition appropriately helps ensure that devices clean up + # properly and do not need to be power-cycled to maintain integrity. + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def reset_trigger(nodemap): + """ + This function returns the camera to a normal state by turning off trigger mode. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + node_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(node_trigger_mode) or not PySpin.IsReadable(node_trigger_mode): + print 'Unable to disable trigger mode (node retrieval). Aborting...' + return False + + node_trigger_mode_off = node_trigger_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(node_trigger_mode_off) or not PySpin.IsReadable(node_trigger_mode_off): + print 'Unable to disable trigger mode (enum entry retrieval). Aborting...' + return False + + node_trigger_mode.SetIntValue(node_trigger_mode_off.GetValue()) + + print 'Trigger mode disabled...' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print '*** DEVICE INFORMATION ***\n' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + err = False + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure trigger + if configure_trigger(cam) is False: + return False + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Reset trigger + result &= reset_trigger(nodemap) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print 'Unable to write to current directory. Please check permissions.' + raw_input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Trigger_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Trigger_QuickSpin.py new file mode 100644 index 0000000..c409662 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python2/Trigger_QuickSpin.py @@ -0,0 +1,422 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Trigger_QuickSpin.py shows how to capture images with the +# trigger using the QuickSpin API. QuickSpin is a subset of the Spinnaker +# library that allows for simpler node access and control. +# +# This example demonstrates how to prepare, execute, and clean up the camera +# in regards to using both software and hardware triggers. Retrieving and +# setting node values using QuickSpin is the only portion of the example +# that differs from Trigger. +# +# A much wider range of topics is covered in the full Spinnaker examples than +# in the QuickSpin ones. There are only enough QuickSpin examples to +# demonstrate node access and to get started with the API; please see full +# Spinnaker examples for further or specific knowledge on a topic. + +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +class TriggerType: + SOFTWARE = 1 + HARDWARE = 2 + +CHOSEN_TRIGGER = TriggerType.SOFTWARE + + +def configure_trigger(cam): + """ + This function configures the camera to use a trigger. First, trigger mode is + ensured to be off in order to select the trigger source. Trigger mode is + then enabled, which has the camera capture only a single image upon the + execution of the chosen trigger. + + :param cam: Camera to configure trigger for. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '*** CONFIGURING TRIGGER ***\n' + + print 'Note that if the application / user software triggers faster than frame time, the trigger may be dropped / skipped by the camera.\n' + print 'If several frames are needed per trigger, a more reliable alternative for such case, is to use the multi-frame mode.\n\n' + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + print 'Software trigger chosen...' + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + print 'Hardware trigger chosen...' + + try: + result = True + + # Ensure trigger mode off + # The trigger must be disabled in order to configure whether the source + # is software or hardware. + if cam.TriggerMode.GetAccessMode() != PySpin.RW: + print 'Unable to disable trigger mode (node retrieval). Aborting...' + return False + + cam.TriggerMode.SetValue(PySpin.TriggerMode_Off) + + print 'Trigger mode disabled...' + + # Set TriggerSelector to FrameStart + # For this example, the trigger selector should be set to frame start. + # This is the default for most cameras. + if cam.TriggerSelector.GetAccessMode() != PySpin.RW: + print 'Unable to get trigger selector (node retrieval). Aborting...' + return False + + cam.TriggerSource.SetValue(PySpin.TriggerSelector_FrameStart) + + print 'Trigger selector set to frame start...' + + # Select trigger source + # The trigger source must be set to hardware or software while trigger + # mode is off. + if cam.TriggerSource.GetAccessMode() != PySpin.RW: + print 'Unable to get trigger source (node retrieval). Aborting...' + return False + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + cam.TriggerSource.SetValue(PySpin.TriggerSource_Software) + print 'Trigger source set to software...' + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + cam.TriggerSource.SetValue(PySpin.TriggerSource_Line0) + print 'Trigger source set to hardware...' + + # Turn trigger mode on + # Once the appropriate trigger source has been set, turn trigger mode + # on in order to retrieve images using the trigger. + cam.TriggerMode.SetValue(PySpin.TriggerMode_On) + print 'Trigger mode turned back on...' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def grab_next_image_by_trigger(cam): + """ + This function acquires an image by executing the trigger node. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + # Use trigger to capture image + # The software trigger only feigns being executed by the Enter key; + # what might not be immediately apparent is that there is not a + # continuous stream of images being captured; in other examples that + # acquire images, the camera captures a continuous stream of images. + # When an image is retrieved, it is plucked from the stream. + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + # Get user input + raw_input('Press the Enter key to initiate software trigger.') + + # Execute software trigger + if cam.TriggerSoftware.GetAccessMode() != PySpin.WO: + print 'Unable to execute trigger. Aborting...' + return False + + cam.TriggerSoftware.Execute() + + # NOTE: Blackfly and Flea3 GEV cameras need 2 second delay after software trigger + + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + print 'Use the hardware to trigger image acquisition.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def acquire_images(cam): + """ + This function acquires and saves 10 images from a device. + Please see Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + print '*** IMAGE ACQUISITION ***\n' + try: + result = True + + # Set acquisition mode to continuous + if cam.AcquisitionMode.GetAccessMode() != PySpin.RW: + print 'Unable to set acquisition mode to continuous. Aborting...' + return False + + cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous) + print 'Acquisition mode set to continuous...' + + # Begin acquiring images + cam.BeginAcquisition() + + print 'Acquiring images...' + + # Get device serial number for filename + device_serial_number = '' + if cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + device_serial_number = cam.TLDevice.DeviceSerialNumber.GetValue() + + print 'Device serial number retrieved as %s...' % device_serial_number + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve the next image from the trigger + result &= grab_next_image_by_trigger(cam) + + # Retrieve next received image + image_result = cam.GetNextImage(1000) + + # Ensure image completion + if image_result.IsIncomplete(): + print 'Image incomplete with image status %d ...' % image_result.GetImageStatus() + + else: + + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print 'Grabbed Image %d, width = %d, height = %d' % (i, width, height) + + # Convert image to mono 8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'Trigger-%s-%d.jpg' % (device_serial_number, i) + else: # if serial number is empty + filename = 'Trigger-%d.jpg' % i + + # Save image + image_converted.Save(filename) + + print 'Image saved at %s\n' % filename + + # Release image + image_result.Release() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def reset_trigger(cam): + """ + This function returns the camera to a normal state by turning off trigger mode. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :returns: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + # Ensure trigger mode off + # The trigger must be disabled in order to configure whether the source + # is software or hardware. + if cam.TriggerMode.GetAccessMode() != PySpin.RW: + print 'Unable to disable trigger mode (node retrieval). Aborting...' + return False + + cam.TriggerMode.SetValue(PySpin.TriggerMode_Off) + + print 'Trigger mode disabled...' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print '*** DEVICE INFORMATION ***\n' + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print '%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable') + + else: + print 'Device control information not available.' + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + err = False + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure trigger + if configure_trigger(cam) is False: + return False + + # Acquire images + result &= acquire_images(cam) + + # Reset trigger + result &= reset_trigger(cam) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print 'Error: %s' % ex + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print 'Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print 'Number of cameras detected: %d' % num_cameras + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print 'Not enough cameras!' + raw_input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print 'Running example for camera %d...' % i + + result &= run_single_camera(cam) + print 'Camera %d example complete... \n' % i + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + raw_input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/AcquireAndDisplay.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/AcquireAndDisplay.py new file mode 100644 index 0000000..2aee556 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/AcquireAndDisplay.py @@ -0,0 +1,313 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# This AcquireAndDisplay.py shows how to get the image data, and then display images in a GUI. +# This example relies on information provided in the ImageChannelStatistics.py example. +# +# This example demonstrates how to display images represented as numpy arrays. +# Currently, this program is limited to single camera use. +# NOTE: keyboard and matplotlib must be installed on Python interpreter prior to running this example. + +import os +import PySpin +import matplotlib.pyplot as plt +import sys +import keyboard +import time + +global continue_recording +continue_recording = True + + +def handle_close(evt): + """ + This function will close the GUI when close event happens. + + :param evt: Event that occurs when the figure closes. + :type evt: Event + """ + + global continue_recording + continue_recording = False + + +def acquire_and_display_images(cam, nodemap, nodemap_tldevice): + """ + This function continuously acquires images from a device and display them in a GUI. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + global continue_recording + + sNodemap = cam.GetTLStreamNodeMap() + + # Change bufferhandling mode to NewestOnly + node_bufferhandling_mode = PySpin.CEnumerationPtr(sNodemap.GetNode('StreamBufferHandlingMode')) + if not PySpin.IsAvailable(node_bufferhandling_mode) or not PySpin.IsWritable(node_bufferhandling_mode): + print('Unable to set stream buffer handling mode.. Aborting...') + return False + + # Retrieve entry node from enumeration node + node_newestonly = node_bufferhandling_mode.GetEntryByName('NewestOnly') + if not PySpin.IsAvailable(node_newestonly) or not PySpin.IsReadable(node_newestonly): + print('Unable to set stream buffer handling mode.. Aborting...') + return False + + # Retrieve integer value from entry node + node_newestonly_mode = node_newestonly.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_bufferhandling_mode.SetIntValue(node_newestonly_mode) + + print('*** IMAGE ACQUISITION ***\n') + try: + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (enum retrieval). Aborting...') + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...') + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Begin acquiring images + # + # *** NOTES *** + # What happens when the camera begins acquiring images depends on the + # acquisition mode. Single frame captures only a single image, multi + # frame catures a set number of images, and continuous captures a + # continuous stream of images. + # + # *** LATER *** + # Image acquisition must be ended when no more images are needed. + cam.BeginAcquisition() + + print('Acquiring images...') + + # Retrieve device serial number for filename + # + # *** NOTES *** + # The device serial number is retrieved in order to keep cameras from + # overwriting one another. Grabbing image IDs could also accomplish + # this. + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Device serial number retrieved as %s...' % device_serial_number) + + # Close program + print('Press enter to close the program..') + + # Figure(1) is default so you can omit this line. Figure(0) will create a new window every time program hits this line + fig = plt.figure(1) + + # Close the GUI when close event happens + fig.canvas.mpl_connect('close_event', handle_close) + + # Retrieve and display images + while(continue_recording): + try: + + # Retrieve next received image + # + # *** NOTES *** + # Capturing an image houses images on the camera buffer. Trying + # to capture an image that does not exist will hang the camera. + # + # *** LATER *** + # Once an image from the buffer is saved and/or no longer + # needed, the image must be released in order to keep the + # buffer from filling up. + + image_result = cam.GetNextImage(1000) + + # Ensure image completion + if image_result.IsIncomplete(): + print('Image incomplete with image status %d ...' % image_result.GetImageStatus()) + + else: + + # Getting the image data as a numpy array + image_data = image_result.GetNDArray() + + # Draws an image on the current figure + plt.imshow(image_data, cmap='gray') + + # Interval in plt.pause(interval) determines how fast the images are displayed in a GUI + # Interval is in seconds. + plt.pause(0.001) + + # Clear current reference of a figure. This will improve display speed significantly + plt.clf() + + # If user presses enter, close the program + if keyboard.is_pressed('ENTER'): + print('Program is closing...') + + # Close figure + plt.close('all') + input('Done! Press Enter to exit...') + continue_recording=False + + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + # End acquisition + # + # *** NOTES *** + # Ending acquisition appropriately helps ensure that devices clean up + # properly and do not need to be power-cycled to maintain integrity. + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return True + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Acquire images + result &= acquire_and_display_images(cam, nodemap, nodemap_tldevice) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point; notice the volume of data that the logging event handler + prints out on debug despite the fact that very little really happens in this + example. Because of this, it may be better to have the logger set to lower + level in order to provide a more concise, focused log. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Acquisition.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Acquisition.py new file mode 100644 index 0000000..3459923 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Acquisition.py @@ -0,0 +1,372 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Acquisition.py shows how to acquire images. It relies on +# information provided in the Enumeration example. Also, check out the +# ExceptionHandling and NodeMapInfo examples if you haven't already. +# ExceptionHandling shows the handling of standard and Spinnaker exceptions +# while NodeMapInfo explores retrieving information from various node types. +# +# This example touches on the preparation and cleanup of a camera just before +# and just after the acquisition of images. Image retrieval and conversion, +# grabbing image data, and saving images are all covered as well. +# +# Once comfortable with Acquisition, we suggest checking out +# AcquisitionMultipleCamera, NodeMapCallback, or SaveToAvi. +# AcquisitionMultipleCamera demonstrates simultaneously acquiring images from +# a number of cameras, NodeMapCallback serves as a good introduction to +# programming with callbacks and events, and SaveToAvi exhibits video creation. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** IMAGE ACQUISITION ***\n') + try: + result = True + + # Set acquisition mode to continuous + # + # *** NOTES *** + # Because the example acquires and saves 10 images, setting acquisition + # mode to continuous lets the example finish. If set to single frame + # or multiframe (at a lower number of images), the example would just + # hang. This would happen because the example has been written to + # acquire 10 images while the camera would have been programmed to + # retrieve less than that. + # + # Setting the value of an enumeration node is slightly more complicated + # than other node types. Two nodes must be retrieved: first, the + # enumeration node is retrieved from the nodemap; and second, the entry + # node is retrieved from the enumeration node. The integer value of the + # entry node is then set as the new value of the enumeration node. + # + # Notice that both the enumeration and the entry nodes are checked for + # availability and readability/writability. Enumeration nodes are + # generally readable and writable whereas their entry nodes are only + # ever readable. + # + # Retrieve enumeration node from nodemap + + # In order to access the node entries, they have to be casted to a pointer type (CEnumerationPtr here) + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (enum retrieval). Aborting...') + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable(node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...') + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Begin acquiring images + # + # *** NOTES *** + # What happens when the camera begins acquiring images depends on the + # acquisition mode. Single frame captures only a single image, multi + # frame catures a set number of images, and continuous captures a + # continuous stream of images. Because the example calls for the + # retrieval of 10 images, continuous mode has been set. + # + # *** LATER *** + # Image acquisition must be ended when no more images are needed. + cam.BeginAcquisition() + + print('Acquiring images...') + + # Retrieve device serial number for filename + # + # *** NOTES *** + # The device serial number is retrieved in order to keep cameras from + # overwriting one another. Grabbing image IDs could also accomplish + # this. + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Device serial number retrieved as %s...' % device_serial_number) + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve next received image + # + # *** NOTES *** + # Capturing an image houses images on the camera buffer. Trying + # to capture an image that does not exist will hang the camera. + # + # *** LATER *** + # Once an image from the buffer is saved and/or no longer + # needed, the image must be released in order to keep the + # buffer from filling up. + image_result = cam.GetNextImage(1000) + + # Ensure image completion + # + # *** NOTES *** + # Images can easily be checked for completion. This should be + # done whenever a complete image is expected or required. + # Further, check image status for a little more insight into + # why an image is incomplete. + if image_result.IsIncomplete(): + print('Image incomplete with image status %d ...' % image_result.GetImageStatus()) + + else: + + # Print image information; height and width recorded in pixels + # + # *** NOTES *** + # Images have quite a bit of available metadata including + # things such as CRC, image status, and offset values, to + # name a few. + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Grabbed Image %d, width = %d, height = %d' % (i, width, height)) + + # Convert image to mono 8 + # + # *** NOTES *** + # Images can be converted between pixel formats by using + # the appropriate enumeration value. Unlike the original + # image, the converted one does not need to be released as + # it does not affect the camera buffer. + # + # When converting images, color processing algorithm is an + # optional parameter. + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'Acquisition-%s-%d.jpg' % (device_serial_number, i) + else: # if serial number is empty + filename = 'Acquisition-%d.jpg' % i + + # Save image + # + # *** NOTES *** + # The standard practice of the examples is to use device + # serial numbers to keep images of one device from + # overwriting those of another. + image_converted.Save(filename) + print('Image saved at %s' % filename) + + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + print('') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + # End acquisition + # + # *** NOTES *** + # Ending acquisition appropriately helps ensure that devices clean up + # properly and do not need to be power-cycled to maintain integrity. + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print('*** DEVICE INFORMATION ***\n') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/AcquisitionMultipleCamera.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/AcquisitionMultipleCamera.py new file mode 100644 index 0000000..6fd7cc8 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/AcquisitionMultipleCamera.py @@ -0,0 +1,334 @@ +# ============================================================================ +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. + +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================ +# +# AcquisitionMultipleCamera.py shows how to capture images from +# multiple cameras simultaneously. It relies on information provided in the +# Enumeration, Acquisition, and NodeMapInfo examples. +# +# This example reads similarly to the Acquisition example, +# except that loops are used to allow for simultaneous acquisitions. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + +def acquire_images(cam_list): + """ + This function acquires and saves 10 images from each device. + + :param cam_list: List of cameras + :type cam_list: CameraList + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** IMAGE ACQUISITION ***\n') + try: + result = True + + # Prepare each camera to acquire images + # + # *** NOTES *** + # For pseudo-simultaneous streaming, each camera is prepared as if it + # were just one, but in a loop. Notice that cameras are selected with + # an index. We demonstrate pseduo-simultaneous streaming because true + # simultaneous streaming would require multiple process or threads, + # which is too complex for an example. + # + + for i, cam in enumerate(cam_list): + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(cam.GetNodeMap().GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (node retrieval; camera %d). Aborting... \n' % i) + return False + + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry \'continuous\' retrieval %d). \ + Aborting... \n' % i) + return False + + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Camera %d acquisition mode set to continuous...' % i) + + # Begin acquiring images + cam.BeginAcquisition() + + print('Camera %d started acquiring images...' % i) + + print() + + # Retrieve, convert, and save images for each camera + # + # *** NOTES *** + # In order to work with simultaneous camera streams, nested loops are + # needed. It is important that the inner loop be the one iterating + # through the cameras; otherwise, all images will be grabbed from a + # single camera before grabbing any images from another. + for n in range(NUM_IMAGES): + for i, cam in enumerate(cam_list): + try: + # Retrieve device serial number for filename + node_device_serial_number = PySpin.CStringPtr(cam.GetTLDeviceNodeMap().GetNode('DeviceSerialNumber')) + + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Camera %d serial number set to %s...' % (i, device_serial_number)) + + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print('Image incomplete with image status %d ... \n' % image_result.GetImageStatus()) + else: + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Camera %d grabbed image %d, width = %d, height = %d' % (i, n, width, height)) + + # Convert image to mono 8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'AcquisitionMultipleCamera-%s-%d.jpg' % (device_serial_number, n) + else: + filename = 'AcquisitionMultipleCamera-%d-%d.jpg' % (i, n) + + # Save image + image_converted.Save(filename) + print('Image saved at %s' % filename) + + # Release image + image_result.Release() + print() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + # End acquisition for each camera + # + # *** NOTES *** + # Notice that what is usually a one-step process is now two steps + # because of the additional step of selecting the camera. It is worth + # repeating that camera selection needs to be done once per loop. + # + # It is possible to interact with cameras through the camera list with + # GetByIndex(); this is an alternative to retrieving cameras as + # CameraPtr objects that can be quick and easy for small tasks. + for cam in cam_list: + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def print_device_info(nodemap, cam_num): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :param cam_num: Camera number. + :type nodemap: INodeMap + :type cam_num: int + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print('Printing device information for camera %d... \n' % cam_num) + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + print() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + +def run_multiple_cameras(cam_list): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam_list: List of cameras + :type cam_list: CameraList + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve transport layer nodemaps and print device information for + # each camera + # *** NOTES *** + # This example retrieves information from the transport layer nodemap + # twice: once to print device information and once to grab the device + # serial number. Rather than caching the nodem#ap, each nodemap is + # retrieved both times as needed. + print('*** DEVICE INFORMATION ***\n') + + for i, cam in enumerate(cam_list): + + # Retrieve TL device nodemap + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + # Print device information + result &= print_device_info(nodemap_tldevice, i) + + # Initialize each camera + # + # *** NOTES *** + # You may notice that the steps in this function have more loops with + # less steps per loop; this contrasts the AcquireImages() function + # which has less loops but more steps per loop. This is done for + # demonstrative purposes as both work equally well. + # + # *** LATER *** + # Each camera needs to be deinitialized once all images have been + # acquired. + for i, cam in enumerate(cam_list): + + # Initialize camera + cam.Init() + + # Acquire images on all cameras + result &= acquire_images(cam_list) + + # Deinitialize each camera + # + # *** NOTES *** + # Again, each camera must be deinitialized separately by first + # selecting the camera and then deinitializing it. + for cam in cam_list: + + # Deinitialize camera + cam.DeInit() + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on all cameras + print('Running example for all cameras...') + + result = run_multiple_cameras(cam_list) + + print('Example complete... \n') + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/BufferHandling.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/BufferHandling.py new file mode 100644 index 0000000..587038f --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/BufferHandling.py @@ -0,0 +1,493 @@ +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= + +# BufferHandling.py shows how the different buffer handling modes work. +# It relies on information provided in the Acquisition and Trigger examples. +# +# Buffer handling determines the ordering at which images are retrieved, and +# what occurs when an image is transmitted while the buffer is full. There are +# four different buffer handling modes available; NewestFirst, NewestOnly, +# OldestFirst and OldestFirstOverwrite. +# +# This example explores retrieving images in a set pattern; triggering the camera +# while not retrieving an image (letting the buffer fill up), and retrieving +# images while not triggering. We cycle through the different buffer handling +# modes to see which images are retrieved, confirming their identites via their +# Frame ID values. + +import os +import PySpin +import time +import sys + +# Total number of buffers +NUM_BUFFERS = 3 +# Number of triggers +NUM_TRIGGERS = 6 +# Total number of loops +NUM_LOOPS = 9 + +def configure_trigger(nodemap): + """ + This function configures the camera to use a trigger. First, trigger mode is + set to off in order to select the trigger source. Once the trigger source + has been selected, trigger mode is then enabled, which has the camera + capture only a single image upon the execution of the trigger. + + :param nodemap: Device nodemap to retrieve images from. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + try: + result = True + print('\n*** CONFIGURING TRIGGER ***\n') + + # Ensure trigger mode off + # + # *** NOTES *** + # The trigger must be disabled in order to configure the + # trigger source. + trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(trigger_mode) or not PySpin.IsWritable(trigger_mode): + print('Unable to disable trigger mode (node retrieval). Aborting...\n') + return False + + trigger_mode_off = PySpin.CEnumEntryPtr(trigger_mode.GetEntryByName('Off')) + if not PySpin.IsAvailable(trigger_mode_off) or not PySpin.IsReadable(trigger_mode_off): + print('Unable to disable trigger mode (enum entry retrieval). Aborting...\n') + return False + + trigger_mode.SetIntValue(trigger_mode_off.GetValue()) + print('Trigger mode disabled...') + + # Set trigger source to software + trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerSource')) + if not PySpin.IsAvailable(trigger_source) or not PySpin.IsWritable(trigger_source): + print('Unable to set trigger mode (node retrieval). Aborting...') + return False + + trigger_source_software = PySpin.CEnumEntryPtr(trigger_source.GetEntryByName('Software')) + if not PySpin.IsAvailable(trigger_source_software) or not PySpin.IsReadable(trigger_source_software): + print('Unable to set trigger mode (enum entry retrieval). Aborting...') + return False + + trigger_source.SetIntValue(trigger_source_software.GetValue()) + print('Trigger source set to software...') + + # Turn trigger mode on + trigger_mode_on = PySpin.CEnumEntryPtr(trigger_mode.GetEntryByName('On')) + if not PySpin.IsAvailable(trigger_mode_on) or not PySpin.IsReadable(trigger_mode_on): + print('Unable to enable trigger mode (enum entry retrieval). Aborting...\n') + return False + + trigger_mode.SetIntValue(trigger_mode_on.GetValue()) + print('Trigger mode turned back on...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + +def grab_next_image_by_trigger(nodemap): + """ + This function retrieves a single image using the trigger. In this example, + only a single image is captured and made available for acquisition - as such, + attempting to acquire two images for a single trigger execution would cause + the example to hang. This is different from other examples, whereby a + constant stream of images are being captured and made available for image + acquisition. + + :param nodemap: Device nodemap to retrieve images from. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + try: + result = True + + # Execute software trigger + software_trigger_command = PySpin.CCommandPtr(nodemap.GetNode('TriggerSoftware')) + if not PySpin.IsAvailable(software_trigger_command) or not PySpin.IsWritable(software_trigger_command): + print('Unable to execute trigger. Aborting...\n') + return False + + software_trigger_command.Execute() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + +def reset_trigger(nodemap): + """ + This function returns the camera to a normal state by turning off trigger mode. + + :param nodemap: Device nodemap to retrieve images from. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + try: + result = True + + # Turn trigger mode back off + # + # *** NOTES *** + # Once all images have been captured, turn trigger mode back off to + # restore the camera to a clean state. + trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(trigger_mode) or not PySpin.IsWritable(trigger_mode): + print('Unable to disable trigger mode (node retrieval). Non-fatal error...\n') + return False + + trigger_mode_off = PySpin.CEnumEntryPtr(trigger_mode.GetEntryByName('Off')) + if not PySpin.IsAvailable(trigger_mode_off) or not PySpin.IsReadable(trigger_mode_off): + print('Unable to disable trigger mode (enum entry retrieval). Non-fatal error...\n') + return False + + trigger_mode.SetIntValue(trigger_mode_off.GetValue()) + print('Trigger mode disabled...\n') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap from camera. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + print('\n*** DEVICE INFORMATION ***\n') + + # Retrieve and display Device Information + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function cycles through the four different buffer handling modes. + It saves three images for three of the buffer handling modes + (NewestFirst, OldestFirst, and OldestFirstOverwrite). For NewestOnly, + it saves one image. + + :param cam: Camera instance to grab images from. + :param nodemap: Device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + print('\n*** IMAGE ACQUISITION ***\n') + + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (node retrieval). Aborting...') + return False + + # Retrieve entry node from enumeration mode + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...') + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Retrieve device serial number for filename + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Device serial number retrieved as %s...' % device_serial_number) + + # Retrieve Stream Parameters device nodemap + s_node_map = cam.GetTLStreamNodeMap() + + # Retrieve Buffer Handling Mode Information + handling_mode = PySpin.CEnumerationPtr(s_node_map.GetNode('StreamBufferHandlingMode')) + if not PySpin.IsAvailable(handling_mode) or not PySpin.IsWritable(handling_mode): + print('Unable to set Buffer Handling mode (node retrieval). Aborting...\n') + return False + + handling_mode_entry = PySpin.CEnumEntryPtr(handling_mode.GetCurrentEntry()) + if not PySpin.IsAvailable(handling_mode_entry) or not PySpin.IsReadable(handling_mode_entry): + print('Unable to set Buffer Handling mode (Entry retrieval). Aborting...\n') + return False + + # Set stream buffer Count Mode to manual + stream_buffer_count_mode = PySpin.CEnumerationPtr(s_node_map.GetNode('StreamBufferCountMode')) + if not PySpin.IsAvailable(stream_buffer_count_mode) or not PySpin.IsWritable(stream_buffer_count_mode): + print('Unable to set Buffer Count Mode (node retrieval). Aborting...\n') + return False + + stream_buffer_count_mode_manual = PySpin.CEnumEntryPtr(stream_buffer_count_mode.GetEntryByName('Manual')) + if not PySpin.IsAvailable(stream_buffer_count_mode_manual) or not PySpin.IsReadable(stream_buffer_count_mode_manual): + print('Unable to set Buffer Count Mode entry (Entry retrieval). Aborting...\n') + return False + + stream_buffer_count_mode.SetIntValue(stream_buffer_count_mode_manual.GetValue()) + print('Stream Buffer Count Mode set to manual...') + + # Retrieve and modify Stream Buffer Count + buffer_count = PySpin.CIntegerPtr(s_node_map.GetNode('StreamBufferCountManual')) + if not PySpin.IsAvailable(buffer_count) or not PySpin.IsWritable(buffer_count): + print('Unable to set Buffer Count (Integer node retrieval). Aborting...\n') + return False + + # Display Buffer Info + print('\nDefault Buffer Handling Mode: %s' % handling_mode_entry.GetDisplayName()) + print('Default Buffer Count: %d' % buffer_count.GetValue()) + print('Maximum Buffer Count: %d' % buffer_count.GetMax()) + + buffer_count.SetValue(NUM_BUFFERS) + + print('Buffer count now set to: %d' % buffer_count.GetValue()) + print('\nCamera will be triggered %d times in a row before %d images will be retrieved' % (NUM_TRIGGERS,(NUM_LOOPS-NUM_TRIGGERS))) + + for x in range (0, 4): + if x == 0: + handling_mode_entry = handling_mode.GetEntryByName('NewestFirst') + handling_mode.SetIntValue(handling_mode_entry.GetValue()) + print('\n\nBuffer Handling Mode has been set to %s' % handling_mode_entry.GetDisplayName()) + elif x == 1: + handling_mode_entry = handling_mode.GetEntryByName('NewestOnly') + handling_mode.SetIntValue(handling_mode_entry.GetValue()) + print('\n\nBuffer Handling Mode has been set to %s' % handling_mode_entry.GetDisplayName()) + elif x == 2: + handling_mode_entry = handling_mode.GetEntryByName('OldestFirst') + handling_mode.SetIntValue(handling_mode_entry.GetValue()) + print('\n\nBuffer Handling Mode has been set to %s' % handling_mode_entry.GetDisplayName()) + elif x == 3: + handling_mode_entry = handling_mode.GetEntryByName('OldestFirstOverwrite') + handling_mode.SetIntValue(handling_mode_entry.GetValue()) + print('\n\nBuffer Handling Mode has been set to %s' % handling_mode_entry.GetDisplayName()) + + # Begin capturing images + cam.BeginAcquisition() + + # Sleep for one second; only necessary when using non-BFS/ORX cameras on startup + if x == 0: + time.sleep(1) + + try: + # Software Trigger the camera then save images + for loop_cnt in range (0, NUM_LOOPS): + if loop_cnt < NUM_TRIGGERS: + # Retrieve the next image from the trigger + result &= grab_next_image_by_trigger(nodemap) + print('\nCamera triggered. No image grabbed') + else: + print('\nNo trigger. Grabbing image %d' %(loop_cnt-NUM_TRIGGERS)) + result_image = cam.GetNextImage(500) + + if result_image.IsIncomplete(): + print('Image incomplete with image status %s ...\n' % result_image.GetImageStatus()) + + if loop_cnt >= NUM_TRIGGERS: + # Retrieve Frame ID + print('Frame ID: %d' % result_image.GetFrameID()) + + # Create a unique filename + if device_serial_number: + filename = '%s-%s-%d.jpg' % (handling_mode_entry.GetSymbolic(),device_serial_number, (loop_cnt-NUM_TRIGGERS)) + else: + filename = '%s-%d.jpg' % (handling_mode_entry.GetSymbolic(),(loop_cnt-NUM_TRIGGERS)) + + # Save image + result_image.Save(filename) + print('Image saved at %s' % filename) + + # Release image + result_image.Release() + + # To control the framerate, have the application pause for 250ms. + time.sleep(0.25) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + if handling_mode_entry.GetSymbolic() == 'NewestOnly': + print('Error should occur when grabbing image 1 with handling mode set to NewestOnly') + result = False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure chunk data + if configure_trigger(nodemap) is False: + return False + + # Acquire images and display chunk data + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Reset trigger + result &= reset_trigger(nodemap) + + # De-initialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + print('\n\nRunning example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) + + + diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ChunkData.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ChunkData.py new file mode 100644 index 0000000..4214d69 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ChunkData.py @@ -0,0 +1,674 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# ChunkData.py shows how to get chunk data on an image, either from +# the nodemap or from the image itself. It relies on information provided in +# the Enumeration, Acquisition, and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the ImageFormatControl +# and Exposure samples. As they are somewhat shorter and simpler, either +# provides a strong introduction to camera customization. +# +# Chunk data provides information on various traits of an image. This includes +# identifiers such as frame ID, properties such as black level, and more. This +# information can be acquired from either the nodemap or the image itself. +# +# It may be preferable to grab chunk data from each individual image, as it +# can be hard to verify whether data is coming from the correct image when +# using the nodemap. This is because chunk data retrieved from the nodemap is +# only valid for the current image; when GetNextImage() is called, chunk data +# will be updated to that of the new current image. +# + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +# Use the following class and global variable to select whether +# chunk data is displayed from the image or the nodemap. +class ChunkDataTypes: + IMAGE = 1 + NODEMAP = 2 + + +CHOSEN_CHUNK_DATA_TYPE = ChunkDataTypes.NODEMAP + + +def configure_chunk_data(nodemap): + """ + This function configures the camera to add chunk data to each image. It does + this by enabling each type of chunk data before enabling chunk data mode. + When chunk data is turned on, the data is made available in both the nodemap + and each image. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + try: + result = True + print('\n*** CONFIGURING CHUNK DATA ***\n') + + # Activate chunk mode + # + # *** NOTES *** + # Once enabled, chunk data will be available at the end of the payload + # of every image captured until it is disabled. Chunk data can also be + # retrieved from the nodemap. + chunk_mode_active = PySpin.CBooleanPtr(nodemap.GetNode('ChunkModeActive')) + + if PySpin.IsAvailable(chunk_mode_active) and PySpin.IsWritable(chunk_mode_active): + chunk_mode_active.SetValue(True) + + print('Chunk mode activated...') + + # Enable all types of chunk data + # + # *** NOTES *** + # Enabling chunk data requires working with nodes: "ChunkSelector" + # is an enumeration selector node and "ChunkEnable" is a boolean. It + # requires retrieving the selector node (which is of enumeration node + # type), selecting the entry of the chunk data to be enabled, retrieving + # the corresponding boolean, and setting it to be true. + # + # In this example, all chunk data is enabled, so these steps are + # performed in a loop. Once this is complete, chunk mode still needs to + # be activated. + chunk_selector = PySpin.CEnumerationPtr(nodemap.GetNode('ChunkSelector')) + + if not PySpin.IsAvailable(chunk_selector) or not PySpin.IsReadable(chunk_selector): + print('Unable to retrieve chunk selector. Aborting...\n') + return False + + # Retrieve entries + # + # *** NOTES *** + # PySpin handles mass entry retrieval in a different way than the C++ + # API. Instead of taking in a NodeList_t reference, GetEntries() takes + # no parameters and gives us a list of INodes. Since we want these INodes + # to be of type CEnumEntryPtr, we can use a list comprehension to + # transform all of our collected INodes into CEnumEntryPtrs at once. + entries = [PySpin.CEnumEntryPtr(chunk_selector_entry) for chunk_selector_entry in chunk_selector.GetEntries()] + + print('Enabling entries...') + + # Iterate through our list and select each entry node to enable + for chunk_selector_entry in entries: + # Go to next node if problem occurs + if not PySpin.IsAvailable(chunk_selector_entry) or not PySpin.IsReadable(chunk_selector_entry): + continue + + chunk_selector.SetIntValue(chunk_selector_entry.GetValue()) + + chunk_str = '\t {}:'.format(chunk_selector_entry.GetSymbolic()) + + # Retrieve corresponding boolean + chunk_enable = PySpin.CBooleanPtr(nodemap.GetNode('ChunkEnable')) + + # Enable the boolean, thus enabling the corresponding chunk data + if not PySpin.IsAvailable(chunk_enable): + print('{} not available'.format(chunk_str)) + result = False + elif chunk_enable.GetValue() is True: + print('{} enabled'.format(chunk_str)) + elif PySpin.IsWritable(chunk_enable): + chunk_enable.SetValue(True) + print('{} enabled'.format(chunk_str)) + else: + print('{} not writable'.format(chunk_str)) + result = False + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def display_chunk_data_from_nodemap(nodemap): + """ + This function displays all available chunk data by looping through the + chunk data category node on the nodemap. + + :param nodemap: Device nodemap to retrieve images from. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + print('Printing chunk data from nodemap...') + try: + result = True + # Retrieve chunk data information nodes + # + # *** NOTES *** + # As well as being written into the payload of the image, chunk data is + # accessible on the GenICam nodemap. When chunk data is enabled, it is + # made available from both the image payload and the nodemap. + chunk_data_control = PySpin.CCategoryPtr(nodemap.GetNode('ChunkDataControl')) + if not PySpin.IsAvailable(chunk_data_control) or not PySpin.IsReadable(chunk_data_control): + print('Unable to retrieve chunk data control. Aborting...\n') + return False + + features = chunk_data_control.GetFeatures() + + # Iterate through children + for feature in features: + feature_node = PySpin.CNodePtr(feature) + feature_display_name = '\t{}:'.format(feature_node.GetDisplayName()) + + if not PySpin.IsAvailable(feature_node) or not PySpin.IsReadable(feature_node): + print('{} node not available'.format(feature_display_name)) + result &= False + continue + # Print node type value + # + # *** NOTES *** + # All nodes can be cast as value nodes and have their information + # retrieved as a string using the ToString() method. This is much + # easier than dealing with each individual node type. + else: + feature_value = PySpin.CValuePtr(feature) + print('{} {}'.format(feature_display_name, feature_value.ToString())) + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def display_chunk_data_from_image(image): + """ + This function displays a select amount of chunk data from the image. Unlike + accessing chunk data via the nodemap, there is no way to loop through all + available data. + + :param image: Image to acquire chunk data from + :type image: Image object + :return: True if successful, False otherwise. + :rtype: bool + """ + print('Printing chunk data from image...') + try: + result = True + print(type(image)) + # Retrieve chunk data from image + # + # *** NOTES *** + # When retrieving chunk data from an image, the data is stored in a + # ChunkData object and accessed with getter functions. + chunk_data = image.GetChunkData() + + # Retrieve exposure time (recorded in microseconds) + exposure_time = chunk_data.GetExposureTime() + print('\tExposure time: {}'.format(exposure_time)) + + # Retrieve frame ID + frame_id = chunk_data.GetFrameID() + print('\tFrame ID: {}'.format(frame_id)) + + # Retrieve gain; gain recorded in decibels + gain = chunk_data.GetGain() + print('\tGain: {}'.format(gain)) + + # Retrieve height; height recorded in pixels + height = chunk_data.GetHeight() + print('\tHeight: {}'.format(height)) + + # Retrieve offset X; offset X recorded in pixels + offset_x = chunk_data.GetOffsetX() + print('\tOffset X: {}'.format(offset_x)) + + # Retrieve offset Y; offset Y recorded in pixels + offset_y = chunk_data.GetOffsetY() + print('\tOffset Y: {}'.format(offset_y)) + + # Retrieve sequencer set active + sequencer_set_active = chunk_data.GetSequencerSetActive() + print('\tSequencer set active: {}'.format(sequencer_set_active)) + + # Retrieve timestamp + timestamp = chunk_data.GetTimestamp() + print('\tTimestamp: {}'.format(timestamp)) + + # Retrieve width; width recorded in pixels + width = chunk_data.GetWidth() + print('\tWidth: {}'.format(width)) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('\n*** DEVICE INFORMATION ***\n') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + else: + print('Device control information not available.') + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print('\n*** IMAGE ACQUISTION ***\n') + + try: + result = True + # Set acquisition mode to continuous + # + # *** NOTES *** + # Because the example acquires and saves 10 images, setting acquisition + # mode to continuous lets the example finish. If set to single frame + # or multiframe (at a lower number of images), the example would just + # hang. This would happen because the example has been written to + # acquire 10 images while the camera would have been programmed to + # retrieve less than that. + # + # Setting the value of an enumeration node is slightly more complicated + # than other node types. Two nodes must be retrieved: first, the + # enumeration node is retrieved from the nodemap; and second, the entry + # node is retrieved from the enumeration node. The integer value of the + # entry node is then set as the new value of the enumeration node. + # + # Notice that both the enumeration and the entry nodes are checked for + # availability and readability/writability. Enumeration nodes are + # generally readable and writable whereas their entry nodes are only + # ever readable. + # + # Retrieve enumeration node from nodemap + + # In order to access the node entries, they have to be casted to a pointer type (CEnumerationPtr here) + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (node retrieval). Aborting...') + return False + + # Retrieve entry node from enumeration mode + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable(node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...') + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Begin acquiring images + # + # *** NOTES *** + # What happens when the camera begins acquiring images depends on the + # acquisition mode. Single frame captures only a single image, multi + # frame captures a set number of images, and continuous captures a + # continuous stream of images. As the example calls for the + # retrieval of 10 images, continuous mode has been set. + # + # *** LATER *** + # Image acquisition must be ended when no more images are needed. + cam.BeginAcquisition() + + print('Acquiring images...') + + # Retrieve device serial number for filename + # + # *** NOTES *** + # The device serial number is retrieved in order to keep cameras from + # overwriting one another. Grabbing image IDs could also accomplish + # this. + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Device serial number retrieved as %s...' % device_serial_number) + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + # Retrieve next received image + # + # *** NOTES *** + # Capturing an image houses images on the camera buffer. Trying + # to capture an image that does not exist will hang the camera. + # + # *** LATER *** + # Once an image from the buffer is saved and/or no longer + # needed, the image must be released in order to keep the + # buffer from filling up. + image_result = cam.GetNextImage(1000) + + # Ensure image completion + # + # *** NOTES *** + # Images can be easily checked for completion. This should be + # done whenever a complete image is expected or required. + # Further, check image status for a little more insight into + # why an image is incomplete. + if image_result.IsIncomplete(): + print('Image incomplete with image status %d ...' % image_result.GetImageStatus()) + else: + + # Print image information + # + # *** NOTES *** + # Images have quite a bit of available metadata including + # things such as CRC, image status, and offset values, to + # name a few. + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Grabbed Image %d, width = %d, height = %d' % (i, width, height)) + + # Convert image to mono 8 + # + # *** NOTES *** + # Images can be converted between pixel formats by using + # the appropriate enumeration value. Unlike the original + # image, the converted one does not need to be released as + # it does not affect the camera buffer. + # + # When converting images, color processing algorithm is an + # optional parameter. + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'ChunkData-%s-%d.jpg' % (device_serial_number, i) + else: + filename = 'ChunkData-%d.jpg' % i + + # Save image + # + # *** NOTES *** + # The standard practice of the examples is to use device + # serial numbers to keep images of one device from + # overwriting those of another. + image_converted.Save(filename) + print('Image saved at %s' % filename) + + # Display chunk data + + if CHOSEN_CHUNK_DATA_TYPE == ChunkDataTypes.IMAGE: + result &= display_chunk_data_from_image(image_result) + elif CHOSEN_CHUNK_DATA_TYPE == ChunkDataTypes.NODEMAP: + result = display_chunk_data_from_nodemap(nodemap) + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + print('') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + # End acquisition + # + # *** NOTES *** + # Ending acquisition appropriately helps ensure that devices clean up + # properly and do not need to be power-cycled to maintain integrity. + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def disable_chunk_data(nodemap): + """ + This function disables each type of chunk data before disabling chunk data mode. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise + :rtype: bool + """ + try: + result = True + + # Retrieve the selector node + chunk_selector = PySpin.CEnumerationPtr(nodemap.GetNode('ChunkSelector')) + + if not PySpin.IsAvailable(chunk_selector) or not PySpin.IsReadable(chunk_selector): + print('Unable to retrieve chunk selector. Aborting...\n') + return False + + # Retrieve entries + # + # *** NOTES *** + # PySpin handles mass entry retrieval in a different way than the C++ + # API. Instead of taking in a NodeList_t reference, GetEntries() takes + # no parameters and gives us a list of INodes. Since we want these INodes + # to be of type CEnumEntryPtr, we can use a list comprehension to + # transform all of our collected INodes into CEnumEntryPtrs at once. + entries = [PySpin.CEnumEntryPtr(chunk_selector_entry) for chunk_selector_entry in chunk_selector.GetEntries()] + + print('Disabling entries...') + + for chunk_selector_entry in entries: + # Go to next node if problem occurs + if not PySpin.IsAvailable(chunk_selector_entry) or not PySpin.IsReadable(chunk_selector_entry): + continue + + chunk_selector.SetIntValue(chunk_selector_entry.GetValue()) + + chunk_symbolic_form = '\t {}:'.format(chunk_selector_entry.GetSymbolic()) + + # Retrieve corresponding boolean + chunk_enable = PySpin.CBooleanPtr(nodemap.GetNode('ChunkEnable')) + + # Disable the boolean, thus disabling the corresponding chunk data + if not PySpin.IsAvailable(chunk_enable): + print('{} not available'.format(chunk_symbolic_form)) + result = False + elif not chunk_enable.GetValue(): + print('{} disabled'.format(chunk_symbolic_form)) + elif PySpin.IsWritable(chunk_enable): + chunk_enable.SetValue(False) + print('{} disabled'.format(chunk_symbolic_form)) + else: + print('{} not writable'.format(chunk_symbolic_form)) + + # Deactivate Chunk Mode + chunk_mode_active = PySpin.CBooleanPtr(nodemap.GetNode('ChunkModeActive')) + + if not PySpin.IsAvailable(chunk_mode_active) or not PySpin.IsWritable(chunk_mode_active): + print('Unable to deactivate chunk mode. Aborting...\n') + return False + + chunk_mode_active.SetValue(False) + + print('Chunk mode deactivated...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure chunk data + if configure_chunk_data(nodemap) is False: + return False + + # Acquire images and display chunk data + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Disable chunk data + if disable_chunk_data(nodemap) is False: + return False + + # De-initialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/CounterAndTimer.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/CounterAndTimer.py new file mode 100644 index 0000000..537d5d4 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/CounterAndTimer.py @@ -0,0 +1,669 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# CounterAndTimer.py shows how to setup a Pulse Width Modulation (PWM) +# signal using counters and timers. The camera will output the PWM signal via +# strobe, and capture images at a rate defined by the PWM signal as well. +# Users should take care to use a PWM signal within the camera's max +# frame rate (by default, the PWM signal is set to 50 Hz). +# +# Counter and Timer functionality is only available for BFS and Oryx Cameras. +# For details on the hardware setup, see our kb article, "Using Counter and +# Timer Control"; https://www.flir.com/support-center/iis/machine-vision/application-note/using-counter-and-timer-control + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** DEVICE INFORMATION ***\n') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + feature_string = node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable' + print('{}: {}'.format(node_feature.GetName(), feature_string)) + + else: + print('Device control information not available.') + + print('') + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + return False + + return result + + +def setup_counter_and_timer(nodemap): + """ + This function configures the camera to setup a Pulse Width Modulation signal using + Counter and Timer functionality. By default, the PWM signal will be set to run at + 50hz, with a duty cycle of 70%. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('Configuring Pulse Width Modulation signal') + + try: + result = True + + # Set Counter Selector to Counter 0 + node_counter_selector = PySpin.CEnumerationPtr(nodemap.GetNode('CounterSelector')) + + # Check to see if camera supports Counter and Timer functionality + if not PySpin.IsAvailable(node_counter_selector): + print('\nCamera does not support Counter and Timer Functionality. Aborting...\n') + return False + + if not PySpin.IsWritable(node_counter_selector): + print('\nUnable to set Counter Selector (enumeration retrieval). Aborting...\n') + return False + + entry_counter_0 = node_counter_selector.GetEntryByName('Counter0') + if not PySpin.IsAvailable(entry_counter_0) or not PySpin.IsReadable(entry_counter_0): + print('\nUnable to set Counter Selector (entry retrieval). Aborting...\n') + return False + + counter_0 = entry_counter_0.GetValue() + + node_counter_selector.SetIntValue(counter_0) + + # Set Counter Event Source to MHzTick + node_counter_event_source = PySpin.CEnumerationPtr(nodemap.GetNode('CounterEventSource')) + if not PySpin.IsAvailable(node_counter_event_source) or not PySpin.IsWritable(node_counter_event_source): + print('\nUnable to set Counter Event Source (enumeration retrieval). Aborting...\n') + return False + + entry_counter_event_source_mhz_tick = node_counter_event_source.GetEntryByName('MHzTick') + if not PySpin.IsAvailable(entry_counter_event_source_mhz_tick) \ + or not PySpin.IsReadable(entry_counter_event_source_mhz_tick): + print('\nUnable to set Counter Event Source (entry retrieval). Aborting...\n') + return False + + counter_event_source_mhz_tick = entry_counter_event_source_mhz_tick.GetValue() + + node_counter_event_source.SetIntValue(counter_event_source_mhz_tick) + + # Set Counter Duration to 14000 + node_counter_duration = PySpin.CIntegerPtr(nodemap.GetNode('CounterDuration')) + if not PySpin.IsAvailable(node_counter_duration) or not PySpin.IsWritable(node_counter_duration): + print('\nUnable to set Counter Duration (integer retrieval). Aborting...\n') + return False + + node_counter_duration.SetValue(14000) + + # Set Counter Delay to 6000 + node_counter_delay = PySpin.CIntegerPtr(nodemap.GetNode('CounterDelay')) + if not PySpin.IsAvailable(node_counter_delay) or not PySpin.IsWritable(node_counter_delay): + print('\nUnable to set Counter Delay (integer retrieval). Aborting...\n') + return False + + node_counter_delay.SetValue(6000) + + # Determine Duty Cycle of PWM signal + duty_cycle = float(node_counter_duration.GetValue()) / (float(node_counter_duration.GetValue() + + node_counter_delay.GetValue())) * 100 + + print('\nThe duty cycle has been set to {}%'.format(duty_cycle)) + + # Determine pulse rate of PWM signal + pulse_rate = 1000000 / float(node_counter_duration.GetValue() + node_counter_delay.GetValue()) + + print('\nThe pulse rate has been set to {} Hz'.format(pulse_rate)) + + # Set Counter Trigger Source to Frame Trigger Wait + node_counter_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode('CounterTriggerSource')) + if not PySpin.IsAvailable(node_counter_trigger_source) or not PySpin.IsWritable(node_counter_trigger_source): + print('\nUnable to set Counter Trigger Source (enumeration retrieval). Aborting...\n') + return False + + entry_counter_trigger_source_ftw = node_counter_trigger_source.GetEntryByName('FrameTriggerWait') + if not PySpin.IsAvailable(entry_counter_trigger_source_ftw)\ + or not PySpin.IsReadable(entry_counter_trigger_source_ftw): + print('\nUnable to set Counter Trigger Source (entry retrieval). Aborting...\n') + return False + + counter_trigger_source_ftw = entry_counter_trigger_source_ftw.GetValue() + + node_counter_trigger_source.SetIntValue(counter_trigger_source_ftw) + + # Set Counter Trigger Activation to Level High + node_counter_trigger_activation = PySpin.CEnumerationPtr(nodemap.GetNode('CounterTriggerActivation')) + if not PySpin.IsAvailable(node_counter_trigger_activation) or \ + not PySpin.IsWritable(node_counter_trigger_activation): + print('\nUnable to set Counter Trigger Activation (enumeration retrieval). Aborting...\n') + return False + + entry_counter_trigger_source_lh = node_counter_trigger_activation.GetEntryByName('LevelHigh') + if not PySpin.IsAvailable(entry_counter_trigger_source_lh) \ + or not PySpin.IsReadable(entry_counter_trigger_source_lh): + print('\nUnable to set Counter Trigger Activation (entry retrieval). Aborting...\n') + return False + + counter_trigger_level_high = entry_counter_trigger_source_lh.GetValue() + + node_counter_trigger_activation.SetIntValue(counter_trigger_level_high) + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + return False + + return result + + +def configure_digital_io(nodemap): + """ + This function configures the GPIO to output the PWM signal. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('\nConfiguring GPIO strobe output') + + try: + result = True + camera_family_bfs = "BFS" + camera_family_oryx = "ORX" + + # Determine camera family + node_device_name = PySpin.CStringPtr(nodemap.GetNode('DeviceModelName')) + if not PySpin.IsAvailable(node_device_name) or not PySpin.IsReadable(node_device_name): + print('\nUnable to determine camera family. Aborting...\n') + return False + + camera_model = node_device_name.GetValue() + + # Set Line Selector + node_line_selector = PySpin.CEnumerationPtr(nodemap.GetNode('LineSelector')) + if not PySpin.IsAvailable(node_line_selector) or not PySpin.IsWritable(node_line_selector): + print('\nUnable to set Line Selector (enumeration retrieval). Aborting...\n') + return False + + if camera_family_bfs in camera_model: + + entry_line_selector_line_1 = node_line_selector.GetEntryByName('Line1') + if not PySpin.IsAvailable(entry_line_selector_line_1) or not PySpin.IsReadable(entry_line_selector_line_1): + print('\nUnable to set Line Selector (entry retrieval). Aborting...\n') + return False + + line_selector_line_1 = entry_line_selector_line_1.GetValue() + + node_line_selector.SetIntValue(line_selector_line_1) + + elif camera_family_oryx in camera_model: + + entry_line_selector_line_2 = node_line_selector.GetEntryByName('Line2') + if not PySpin.IsAvailable(entry_line_selector_line_2) or not PySpin.IsReadable(entry_line_selector_line_2): + print('\nUnable to set Line Selector (entry retrieval). Aborting...\n') + return False + + line_selector_line_2 = entry_line_selector_line_2.GetValue() + + node_line_selector.SetIntValue(line_selector_line_2) + + # Set Line Mode to output + node_line_mode = PySpin.CEnumerationPtr(nodemap.GetNode('LineMode')) + if not PySpin.IsAvailable(node_line_mode) or not PySpin.IsWritable(node_line_mode): + print('\nUnable to set Line Mode (enumeration retrieval). Aborting...\n') + return False + + entry_line_mode_output = node_line_mode.GetEntryByName('Output') + if not PySpin.IsAvailable(entry_line_mode_output) or not PySpin.IsReadable(entry_line_mode_output): + print('\nUnable to set Line Mode (entry retrieval). Aborting...\n') + return False + + line_mode_output = entry_line_mode_output.GetValue() + + node_line_mode.SetIntValue(line_mode_output) + + # Set Line Source for Selected Line to Counter 0 Active + node_line_source = PySpin.CEnumerationPtr(nodemap.GetNode('LineSource')) + if not PySpin.IsAvailable(node_line_source) or not PySpin.IsWritable(node_line_source): + print('\nUnable to set Line Source (enumeration retrieval). Aborting...\n') + return False + + entry_line_source_counter_0_active = node_line_source.GetEntryByName('Counter0Active') + if not PySpin.IsAvailable(entry_line_source_counter_0_active) \ + or not PySpin.IsReadable(entry_line_source_counter_0_active): + print('\nUnable to set Line Source (entry retrieval). Aborting...\n') + return False + + line_source_counter_0_active = entry_line_source_counter_0_active.GetValue() + + node_line_source.SetIntValue(line_source_counter_0_active) + + if camera_family_bfs in camera_model: + # Change Line Selector to Line 2 and Enable 3.3 Voltage Rail + entry_line_selector_line_2 = node_line_selector.GetEntryByName('Line2') + if not PySpin.IsAvailable(entry_line_selector_line_2) or not PySpin.IsReadable(entry_line_selector_line_2): + print('\nUnable to set Line Selector (entry retrieval). Aborting...\n') + return False + + line_selector_line_2 = entry_line_selector_line_2.GetValue() + + node_line_selector.SetIntValue(line_selector_line_2) + + node_voltage_enable = PySpin.CBooleanPtr(nodemap.GetNode('V3_3Enable')) + if not PySpin.IsAvailable(node_voltage_enable) or not PySpin.IsWritable(node_voltage_enable): + print('\nUnable to set Voltage Enable (boolean retrieval). Aborting...\n') + return False + + node_voltage_enable.SetValue(True) + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + return False + + return result + + +def configure_exposure_and_trigger(nodemap): + """ + This function configures the camera to set a manual exposure value and enables + camera to be triggered by the PWM signal. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('\nConfiguring Exposure and Trigger') + + try: + result = True + + # Turn off auto exposure + node_exposure_auto = PySpin.CEnumerationPtr(nodemap.GetNode('ExposureAuto')) + if not PySpin.IsAvailable(node_exposure_auto) or not PySpin.IsWritable(node_exposure_auto): + print('\nUnable to set Exposure Auto (enumeration retrieval). Aborting...\n') + return False + + entry_exposure_auto_off = node_exposure_auto.GetEntryByName('Off') + if not PySpin.IsAvailable(entry_exposure_auto_off) or not PySpin.IsReadable(entry_exposure_auto_off): + print('\nUnable to set Exposure Auto (entry retrieval). Aborting...\n') + return False + + exposure_auto_off = entry_exposure_auto_off.GetValue() + + node_exposure_auto.SetIntValue(exposure_auto_off) + + # Set Exposure Time to less than 1/50th of a second (5000 us is used as an example) + node_exposure_time = PySpin.CFloatPtr(nodemap.GetNode('ExposureTime')) + if not PySpin.IsAvailable(node_exposure_time) or not PySpin.IsWritable(node_exposure_time): + print('\nUnable to set Exposure Time (float retrieval). Aborting...\n') + return False + + node_exposure_time.SetValue(5000) + + # Ensure trigger mode is off + # + # *** NOTES *** + # The trigger must be disabled in order to configure + node_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(node_trigger_mode) or not PySpin.IsWritable(node_trigger_mode): + print('\nUnable to disable trigger mode (node retrieval). Aborting...\n') + return False + + entry_trigger_mode_off = node_trigger_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(entry_trigger_mode_off) or not PySpin.IsReadable(entry_trigger_mode_off): + print('\nUnable to disable trigger mode (enum entry retrieval). Aborting...\n') + return False + + node_trigger_mode.SetIntValue(entry_trigger_mode_off.GetValue()) + + # Set Trigger Source to Counter 0 Start + node_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerSource')) + if not PySpin.IsAvailable(node_trigger_source) or not PySpin.IsWritable(node_trigger_source): + print('\nUnable to set trigger source (enumeration retrieval). Aborting...\n') + return False + + entry_trigger_source_counter_0_start = node_trigger_source.GetEntryByName('Counter0Start') + if not PySpin.IsAvailable(entry_trigger_source_counter_0_start)\ + or not PySpin.IsReadable(entry_trigger_source_counter_0_start): + print('\nUnable to set trigger mode (enum entry retrieval). Aborting...\n') + return False + + node_trigger_source.SetIntValue(entry_trigger_source_counter_0_start.GetValue()) + + # Set Trigger Overlap to Readout + node_trigger_overlap = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerOverlap')) + if not PySpin.IsAvailable(node_trigger_overlap) or not PySpin.IsWritable(node_trigger_overlap): + print('\nUnable to set Trigger Overlap (enumeration retrieval). Aborting...\n') + return False + + entry_trigger_overlap_ro = node_trigger_overlap.GetEntryByName('ReadOut') + if not PySpin.IsAvailable(entry_trigger_overlap_ro) or not PySpin.IsReadable(entry_trigger_overlap_ro): + print('\nUnable to set Trigger Overlap (entry retrieval). Aborting...\n') + return False + + trigger_overlap_ro = entry_trigger_overlap_ro.GetValue() + + node_trigger_overlap.SetIntValue(trigger_overlap_ro) + + # Turn trigger mode on + entry_trigger_mode_on = node_trigger_mode.GetEntryByName('On') + if not PySpin.IsAvailable(entry_trigger_mode_on) or not PySpin.IsReadable(entry_trigger_mode_on): + print('\nUnable to enable trigger mode (enum entry retrieval). Aborting...\n') + return False + + node_trigger_mode.SetIntValue(entry_trigger_mode_on.GetValue()) + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + return False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device; please see + Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('\n*** IMAGE ACQUISITION ***\n') + try: + result = True + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (enumeration retrieval). Aborting...\n') + return False + + entry_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(entry_acquisition_mode_continuous)\ + or not PySpin.IsReadable(entry_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (enum entry retrieval). Aborting...\n') + return False + + acquisition_mode_continuous = entry_acquisition_mode_continuous.GetValue() + + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Begin acquiring images + cam.BeginAcquisition() + + print('Acquiring images...') + + # Retrieve device serial number for filename + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Device serial number retrieved as {}...'.format(device_serial_number)) + + print('') + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print('Image incomplete with image status {} ...'.format(image_result.GetImageStatus())) + + else: + + # Print image information; height and width recorded in pixels + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Grabbed image {}, width = {}, height = {}'.format(i, width, height)) + + # Convert image to mono 8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'CounterAndTimer-{}-{}.jpg'.format(device_serial_number, i) + else: # if serial number is empty + filename = 'CounterAndTimer-{}.jpg'.format(i) + + # Save image + image_converted.Save(filename) + print('Image saved at {}'.format(filename)) + + # Release image + image_result.Release() + print('') + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + return False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + return False + + return result + + +def reset_trigger(nodemap): + """ + This function returns the camera to a normal state by turning off trigger mode. + + *** NOTES *** + This function turns off trigger mode, but does not change the trigger source. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Turn trigger mode back off + node_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(node_trigger_mode) or not PySpin.IsWritable(node_trigger_mode): + print('Unable to disable trigger mode (node retrieval). Non-fatal error...\n') + + entry_trigger_mode_off = node_trigger_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(entry_trigger_mode_off) or not PySpin.IsReadable(entry_trigger_mode_off): + print('Unable to disable trigger mode (enum entry retrieval). Non-fatal error...\n') + + node_trigger_mode.SetIntValue(entry_trigger_mode_off.GetValue()) + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see the NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure Counter and Timer setup + result &= setup_counter_and_timer(nodemap) + if not result: + return result + + # Configure DigitalIO (GPIO output) + result &= configure_digital_io(nodemap) + if not result: + return result + + # Configure Exposure and Trigger + result &= configure_exposure_and_trigger(nodemap) + if not result: + return result + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Reset trigger + result &= reset_trigger(nodemap) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: {}.{}.{}.{}'.format(version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: {}'.format(num_cameras)) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera {}...'.format(i)) + + result &= run_single_camera(cam) + print('Camera {} example complete... \n'.format(i)) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/DeviceEvents.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/DeviceEvents.py new file mode 100644 index 0000000..53ee365 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/DeviceEvents.py @@ -0,0 +1,494 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# =============================================================================*/ +# +# DeviceEvents.py shows how to create a handler to access device +# events. It relies on information provided in the Enumeration, Acquisition, +# and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the NodeMapCallback +# example, as nodemap callbacks follow the same general procedure as events. +# +# Device events can be thought of as camera-related events. This example +# creates a user-defined class, DeviceEventHandler, which allows the user to +# define any properties, parameters, and the event handler itself while DeviceEventHandler, +# the parent class, allows the child class to appropriately interface with +# the Spinnaker SDK. + +import os +import PySpin +import sys + + +class EventType: + """ + 'Enum' for choosing whether to register a event specifically for exposure end events + or universally for all events. + """ + GENERIC = 0 + SPECIFIC = 1 + +CHOSEN_EVENT = EventType.GENERIC # change me! +NUM_IMAGES = 10 # number of images to acquire + + +class DeviceEventHandler(PySpin.DeviceEventHandler): + """ + This class defines the properties, parameters, and the event handler itself. Take a + moment to notice what parts of the class are mandatory, and what have been + added for demonstration purposes. First, any class used to define device + events must inherit from DeviceEventHandler. Second, the method signature of + OnDeviceEvent() must also be consistent. Everything else - including the + constructor, destructor, properties, and body of OnDeviceEvent() - are + particular to the example. + """ + def __init__(self, eventname): + """ + This constructor registers an event name to be used on device events. + + :param eventname: Name of event to register. + :type eventname: str + :rtype: None + """ + super(DeviceEventHandler, self).__init__() + self.event_name = eventname + self.count = 0 + + def OnDeviceEvent(self, eventname): + """ + Callback function when a device event occurs. + Note eventname is a wrapped gcstring, not a Python string, but basic operations such as printing and comparing + with Python strings are supported. + + :param eventname: gcstring representing the name of the occurred event. + :type eventname: gcstring + :rtype: None + """ + if eventname == self.event_name: + self.count += 1 + + # Print information on specified device event + print('\tDevice event %s with ID %i number %i...' % (eventname, + self.GetDeviceEventId(), + self.count)) + else: + # Print no information on non-specified event + print('\tDevice event occurred; not %s; ignoring...' % self.event_name) + + +def configure_device_events(nodemap, cam): + """ + This function configures the example to execute device events by enabling all + types of device events, and then creating and registering a device event handler that + only concerns itself with an end of exposure event. + + :param INodeMap nodemap: Device nodemap. + :param CameraPtr cam: Pointer to camera. + :returns: tuple (result, device_event_handler) + WHERE + result is True if successful, False otherwise + device_event_handler is the event handler + :rtype: (bool, DeviceEventHandler) + """ + print('\n*** CONFIGURING DEVICE EVENTS ***\n') + + try: + result = True + + # Retrieve device event selector + # + # *** NOTES *** + # Each type of device event must be enabled individually. This is done + # by retrieving "EventSelector" (an enumeration node) and then enabling + # the device event on "EventNotification" (another enumeration node). + # + # This example only deals with exposure end events. However, instead of + # only enabling exposure end events with a simpler device event function, + # all device events are enabled while the device event handler deals with + # ensuring that only exposure end events are considered. A more standard + # use-case might be to enable only the events of interest. + node_event_selector = PySpin.CEnumerationPtr(nodemap.GetNode('EventSelector')) + if not PySpin.IsAvailable(node_event_selector) or not PySpin.IsReadable(node_event_selector): + print('Unable to retrieve event selector entries. Aborting...') + return False + + entries = node_event_selector.GetEntries() + print('Enabling event selector entries...') + + # Enable device events + # + # *** NOTES *** + # In order to enable a device event, the event selector and event + # notification nodes (both of type enumeration) must work in unison. + # The desired event must first be selected on the event selector node + # and then enabled on the event notification node. + for entry in entries: + + # Select entry on selector node + node_entry = PySpin.CEnumEntryPtr(entry) + if not PySpin.IsAvailable(node_entry) or not PySpin.IsReadable(node_entry): + + # Skip if node fails + result = False + continue + + node_event_selector.SetIntValue(node_entry.GetValue()) + + # Retrieve event notification node (an enumeration node) + node_event_notification = PySpin.CEnumerationPtr(nodemap.GetNode('EventNotification')) + if not PySpin.IsAvailable(node_event_notification) or not PySpin.IsWritable(node_event_notification): + + # Skip if node fails + result = False + continue + + # Retrieve entry node to enable device event + node_event_notification_on = PySpin.CEnumEntryPtr(node_event_notification.GetEntryByName('On')) + if not PySpin.IsAvailable(node_event_notification_on) or not PySpin.IsReadable(node_event_notification_on): + + # Skip if node fails + result = False + continue + + node_event_notification.SetIntValue(node_event_notification_on.GetValue()) + + print('\t%s: enabled...' % node_entry.GetDisplayName()) + + # Create device event handler + # + # *** NOTES *** + # The class has been designed to take in the name of an event. If all + # events are registered generically, all event types will trigger a + # device event; on the other hand, if an event handler is registered + # specifically, only that event will trigger an event. + device_event_handler = DeviceEventHandler('EventExposureEnd') + + # Register device event handler + # + # *** NOTES *** + # Device event handlers are registered to cameras. If there are multiple + # cameras, each camera must have any device event handlers registered to it + # separately. Note that multiple device event handlers may be registered to a + # single camera. + # + # *** LATER *** + # Device event handlers must be unregistered manually. This must be done prior + # to releasing the system and while the device event handlers are still in + # scope. + if CHOSEN_EVENT == EventType.GENERIC: + + # Device event handlers registered generally will be triggered by any device events. + cam.RegisterEventHandler(device_event_handler) + + print('Device event handler registered generally...') + + elif CHOSEN_EVENT == EventType.SPECIFIC: + + # Device event handlers registered to a specified event will only + # be triggered by the type of event is it registered to. + cam.RegisterEventHandler(device_event_handler, 'EventExposureEnd') + + print('Device event handler registered specifically to EventExposureEnd events...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result, device_event_handler + + +def reset_device_events(cam, device_event_handler): + """ + This function resets the example by unregistering the device event handler. + + :param cam: Camera to unregister event handler from. + :param device_event_handler: Event handler for this example. + :type cam: CameraPtr + :type device_event_handler: DeviceEventHandler + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Unregister device event handler + # + # *** NOTES *** + # It is important to unregister all device event handlers from all cameras that + # they are registered to. + cam.UnregisterEventHandler(device_event_handler) + + print('Device event handler unregistered...\n') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print('\n*** DEVICE INFORMATION ***\n') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex.message) + return False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device; please see + Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print('\n*** IMAGE ACQUISITION ***\n') + try: + result = True + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (enum retrieval). Aborting...\n') + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) \ + or not PySpin.IsReadable(node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...\n') + return False + + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Begin acquiring images + cam.BeginAcquisition() + + print('Acquiring images...') + + # Retrieve device serial number for filename + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Device serial number retrieved as %s...' % device_serial_number) + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print('Image incomplete with image status %s...' % image_result.GetImageStatus()) + + else: + + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Grabbed Image %i, width = %i, height = %i' % (i, width, height)) + + # Convert to mono8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + if device_serial_number: + filename = 'DeviceEvents-%s-%i.jpg' % (device_serial_number, i) + else: + filename = 'DeviceEvents-%i.jpg' % i + + # Save image + image_converted.Save(filename) + print('Image saved at %s' % filename) + + # Release image + image_result.Release() + print('') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to setup and run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure device event handlers + err, device_event_handler = configure_device_events(nodemap, cam) + if not err: + return err + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Reset device event handlers + result &= reset_device_events(cam, device_event_handler) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex.message) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Enumeration.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Enumeration.py new file mode 100644 index 0000000..489b34a --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Enumeration.py @@ -0,0 +1,272 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Enumeration.py shows how to enumerate interfaces and cameras. +# Knowing this is mandatory for doing anything with the Spinnaker SDK, and is +# therefore the best place to start learning how to use the SDK. +# +# This example introduces the preparation, use, and cleanup of the system +# object, interface and camera lists, interfaces, and cameras. It also touches +# on retrieving both nodes from nodemaps and information from nodes. +# +# Once comfortable with enumeration, we suggest checking out the Acquisition and/or +# NodeMapInfo examples. Acquisition demonstrates using a camera to acquire images, +# and NodeMapInfo demonstrates retrieving information from various node types. + +import PySpin +import sys + + +def query_interface(interface): + """ + Queries an interface for its cameras and prints out device information. + + :param interface: InterfacePtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Retrieve TL nodemap from interface + # + # *** NOTES *** + # Each interface has a nodemap that can be retrieved in order to + # access information about the interface itself, any devices + # connected, or addressing information if applicable. + nodemap_interface = interface.GetTLNodeMap() + + # Print interface display name + # + # *** NOTES *** + # Grabbing node information requires first retrieving the node and + # then retrieving its information. There are two things to keep in + # mind. First, a node is distinguished by type, which is related + # to its value's data type. Second, nodes should be checked for + # availability and readability/writability prior to making an + # attempt to read from or write to the node. + # + # Note that for Python, the node retrieved then has to be 'cast' + # to the proper type (CStringPtr in this case) before it can be used. + node_interface_display_name = PySpin.CStringPtr(nodemap_interface.GetNode('InterfaceDisplayName')) + + if PySpin.IsAvailable(node_interface_display_name) and PySpin.IsReadable(node_interface_display_name): + interface_display_name = node_interface_display_name.GetValue() + + print(interface_display_name) + + else: + print('Interface display name not readable') + + # Update list of cameras on the interface + # + # *** NOTES *** + # Updating the cameras on each interface is especially important if + # there has been any device arrivals or removals since the last time + # that UpdateCameras() was called. + interface.UpdateCameras() + + # Retrieve list of cameras from the interface + # + # *** NOTES *** + # Camera lists can be retrieved from an interface or the system object. + # Camera lists retrieved from an interface, such as this one, only + # return cameras attached on that specific interface whereas camera + # lists retrieved from the system will return all cameras on all + # interfaces. + # + # *** LATER *** + # Camera lists must be cleared manually. This must be done prior to + # releasing the system and while the camera list is still in scope. + cam_list = interface.GetCameras() + + # Retrieve number of cameras + num_cams = cam_list.GetSize() + + # Return if no cameras detected + if num_cams == 0: + print('\tNo devices detected.\n') + return result + + # Print device vendor and model name for each camera on the interface + for i, cam in enumerate(cam_list): + + # Retrieve TL device nodemap; please see NodeMapInfo example for + # additional comments on transport layer nodemaps + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + # Print device vendor name and device model name + # + # *** NOTES *** + # Grabbing node information requires first retrieving the node and + # then retrieving its information. There are two things to keep in + # mind. First, a node is distinguished by type, which is related + # to its value's data type. Second, nodes should be checked for + # availability and readability/writability prior to making an + # attempt to read from or write to the node. + node_device_vendor_name = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceVendorName')) + + if PySpin.IsAvailable(node_device_vendor_name) and PySpin.IsReadable(node_device_vendor_name): + device_vendor_name = node_device_vendor_name.ToString() + + node_device_model_name = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceModelName')) + + if PySpin.IsAvailable(node_device_model_name) and PySpin.IsReadable(node_device_model_name): + device_model_name = node_device_model_name.ToString() + + print('\tDevice %i %s %s \n' % (i, device_vendor_name, device_model_name)) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before losing scope + # + # *** NOTES *** + # Camera lists (and interface lists) must be cleared manually while in + # the same scope that the system is released. However, in cases like this + # where scope is lost, camera lists (and interface lists) will be cleared + # automatically. + cam_list.Clear() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + # + # *** NOTES *** + # Everything originates with the system object. It is important to notice + # that it has a singleton implementation, so it is impossible to have + # multiple system objects at the same time. Users can only get a smart + # pointer (SystemPtr) to the system instance. + # + # *** LATER *** + # The system object should be cleared prior to program completion. If not + # released explicitly, it will be released automatically when all SystemPtr + # objects that point to the system go out of scope. + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of interfaces from the system + # + # *** NOTES *** + # Interface lists are retrieved from the system object. + # + # *** LATER *** + # Interface lists must be cleared manually. This must be done prior to + # releasing the system and while the interface list is still in scope. + iface_list = system.GetInterfaces() + + # Get number of interfaces + num_interfaces = iface_list.GetSize() + + print('Number of interfaces detected: %i' % num_interfaces) + + # Retrieve list of cameras from the system + # + # *** NOTES *** + # Camera lists can be retrieved from an interface or the system object. + # Camera lists retrieved from the system, such as this one, return all + # cameras available on the system. + # + # *** LATER *** + # Camera lists must be cleared manually. This must be done prior to + # releasing the system and while the camera list is still in scope. + cam_list = system.GetCameras() + + num_cams = cam_list.GetSize() + + print('Number of cameras detected: %i' % num_cams) + + # Finish if there are no cameras + if num_cams == 0 or num_interfaces == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Clear interface list before releasing system + iface_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + print('\n*** QUERYING INTERFACES ***\n') + + for iface in iface_list: + + # Query interface + result &= query_interface(iface) + + # Release reference to interface + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del iface + + # Clear camera list before releasing system + # + # *** NOTES *** + # Camera lists must be cleared manually prior to a system release call. + cam_list.Clear() + + # Clear interface list before releasing system + # + # *** NOTES *** + # Interface lists must be cleared manually prior to a system release call. + iface_list.Clear() + + # Release system instance + # + # *** NOTES *** + # The system should be released, but if it is not, it will do so itself. + # It is often at the release of the system (whether manual or automatic) + # that unreleased resources and still-registered events will throw an + # exception. + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/EnumerationEvents.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/EnumerationEvents.py new file mode 100644 index 0000000..3761d54 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/EnumerationEvents.py @@ -0,0 +1,216 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# EnumerationEvents.py explores arrival and removal events on interfaces and the system. +# It relies on information provided in the Enumeration, Acquisition, and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the NodeMapCallback example, +# as nodemap callbacks follow the same general procedure as events, but with a few less steps. +# +# This example creates two user-defined classes: InterfaceEventHandler and SystemEventHandler. +# These child classes allow the user to define properties, parameters, and the event handler itself +# while the parent classes - DeviceArrivalEventHandler, DeviceRemovalEventHandler, and InterfaceEventHandler - +# allow the child classes to interface with Spinnaker. + +import PySpin + + +class SystemEventHandler(PySpin.InterfaceEventHandler): + """ + This class defines the properties and methods for device arrivals and removals + on the system. Take special note of the signatures of the OnDeviceArrival() + and OnDeviceRemoval() methods. + All three event handler types - DeviceArrivalEventHandler, DeviceRemovalEventHandler, + and InterfaceEventHandler - can be registered to interfaces, the system, or both. + However, in Spinnaker Python, an enumeration event handler must inherit from + InterfaceEventHandler if we want to handle both arrival and removal events. + + *** NOTES *** + Registering an interface event handler to the system is basically the same thing + as registering that event handler to all interfaces, with the added benefit of + not having to manage newly arrived or newly removed interfaces. In order to manually + manage newly arrived or removed interfaces, one would need to implement interface + arrival/removal event handlers, which are not yet supported in the Spinnaker Python API. + """ + def __init__(self, system): + """ + Constructor. This sets the system instance. + + :param system: Instance of the system. + :type system: SystemPtr + :rtype: None + """ + super(SystemEventHandler, self).__init__() + self.system = system + + + def OnDeviceArrival(self, serial_number): + """ + This method defines the arrival event on the system. It prints out + the device serial number of the camera arriving and the number of + cameras currently connected. The argument is the serial number of + the camera that triggered the arrival event. + + :param serial_number: gcstring representing the serial number of the arriving camera. + :type serial_number: gcstring + :return: None + """ + cam_list = self.system.GetCameras() + count = cam_list.GetSize() + print('System event handler:') + print('\tDevice %i has arrived on the system.' % serial_number) + print('\tThere %s %i %s on the system.' % ('is' if count == 1 else 'are', + count, + 'device' if count == 1 else 'devices')) + + + def OnDeviceRemoval(self, serial_number): + """ + This method defines the removal event on the system. It prints out the + device serial number of the camera being removed and the number of cameras + currently connected. The argument is the serial number of the camera that + triggered the removal event. + + :param serial_number: gcstring representing the serial number of the removed camera. + :type serial_number: gcstring + :return: None + """ + cam_list = self.system.GetCameras() + count = cam_list.GetSize() + print('System event handler:') + print('\tDevice %i was removed from the system.' % serial_number) + print('\tThere %s %i %s on the system.' % ('is' if count == 1 else 'are', + count, + 'device' if count == 1 else 'devices')) + + +def check_gev_enabled(system): + """ + This function checks if GEV enumeration is enabled on the system. + + :param system: Current system instance. + :type system: SystemPtr + + """ + + # Retrieve the System TL NodeMap and EnumerateGEVInterfaces node + system_node_map = system.GetTLNodeMap() + node_gev_enumeration = PySpin.CBooleanPtr(system_node_map.GetNode('EnumerateGEVInterfaces')) + + # Ensure the node is valid + if not PySpin.IsAvailable(node_gev_enumeration) or not PySpin.IsReadable(node_gev_enumeration): + print('EnumerateGEVInterfaces node is unavailable or unreadable. Aborting...') + return + + # Check if node is enabled + gev_enabled = node_gev_enumeration.GetValue() + if not gev_enabled: + print('\nWARNING: GEV Enumeration is disabled.') + print('If you intend to use GigE cameras please run the EnableGEVInterfaces shortcut\n' + 'or set EnumerateGEVInterfaces to true and relaunch your application.\n') + return + print('GEV enumeration is enabled. Continuing..') + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :rtype: None + """ + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Check if GEV enumeration is enabled + check_gev_enabled(system) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cams = cam_list.GetSize() + + print('Number of cameras detected: %i' % num_cams) + + # Retrieve list of interfaces from the system + # + # *** NOTES *** + # MacOS interfaces are only registered if they are active. + # For this example to have the desired outcome all devices must be connected + # at the beginning and end of this example in order to register and deregister + # an event handler on each respective interface. + iface_list = system.GetInterfaces() + + num_ifaces = iface_list.GetSize() + + print('Number of interfaces detected: %i' % num_ifaces) + + print('*** CONFIGURING ENUMERATION EVENTS *** \n') + + # Create interface event handler for the system + # + # *** NOTES *** + # The SystemEventHandler has been constructed to accept a system object in + # order to print the number of cameras on the system. + system_event_handler = SystemEventHandler(system) + + # Register interface event handler for the system + # + # *** NOTES *** + # Arrival, removal, and interface event handlers can all be registered to + # interfaces or the system. Do not think that interface event handlers can only be + # registered to an interface. An interface event handler is merely a combination + # of an arrival and a removal event handler. + # + # *** LATER *** + # Arrival, removal, and interface event handlers must all be unregistered manually. + # This must be done prior to releasing the system and while they are still + # in scope. + system.RegisterInterfaceEventHandler(system_event_handler) + + # Wait for user to plug in and/or remove camera devices + input('\nReady! Remove/Plug in cameras to test or press Enter to exit...\n') + + # Unregister system event handler from system object + # + # *** NOTES *** + # It is important to unregister all arrival, removal, and interface event handlers + # registered to the system. + system.UnregisterInterfaceEventHandler(system_event_handler) + + # Delete system event handler, which has a system reference + del system_event_handler + print('Event handler unregistered from system...') + + # Clear camera list before releasing system + cam_list.Clear() + + # Clear interface list before releasing system + iface_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + +if __name__ == '__main__': + main() diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Enumeration_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Enumeration_QuickSpin.py new file mode 100644 index 0000000..f016f64 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Enumeration_QuickSpin.py @@ -0,0 +1,260 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Enumeration_QuickSpin.py shows how to enumerate interfaces +# and cameras using the QuickSpin API. QuickSpin is a subset of the Spinnaker +# library that allows for simpler node access and control. This is a great +# example to start learning about QuickSpin. +# +# This example introduces the preparation, use, and cleanup of the system +# object, interface and camera lists, interfaces, and cameras. It also +# touches on retrieving information from pre-fetched nodes using QuickSpin. +# Retrieving node information is the only portion of the example that +# differs from Enumeration. +# +# A much wider range of topics is covered in the full Spinnaker examples than +# in the QuickSpin ones. There are only enough QuickSpin examples to +# demonstrate node access and to get started with the API; please see full +# Spinnaker examples for further or specific knowledge on a topic. + +import PySpin +import sys + + +def query_interface(interface): + """ + Queries an interface for its cameras and prints out device information. + + :param interface: InterfacePtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Print interface display name + # + # *** NOTES *** + # QuickSpin allows for the retrieval of interface information directly + # from an interface. Because interface information is made available + # on the transport layer, camera initialization is not required. + node_interface_display_name = interface.TLInterface.InterfaceDisplayName + if PySpin.IsAvailable(node_interface_display_name) and PySpin.IsReadable(node_interface_display_name): + + interface_display_name = node_interface_display_name.GetValue() + + print(interface_display_name) + + else: + print('Interface display name not readable') + + # Update list of cameras on the interface + # + # *** NOTES *** + # Updating the cameras on each interface is especially important if + # there has been any device arrivals or removals since the last time + # that UpdateCameras() was called. + interface.UpdateCameras() + + # Retrieve list of cameras from the interface + # + # *** NOTES *** + # Camera lists can be retrieved from an interface or the system object. + # Camera lists retrieved from an interface, such as this one, only + # return cameras attached on that specific interface whereas camera + # lists retrieved from the system will return all cameras on all + # interfaces. + # + # *** LATER *** + # Camera lists must be cleared manually. This must be done prior to + # releasing the system and while the camera list is still in scope. + cam_list = interface.GetCameras() + + # Retrieve number of cameras + num_cams = cam_list.GetSize() + + # Return if no cameras detected + if num_cams == 0: + print('\tNo devices detected.\n') + return True + + # Print device vendor and model name for each camera on the interface + for i, cam in enumerate(cam_list): + + # Print device vendor name and device model name + # + # *** NOTES *** + # In QuickSpin, accessing nodes does not require first retrieving a + # nodemap. Instead, GenICam nodes are made available + # directly through the camera, and transport layer nodes are made + # available through the camera's TLDevice and TLStream properties. + # + # Most camera interaction happens through the GenICam nodemap, which + # requires the device to be initialized. Simpler reads, like the + # ones below, can often be accomplished at the transport layer, + # which does not require initialization; please see + # NodeMapInfo_QuickSpin for additional information on this topic. + # + # Readability/writability should be checked prior to interacting with + # nodes. Readability and writability are ensured by checking the + # access mode or by using the methods + if cam.TLDevice.DeviceVendorName.GetAccessMode() == PySpin.RO: + device_vendor_name = cam.TLDevice.DeviceVendorName.ToString() + + if cam.TLDevice.DeviceModelName.GetAccessMode() == PySpin.RO: + device_model_name = cam.TLDevice.DeviceModelName.GetValue() + + print('\tDevice %i %s %s \n' % (i, device_vendor_name, device_model_name)) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before losing scope + # + # *** NOTES *** + # Camera lists (and interface lists) must be cleared manually while in + # the same scope that the system is released. However, in cases like this + # where scope is lost, camera lists (and interface lists) will be cleared + cam_list.Clear() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point. + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + # + # *** NOTES *** + # Everything originates with the system object. It is important to notice + # that it has a singleton implementation, so it is impossible to have + # multiple system objects at the same time. Users can only get a smart + # pointer (SystemPtr) to the system instance. + # + # *** LATER *** + # The system object should be cleared prior to program completion. If not + # released explicitly, it will be released automatically when all SystemPtr + # objects that point to the system go out of scope. + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of interfaces from the system + # + # *** NOTES *** + # Interface lists are retrieved from the system object. + # + # *** LATER *** + # Interface lists must be cleared manually. This must be done prior to + # releasing the system and while the interface list is still in scope. + iface_list = system.GetInterfaces() + + # Get number of interfaces + num_ifaces = iface_list.GetSize() + + print('Number of interfaces detected: %i' % num_ifaces) + + # Retrieve list of cameras from the system + # + # *** NOTES *** + # Camera lists can be retrieved from an interface or the system object. + # Camera lists retrieved from the system, such as this one, return all + # cameras available on the system. + # + # *** LATER *** + # Camera lists must be cleared manually. This must be done prior to + # releasing the system and while the camera list is still in scope. + cam_list = system.GetCameras() + + num_cams = cam_list.GetSize() + + print('Number of cameras detected: %i' % num_cams) + + # Finish if there are no cameras + if num_cams == 0 or num_ifaces == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Clear interface list before releasing system + iface_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + print('\n*** QUERYING INTERFACES ***\n') + + for iface in iface_list: + + # Query interface + result &= query_interface(iface) + + # Release reference to interface + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del iface + + # Clear camera list before releasing system + # + # *** NOTES *** + # Camera lists must be cleared manually prior to a system release call. + cam_list.Clear() + + # Clear interface list before releasing system + # + # *** NOTES *** + # Interface lists must be cleared manually prior to a system release call. + iface_list.Clear() + + # Release system instance + # + # *** NOTES *** + # The system should be released, but if it is not, it will do so itself. + # It is often at the release of the system (whether manual or automatic) + # that unreleased resources and still registered events will throw an + # exception. + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Exposure_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Exposure_QuickSpin.py new file mode 100644 index 0000000..af71c34 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Exposure_QuickSpin.py @@ -0,0 +1,369 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Exposure_QuickSpin.py shows how to customize image exposure time +# using the QuickSpin API. QuickSpin is a subset of the Spinnaker library +# that allows for simpler node access and control. +# +# This example prepares the camera, sets a new exposure time, and restores +# the camera to its default state. Ensuring custom values fall within an +# acceptable range is also touched on. Retrieving and setting information +# is the only portion of the example that differs from Exposure. +# +# A much wider range of topics is covered in the full Spinnaker examples than +# in the QuickSpin ones. There are only enough QuickSpin examples to +# demonstrate node access and to get started with the API; please see full +# Spinnaker examples for further or specific knowledge on a topic. + +import PySpin +import sys + +NUM_IMAGES = 5 # number of images to save + + +def configure_exposure(cam): + """ + This function configures a custom exposure time. Automatic exposure is turned + off in order to allow for the customization, and then the custom setting is + applied. + + :param cam: Camera to configure exposure for. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** CONFIGURING EXPOSURE ***\n') + + try: + result = True + + # Turn off automatic exposure mode + # + # *** NOTES *** + # Automatic exposure prevents the manual configuration of exposure + # times and needs to be turned off for this example. Enumerations + # representing entry nodes have been added to QuickSpin. This allows + # for the much easier setting of enumeration nodes to new values. + # + # The naming convention of QuickSpin enums is the name of the + # enumeration node followed by an underscore and the symbolic of + # the entry node. Selecting "Off" on the "ExposureAuto" node is + # thus named "ExposureAuto_Off". + # + # *** LATER *** + # Exposure time can be set automatically or manually as needed. This + # example turns automatic exposure off to set it manually and back + # on to return the camera to its default state. + + if cam.ExposureAuto.GetAccessMode() != PySpin.RW: + print('Unable to disable automatic exposure. Aborting...') + return False + + cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Off) + print('Automatic exposure disabled...') + + # Set exposure time manually; exposure time recorded in microseconds + # + # *** NOTES *** + # Notice that the node is checked for availability and writability + # prior to the setting of the node. In QuickSpin, availability and + # writability are ensured by checking the access mode. + # + # Further, it is ensured that the desired exposure time does not exceed + # the maximum. Exposure time is counted in microseconds - this can be + # found out either by retrieving the unit with the GetUnit() method or + # by checking SpinView. + + if cam.ExposureTime.GetAccessMode() != PySpin.RW: + print('Unable to set exposure time. Aborting...') + return False + + # Ensure desired exposure time does not exceed the maximum + exposure_time_to_set = 2000000.0 + exposure_time_to_set = min(cam.ExposureTime.GetMax(), exposure_time_to_set) + cam.ExposureTime.SetValue(exposure_time_to_set) + print('Shutter time set to %s us...\n' % exposure_time_to_set) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def reset_exposure(cam): + """ + This function returns the camera to a normal state by re-enabling automatic exposure. + + :param cam: Camera to reset exposure on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Turn automatic exposure back on + # + # *** NOTES *** + # Automatic exposure is turned on in order to return the camera to its + # default state. + + if cam.ExposureAuto.GetAccessMode() != PySpin.RW: + print('Unable to enable automatic exposure (node retrieval). Non-fatal error...') + return False + + cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Continuous) + + print('Automatic exposure enabled...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def print_device_info(cam): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param cam: Camera to get device information from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** DEVICE INFORMATION ***\n') + + try: + result = True + nodemap = cam.GetTLDeviceNodeMap() + + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex.message) + return False + + return result + + +def acquire_images(cam): + """ + This function acquires and saves 10 images from a device; please see + Acquisition example for more in-depth comments on the acquisition of images. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + print('*** IMAGE ACQUISITION ***') + + try: + result = True + + # Set acquisition mode to continuous + if cam.AcquisitionMode.GetAccessMode() != PySpin.RW: + print('Unable to set acquisition mode to continuous. Aborting...') + return False + + cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous) + print('Acquisition mode set to continuous...') + + # Begin acquiring images + cam.BeginAcquisition() + + print('Acquiring images...') + + # Get device serial number for filename + device_serial_number = '' + if cam.TLDevice.DeviceSerialNumber is not None and cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + device_serial_number = cam.TLDevice.DeviceSerialNumber.GetValue() + + print('Device serial number retrieved as %s...' % device_serial_number) + + # Get the value of exposure time to set an appropriate timeout for GetNextImage + timeout = 0 + if cam.ExposureTime.GetAccessMode() == PySpin.RW or cam.ExposureTime.GetAccessMode() == PySpin.RO: + # The exposure time is retrieved in µs so it needs to be converted to ms to keep consistency with the unit being used in GetNextImage + timeout = (int)(cam.ExposureTime.GetValue() / 1000 + 1000) + else: + print ('Unable to get exposure time. Aborting...') + return False + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + # Retrieve next received image and ensure image completion + # By default, GetNextImage will block indefinitely until an image arrives. + # In this example, the timeout value is set to [exposure time + 1000]ms to ensure that an image has enough time to arrive under normal conditions + image_result = cam.GetNextImage(timeout) + + if image_result.IsIncomplete(): + print('Image incomplete with image status %d...' % image_result.GetImageStatus()) + + else: + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Grabbed Image %d, width = %d, height = %d' % (i, width, height)) + + # Convert image to Mono8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8) + + # Create a unique filename + filename = 'ExposureQS-%s-%d.jpg' % (device_serial_number, i) + + # Save image + image_converted.Save(filename) + + print('Image saved at %s' % filename) + + # Release image + image_result.Release() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo_QuickSpin example for more + in-depth comments on setting up cameras. + + :param cam: Camera to run example on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + # Initialize camera + cam.Init() + + # Print device info + result = print_device_info(cam) + + # Configure exposure + if not configure_exposure(cam): + return False + + # Acquire images + result &= acquire_images(cam) + + # Reset exposure + result &= reset_exposure(cam) + + # Deinitialize camera + cam.DeInit() + + return result + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + +def main(): + """ + Example entry point; please see Enumeration_QuickSpin example for more + in-depth comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/FileAccess_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/FileAccess_QuickSpin.py new file mode 100644 index 0000000..f2dae8c --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/FileAccess_QuickSpin.py @@ -0,0 +1,692 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# FileAccess_QuickSpin.py shows shows how to read and write images using camera File Access function. +# +# This example uploads an image to the camera File Access storage and also +# downloads the image from the camera File Access storage and saves it to +# the disk. +# +# It also provides debug message when an additional argument `--verbose` is passed in, +# giving more detailed status of the progress to the users. +# +# Run with arguments in format (no quotes): "--mode --verbose (optional)" +# /d: Download saved image from camera and save it to the working directory. +# /u: Grab an image and store it on camera. +# + +import PySpin +import numpy as np +import os +import argparse +import sys + +parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) +subparsers = parser.add_subparsers() + +class ImageAcquisitionUtil: + @staticmethod + def check_node_readable(node): + return PySpin.IsAvailable(node) and PySpin.IsReadable(node) + + @staticmethod + def grab_reference_image(cam): + """ + This function first grabs 5 images to stablize the camera, + then it grabs a reference image and returns its pointer. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: Pointer to the reference image + :rtype: ImagePtr + """ + reference_image = PySpin.Image.Create() + + # Start capturing images + cam.BeginAcquisition() + + # Grab a couple of images to stabilize the camera + for image_count in range(5): + try: + result_image = cam.GetNextImage(1000) + if result_image.IsIncomplete(): + print('Imgae incomplete with image status %s' % result_image.GetImageStatus()) + else: + print('Grabbed image %s' %str(image_count) + ', width = %s' % str(result_image.GetWidth())\ + + ', height = %s' % str(result_image.GetHeight())) + reference_image.DeepCopy(result_image) + result_image.Release() + except PySpin.SpinnakerException as ex: + print(ex) + continue + + cam.EndAcquisition() + + return reference_image + +class FileAccess: + @staticmethod + def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print('*** DEVICE INFORMATION ***\n') + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if ImageAcquisitionUtil.check_node_readable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + print('') + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + @staticmethod + def execute_delete_command(cam): + """ + This function executes delete operation on the camera. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Delete) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print('Failed to delete file!') + return False + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + return True + + @staticmethod + def open_file_to_write(cam): + """ + This function opens the camera file for writing. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Open) + cam.FileOpenMode.SetValue(PySpin.FileOpenMode_Write) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print('Failed to open file for writing!') + return False + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + return True + + @staticmethod + def execute_write_command(cam): + """ + This function executes write command on the camera. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Write) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print('Failed to write to file!') + return False + except PySpin.SpinnakerException as ex: + print('Unexpected exception : %s' % ex) + return False + return True + + @staticmethod + def close_file(cam): + """ + This function closes the file. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Close) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print('Failed to close file!') + return False + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + return True + + @staticmethod + def upload_image(cam, verbose=False): + """ + This function first acquires a reference image from the camera, + then it writes the image file to the camera with file selector UserFile1. + + :param cam: Camera used to download file from. + :param verbose: Prints additional details of file download (False by default) + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + success = True + + nodemap_tldevice = cam.GetTLDeviceNodeMap() + FileAccess.print_device_info(nodemap_tldevice) + + cam.Init() + + # Check file selector support + print('Checking file selector support') + if cam.FileSelector.GetAccessMode() == PySpin.NA or cam.FileSelector.GetAccessMode() == PySpin.NI: + print('File selector not supported on device!') + return False + + # Apply small pixel format + if ImageAcquisitionUtil.check_node_readable(cam.PixelFormat.GetEntry(PySpin.PixelFormat_Mono8)): + cam.PixelFormat.SetValue(PySpin.PixelFormat_Mono8) + else: + # Use Bayer8 if Mono8 is not available + cam.PixelFormat.SetValue(PySpin.PixelFormat_BayerGB8) + + # Display camera setup information + print('Width: %s' % cam.Width.GetValue()) + print('Height: %s' % cam.Height.GetValue()) + print('offsetX: %s' % cam.OffsetX.GetValue()) + print('OffsetY: %s' % cam.OffsetY.GetValue()) + print('PixelFormat: %s' % cam.PixelFormat.GetValue()) + + # Grab reference image + try: + reference_image = ImageAcquisitionUtil.grab_reference_image(cam) + except PySpin.SpinnakerException as ex: + cam.DeInit() + del cam + print('Unexpected error grabbing reference image: %s' % ex) + return False + + # Form file path + filename = "DeviceStreamWrite-" + if cam.DeviceSerialNumber.GetAccessMode() == PySpin.RW or cam.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + filename += "%s-" % cam.DeviceSerialNumber.ToString() + filename += ".bmp" + + # Save image + reference_image.Save(filename) + print('Image saved at %s' % filename) + + print('*** UPLOADING IMAGE ***') + + # Perform file stream write + selector_list = cam.FileSelector.GetEntries() + + for entry in selector_list: + # Get current enum entry node + node = PySpin.CEnumEntryPtr(entry) + + if verbose: + print('\nChecking FileSelector EnumEntry - %s' % node.GetSymbolic()) + + # Check file selector entry support + if not node or not ImageAcquisitionUtil.check_node_readable(node): + # Go to next entry node + print('%s not supported!' % node.GetSymbolic()) + continue + + if node.GetSymbolic() == "UserFile1": + # Set file selector + cam.FileSelector.SetIntValue(int(node.GetNumericValue())) + + # Delete file on camera before writing in case camera runs out of space + file_size = cam.FileSize.GetValue() + if file_size > 0: + if not FileAccess.execute_delete_command(cam): + print('Failed to delete file!') + success = False + continue + + # Open file on camera for write + if not FileAccess.open_file_to_write(cam): + print('Failed to open file!') + success = False + continue + + # Attempt to set FileAccessLength to FileAccessBufferNode length to speed up the write + if cam.FileAccessLength.GetValue() < cam.FileAccessBuffer.GetLength(): + try: + cam.FileAccessLength.SetValue(cam.FileAccessBuffer.GetLength()) + except PySpin.SpinnakerException as ex: + print('Unable to set FileAccessLength to FileAccessBuffer length: %s' % ex) + + # Set file access offset to zero if it's not + cam.FileAccessOffset.SetValue(0) + + # Compute number of write operations required + total_bytes_to_write = reference_image.GetBufferSize() + intermediate_buffer_size = cam.FileAccessLength.GetValue() + write_iterations = (total_bytes_to_write // intermediate_buffer_size) + \ + (0 if ((total_bytes_to_write % intermediate_buffer_size) == 0) else 1) + + if total_bytes_to_write == 0: + print('Empty Image. No data will be written to camera.') + return False + + if verbose: + print('') + print('Total bytes to write: %s' % total_bytes_to_write) + print('FileAccessLength: %s' % intermediate_buffer_size) + print('Write iterations: %s' % write_iterations) + + bytes_left_to_write = total_bytes_to_write + total_bytes_written = 0 + + print('Writing data to device') + + # Splitting the file into equal chunks (except the last chunk) + sections = [] + for index in range(write_iterations): + offset = index * intermediate_buffer_size + if offset == 0: + continue + sections.append(offset) + + # Get image data and split into equal chunks + image_data = reference_image.GetData() + split_data = np.array_split(image_data, sections) + + for i in range(len(split_data)): + # Setup data to write + tmp_buffer = split_data[i] + + # Write to AccessBufferNode + cam.FileAccessBuffer.Set(tmp_buffer) + + if intermediate_buffer_size > bytes_left_to_write: + # Update FileAccessLength, otherwise garbage data outside the range would be written to device + cam.FileAccessLength.SetValue(bytes_left_to_write) + + # Perform write command + if not FileAccess.execute_write_command(cam): + print('Writing stream failed!') + success = False + break + + # Verify size of bytes written + size_written = cam.FileOperationResult.GetValue() + + # Log current file access offset + if verbose: + print('File Access Offset: %s' % cam.FileAccessOffset.GetValue()) + + # Keep track of total bytes written + total_bytes_written += size_written + if verbose: + print('Bytes written: %s of %s' % (total_bytes_written, total_bytes_to_write)) + + # Keep track of bytes left to write + bytes_left_to_write = total_bytes_to_write - total_bytes_written + + if verbose: + print('Progress: (%s//%s)' % (i, write_iterations)) + else: + print('Progress: %s' % int((i*100 / write_iterations)) + "%") + + print('Writing complete') + + if not FileAccess.close_file(cam): + success = False + + cam.DeInit() + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + return success + + @staticmethod + def open_file_to_read(cam): + """ + This function opens the file to read. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Open) + cam.FileOpenMode.SetValue(PySpin.FileOpenMode_Read) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print('Failed to open file for reading!') + return False + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + return True + + @staticmethod + def execute_read_command(cam): + """ + This function executes read command on the camera. + + :param cam: Camera used to perform file operation. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + cam.FileOperationSelector.SetValue(PySpin.FileOperationSelector_Read) + cam.FileOperationExecute.Execute() + + if cam.FileOperationStatus.GetValue() != PySpin.FileOperationStatus_Success: + print('Failed to read file!') + return False + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + return True + + @staticmethod + def download_image(cam, verbose=False): + """ + This function reads the image file stored in the camera file selector UserFile1, + saving the file to the working directory of this example. + + :param cam: Camera used to download file from. + :param verbose: Prints additional details of file download (False by default) + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + success = True + + nodemap_tldevice = cam.GetTLDeviceNodeMap() + FileAccess.print_device_info(nodemap_tldevice) + + cam.Init() + + # Check file selector support + print('Checking file selector support') + if cam.FileSelector.GetAccessMode() == PySpin.NA or cam.FileSelector.GetAccessMode() == PySpin.NI: + print('File selector not supported on device!') + return False + + print('*** DOWNLOADING IMAGE ***') + + selector_list = cam.FileSelector.GetEntries() + + for entry in selector_list: + node = PySpin.CEnumEntryPtr(entry) + if verbose: + print('\nChecking FileSelector EnumEntry - %s' % node.GetSymbolic()) + + # Check file selector entry support + if not node or not ImageAcquisitionUtil.check_node_readable(node): + # Go to next entry node + print('%s not supported!' % node.GetSymbolic()) + continue + + # Use UserFile1 as the selector in this example. + # Available file selector entries varies across different cameras + if node.GetSymbolic() == "UserFile1": + # Set file selector + cam.FileSelector.SetIntValue(int(node.GetNumericValue())) + + # Get file size + total_bytes_to_read = cam.FileSize.GetValue() + if total_bytes_to_read == 0: + print('%s - No data available to read!' % node.GetSymbolic()) + success = False + continue + + print('Total data to download: %s' % total_bytes_to_read) + + # Open file on camera for reading + if not FileAccess.open_file_to_read(cam): + print('Failed to open file!') + success = False + continue + + # Attempt to set FileAccessLength to FileAccessBufferNode length to speed up the write + if cam.FileAccessLength.GetValue() < cam.FileAccessBuffer.GetLength(): + try: + cam.FileAccessLength.SetValue(cam.FileAccessBuffer.GetLength()) + except PySpin.SpinnakerException as ex: + print('Unable to set FileAccessLength to FileAccessBuffer length: %s' % ex) + + # Set file access offset to zero + cam.FileAccessOffset.SetValue(0) + + # Computer number of read operations required + intermediate_buffer_size = cam.FileAccessLength.GetValue() + read_iterations = (total_bytes_to_read // intermediate_buffer_size) + \ + (0 if ((total_bytes_to_read % intermediate_buffer_size) == 0) else 1) + + if verbose: + print('') + print('Total bytes to read: %s' % total_bytes_to_read) + print('FileAccessLength: %s' % intermediate_buffer_size) + print('Write iterations: %s' % read_iterations) + + print('Fetching image from camera.') + + total_size_read = 0 + size_read = cam.FileOperationResult.GetValue() + image_data = np.array(size_read, dtype=np.uint8) + + for i in range(read_iterations): + if not FileAccess.execute_read_command(cam): + print('Reading stream failed!') + success = False + break + + # Verify size of bytes read + size_read = cam.FileOperationResult.GetValue() + + # Read from buffer Node + buffer_read = cam.FileAccessBuffer.Get(size_read) + if i == 0: + image_data = buffer_read + else: + image_data = np.append(image_data, buffer_read) + + # Keep track of total bytes read + total_size_read += size_read + if verbose: + print('Bytes read: %s of %s' % (total_size_read, total_bytes_to_read)) + print('Progress: (%s//%s)' % (i, read_iterations)) + else: + print('Progress: %s' % int((i*100 / read_iterations)) + "%") + + print('Reading complete') + + if not FileAccess.close_file(cam): + success = False + + # Form file path + filename = "DeviceStreamRead-" + + if cam.DeviceSerialNumber.GetAccessMode() == PySpin.RW or cam.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + filename += "%s-" % cam.DeviceSerialNumber.ToString() + + filename += ".bmp" + + # Image should be captured with Mono8 or Bayer8, it sets camera to correct pixel format + # in order to grab image ROI + if ImageAcquisitionUtil.check_node_readable(cam.PixelFormat.GetEntry(PySpin.PixelFormat_Mono8)): + cam.PixelFormat.SetValue(PySpin.PixelFormat_Mono8) + elif ImageAcquisitionUtil.check_node_readable(cam.PixelFormat.GetEntry(PySpin.PixelFormat_BayerGB8)): + # Use Bayer8 if Mono8 is not available + cam.PixelFormat.SetValue(PySpin.PixelFormat_BayerGB8) + else: + print('Failed to set camera pixel format.') + return False + + width = cam.Width.GetValue() + height = cam.Height.GetValue() + offset_x = cam.OffsetX.GetValue() + offset_y = cam.OffsetY.GetValue() + pixel_format = cam.PixelFormat.GetValue() + + # Form image and save data + print('Width: %s' % width) + print('Height: %s' % height) + print('OffsetX: %s' % offset_x) + print('OffsetY: %s' % offset_y) + print('PixelFormat: %s' % pixel_format) + + # Create image + image = PySpin.Image.Create(width, height, offset_x, offset_y, pixel_format, image_data) + + # Save image + image.Save(filename) + print('Image saved at %s' % filename) + + cam.DeInit() + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + return success + +def main(): + """ + Example entry point; please see Enumeration.py example for more in-depth + comments on preparing and cleaning up the system with PySpin. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = False + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + parser = argparse.ArgumentParser() + parser = subparsers.add_parser('stop', formatter_class=argparse.RawTextHelpFormatter) + + parser.add_argument('--mode', required=True, type=str, + help='/u : Grab an image and store it on camera.\n/d : Download saved image from camera and save it to the working directory.\n') + parser.add_argument('--verbose', default=False, action='store_true', + help='Enable verbose output.') + + args = parser.parse_args() + + cam_list = system.GetCameras() + num_cameras = cam_list.GetSize() + + # This example only works with 1 camera is connected. + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + elif num_cameras > 1: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('This example only works when 1 camera is connected.') + input('Done! Press Enter to exit...') + return False + else: + if args.mode == '/u' or args.mode == '/U': + result = FileAccess.upload_image(cam_list[0], args.verbose) + elif args.mode == '/d' or args.mode == '/D': + result = FileAccess.download_image(cam_list[0], args.verbose) + else: + print("Invalid Argument! Use '--help' to learn available arguments.") + input('Done! Press Enter to exit...') + return False + + if not result: + print('File Access failed') + else: + print('File Access is successful!') + + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/HighDynamicRange.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/HighDynamicRange.py new file mode 100644 index 0000000..da60789 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/HighDynamicRange.py @@ -0,0 +1,302 @@ +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# HighDynamicRange.py +# This example shows how to set High Dynamic Range (HDR) if it is available on the camera. + +import PySpin +import os +import sys + +NUM_IMAGES = 4 # number of images to grab + +K_HDR_SHUTTER1 = 1000 # us +K_HDR_SHUTTER2 = 5000 +K_HDR_SHUTTER3 = 15000 +K_HDR_SHUTTER4 = 30000 + +K_HDR_GAIN1 = 0 # dB +K_HDR_GAIN2 = 5 +K_HDR_GAIN3 = 10 +K_HDR_GAIN4 = 15 + + +def print_device_info(nodemap): + """ + Helper for outputting camera information + + :param nodemap: Transport layer device nodemap. + :type INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print('*** DEVICE INFORMATION ***') + + try: + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceControl')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return True + +def check_node_accessibility(node): + """ + Helper for checking GenICam node accessibility + + :param node: GenICam node being checked + :type node: CNodePtr + :return: True if accessible, False otherwise + :rtype: bool + """ + + return PySpin.IsAvailable(node) and (PySpin.IsReadable(node) or PySpin.IsWritable(node)) + +def toggle_hdr_mode(nodemap, hdr_on): + """ + Helper for toggling HDR mode on camera + + :param nodemap: Transport layer device nodemap. + :type: INodeMap + :param hdr_on: True if want to turn hdr mode on, False otherwise. + :type hdr_on: bool + :return: True if successful, False otherwise. + :rtype: bool + """ + + node_hdr_enabled = PySpin.CBooleanPtr(nodemap.GetNode("PGR_HDRModeEnabled")) + + if check_node_accessibility(node_hdr_enabled): + node_hdr_enabled.SetValue(hdr_on) + else: + return False + + print('HDR mode turned to', hdr_on) + + return True + +def initialize_hdr_images(nodemap): + """ + Helper for initializing HDR images + + :param nodemap: Transport layer device nodemap. + :type: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + hdr_image_selector = PySpin.CEnumerationPtr(nodemap.GetNode("PGR_HDRImageSelector")) + hdr_exposure_abs = PySpin.CFloatPtr(nodemap.GetNode("PGR_HDR_ExposureTimeAbs")) + hdr_gain_abs = PySpin.CFloatPtr(nodemap.GetNode("PGR_HDR_GainAbs")) + + if not check_node_accessibility(hdr_image_selector): + return False + if not check_node_accessibility(hdr_exposure_abs): + return False + if not check_node_accessibility(hdr_gain_abs): + return False + + # Configure Image1 + hdr_image_selector.SetIntValue(hdr_image_selector.GetEntryByName("Image1").GetValue()) + hdr_exposure_abs.SetValue(K_HDR_SHUTTER1) + hdr_gain_abs.SetValue(K_HDR_GAIN1) + print('Initialized HDR Image1...') + + # Configure Image2 + hdr_image_selector.SetIntValue(hdr_image_selector.GetEntryByName("Image2").GetValue()) + hdr_exposure_abs.SetValue(K_HDR_SHUTTER2) + hdr_gain_abs.SetValue(K_HDR_GAIN2) + print('Initialized HDR Image2...') + + # Configure Image3 + hdr_image_selector.SetIntValue(hdr_image_selector.GetEntryByName("Image3").GetValue()) + hdr_exposure_abs.SetValue(K_HDR_SHUTTER3) + hdr_gain_abs.SetValue(K_HDR_GAIN3) + print('Initialized HDR Image3...') + + # Configure Image4 + hdr_image_selector.SetIntValue(hdr_image_selector.GetEntryByName("Image4").GetValue()) + hdr_exposure_abs.SetValue(K_HDR_SHUTTER4) + hdr_gain_abs.SetValue(K_HDR_GAIN4) + print('Initialized HDR Image4...') + + return True + +def run_single_camera(cam): + """ + Helper for running example on single camera + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Initialize camera + cam.Init() + + # Get GenICam NodeMap info from camera + nodemap = cam.GetNodeMap() + + # Get camera information through NodeMap + print_device_info(nodemap) + + # Verify whether HDR is supported on this device + node_hdr_enabled = PySpin.CBooleanPtr(nodemap.GetNode("PGR_HDRModeEnabled")) + if not PySpin.IsAvailable(node_hdr_enabled): + print('HDR is not supported! Exiting...') + return True + + # HDR needs to be enabled prior to configure individual HDR images + toggle_hdr_mode(nodemap, True) + + if not initialize_hdr_images(nodemap): + print('Error configuring HDR image! Exiting...') + return False + + # Retrieve Device ID + device_id = cam.GetTLDeviceNodeMap().GetNode("DeviceID") + + # Begin capturing images + print('Starting grabbing images...') + cam.BeginAcquisition() + + for i in range(NUM_IMAGES): + try: + # Retrieve the next received image + raw_image = cam.GetNextImage(1000) + width = raw_image.GetWidth() + height = raw_image.GetHeight() + print('Grabbed image %d, width = %d, height = %d' % (i, width, height)) + + # Convert image to Mono8 + converted_image = raw_image.Convert(PySpin.PixelFormat_Mono8) + + # Create a unique filename + filename = 'HighDynamicRange-%s-%d.jpg' % (device_id, i) + + # Save image + converted_image.Save(filename) + + # Image need to be released after use + raw_image.Release() + + except PySpin.SpinnakerException as ex: + print('Error Retrieving Image: %s' % ex) + result = False + continue + + # End capturing of images + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + print() + + return result + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for cam in cam_list: + result &= run_single_camera(cam) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageChannelStatistics.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageChannelStatistics.py new file mode 100644 index 0000000..7589b73 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageChannelStatistics.py @@ -0,0 +1,302 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# ImageChannelStatisitcs.py shows how to get the image data and channel statistics, and then saves / displays them. +# This example relies on information provided in the Acquisition examples. +# +# This example demonstrates how to visualize the image histogram using Python, and display an image represented as +# a numpy array. +# +# NOTE: matplotlib must be installed on Python interpreter prior to running this example + +import os +import sys +import PySpin +import matplotlib.pyplot as plt + +NUM_IMAGES = 10 # number of images to grab + + +def acquire_and_display_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and displays the channel statistics of N images from a device. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** IMAGE ACQUISITION ***\n') + try: + result = True + + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (enum retrieval). Aborting...') + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...') + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + node_pixel_format = PySpin.CEnumerationPtr(nodemap.GetNode('PixelFormat')) + if not PySpin.IsAvailable(node_pixel_format) or not PySpin.IsWritable(node_pixel_format): + print('Unable to set Pixel Format. Aborting...') + return False + + else: + # Retrieve entry node from enumeration node + node_pixel_format_mono8 = PySpin.CEnumEntryPtr(node_pixel_format.GetEntryByName('Mono8')) + if not PySpin.IsAvailable(node_pixel_format_mono8) or not PySpin.IsReadable(node_pixel_format_mono8): + print('Unable to set Pixel Format to MONO8. Aborting...') + return False + + # Retrieve integer value from entry node + pixel_format_mono8 = node_pixel_format_mono8.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_pixel_format.SetIntValue(pixel_format_mono8) + + print('Pixel Format set to MONO8 ...') + + cam.BeginAcquisition() + + print('Acquiring images...') + + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Device serial number retrieved as %s...' % device_serial_number) + + plt.ion() + for i in range(NUM_IMAGES): + try: + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print('Image incomplete with image status %d ...' % image_result.GetImageStatus()) + else: + fig = plt.figure(1) + + try: + image_stats = image_result.CalculateChannelStatistics(PySpin.GREY) + # Getting the image data as a numpy array + image_data = image_result.GetNDArray() + + # Display Statistics + print('SN%s image %d:' % (device_serial_number, i)) + print('\tNumber pixel values : %d' % image_stats.num_pixel_values) + print('\tRange: Min = %d, Max = %d' % (image_stats.range_min, + image_stats.range_max)) + print('\tPixel Value: Min = %d, Max = %d, Mean = %.2f' % (image_stats.pixel_value_min, + image_stats.pixel_value_max, + image_stats.pixel_value_mean)) + + # Using matplotlib, two subplots are created where the top subplot is the histogram and the + # bottom subplot is the image. + # + # Refer to https://matplotlib.org/2.0.2/api/pyplot_api.html#module-matplotlib.pyplot + + # Clear the figure to reuse for next plot + plt.clf() + + # Plot the histogram in the first subplot in a 2 row by 1 column grid + plt.subplot(211) + plt.cla() + plt.plot(image_stats.histogram, label='Grey') + plt.title('SN%s Histogram (%d)' % (device_serial_number, i)) + plt.legend() + + # Plot the image in the second subplot in a 2 row by 1 column grid + plt.subplot(212) + plt.cla() + plt.imshow(image_data, cmap='gray') + + # Show the image + plt.show() + plt.pause(0.01) + + # Create a unique filename + if device_serial_number: + filename = 'ImageChannelStatistics-%s-%d.png' % (device_serial_number, i) + else: # if serial number is empty + filename = 'ImageChannelStatistics-%d.png' % i + + fig.savefig(filename) + print('\tSave to %s' % filename) + print() + + except PySpin.SpinnakerException: + raise + + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + + except PySpin.SpinnakerException: + raise + + cam.EndAcquisition() + print('End Acquisition') + + plt.close() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + #Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Acquire images + result &= acquire_and_display_images(cam, nodemap, nodemap_tldevice) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + +def main(): + """ + Example entry point; notice the volume of data that the logging event handler + prints out on debug despite the fact that very little really happens in this + example. Because of this, it may be better to have the logger set to lower + level in order to provide a more concise, focused log. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) + diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageEvents.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageEvents.py new file mode 100644 index 0000000..ac85f18 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageEvents.py @@ -0,0 +1,452 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# ImageEvents.py shows how to acquire images using the image event handler. +# It relies on information provided in the Enumeration, Acquisition, +# and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the NodeMapCallback +# example, as nodemap callbacks follow the same general procedure as +# events, but with a few less steps. +# +# This example creates a user-defined class, ImageEventHandler, that inherits +# from the Spinnaker class, ImageEventHandler. ImageEventHandler allows the user to +# define any properties, parameters, and the event handler itself while ImageEvent +# allows the child class to appropriately interface with Spinnaker. + +import os +import sys +import PySpin +from time import sleep + +SLEEP_DURATION = 200 # amount of time for main thread to sleep for (in milliseconds) until _NUM_IMAGES have been saved + + +class ImageEventHandler(PySpin.ImageEventHandler): + """ + This class defines the properties, parameters, and the event handler itself. Take a + moment to notice what parts of the class are mandatory, and what have been + added for demonstration purposes. First, any class used to define image event handlers + must inherit from ImageEventHandler. Second, the method signature of OnImageEvent() + must also be consistent. Everything else - including the constructor, + destructor, properties, body of OnImageEvent(), and other functions - + is particular to the example. + """ + _NUM_IMAGES = 10 + + def __init__(self, cam): + """ + Constructor. Retrieves serial number of given camera and sets image counter to 0. + + :param cam: Camera instance, used to get serial number for unique image filenames. + :type cam: CameraPtr + :rtype: None + """ + super(ImageEventHandler, self).__init__() + + nodemap = cam.GetTLDeviceNodeMap() + + # Retrieve device serial number + node_device_serial_number = PySpin.CStringPtr(nodemap.GetNode('DeviceSerialNumber')) + + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + self._device_serial_number = node_device_serial_number.GetValue() + + # Initialize image counter to 0 + self._image_count = 0 + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + def OnImageEvent(self, image): + """ + This method defines an image event. In it, the image that triggered the + event is converted and saved before incrementing the count. Please see + Acquisition example for more in-depth comments on the acquisition + of images. + + :param image: Image from event. + :type image: ImagePtr + :rtype: None + """ + # Save max of _NUM_IMAGES Images + if self._image_count < self._NUM_IMAGES: + print('Image event occurred...') + + # Check if image is incomplete + if image.IsIncomplete(): + print('Image incomplete with image status %i...' % image.GetImageStatus()) + + else: + # Print image info + print('Grabbed image %i, width = %i, height = %i' % (self._image_count, + image.GetWidth(), + image.GetHeight())) + + # Convert to mono8 + image_converted = image.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create unique filename and save image + if self._device_serial_number: + filename = 'ImageEvents-%s-%i.jpg' % (self._device_serial_number, self._image_count) + + else: # if serial number is empty + filename = 'ImageEvents-%i.jpg' % self._image_count + + image_converted.Save(filename) + + print('Image saved at %s\n' % filename) + + # Increment image counter + self._image_count += 1 + + def get_image_count(self): + """ + Getter for image count. + + :return: Number of images saved. + :rtype: int + """ + return self._image_count + + def get_max_images(self): + """ + Getter for maximum images. + + :return: Total number of images to save. + :rtype: int + """ + return self._NUM_IMAGES + + +def configure_image_events(cam): + """ + This function configures the example to execute image events by preparing and + registering an image event. + + :param cam: Camera instance to configure image event. + :return: tuple(result, image_event_handler) + WHERE + result is True if successful, False otherwise + image_event_handler is the event handler + :rtype: (bool, ImageEventHandler) + """ + try: + result = True + + # Create image event handler + # + # *** NOTES *** + # The class has been constructed to accept a camera pointer in order + # to allow the saving of images with the device serial number. + image_event_handler = ImageEventHandler(cam) + + # Register image event handler + # + # *** NOTES *** + # Image events are registered to cameras. If there are multiple + # cameras, each camera must have the image events registered to it + # separately. Also, multiple image events may be registered to a + # single camera. + # + # *** LATER *** + # Image event handlers must be unregistered manually. This must be done prior + # to releasing the system and while the image events are still in + # scope. + cam.RegisterEventHandler(image_event_handler) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result, image_event_handler + + +def wait_for_images(image_event_handler): + """ + This function waits for the appropriate amount of images. Notice that + whereas most examples actively retrieve images, the acquisition of images is + handled passively in this example. + + :param image_event_handler: Image event handler. + :type image_event_handler: ImageEventHandler + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Wait for images + # + # *** NOTES *** + # In order to passively capture images using image event handlers and + # automatic polling, the main thread sleeps in increments of SLEEP_DURATION ms + # until _MAX_IMAGES images have been acquired and saved. + while image_event_handler.get_image_count() < image_event_handler.get_max_images(): + print('\t//\n\t// Sleeping for %i ms. Grabbing images...' % SLEEP_DURATION) + sleep(SLEEP_DURATION / 1000.0) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def reset_image_events(cam, image_event_handler): + """ + This functions resets the example by unregistering the image event handler. + + :param cam: Camera instance. + :param image_event_handler: Image event handler for cam. + :type cam: CameraPtr + :type image_event_handler: ImageEventHandler + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Unregister image event handler + # + # *** NOTES *** + # It is important to unregister all image events from all cameras they are registered to. + # Unlike SystemEventHandler and InterfaceEventHandler in the EnumerationEvents example, + # there is no need to explicitly delete the ImageEventHandler here as it does not store + # an instance of the camera (it gets deleted in the constructor already). + cam.UnregisterEventHandler(image_event_handler) + + print('Image events unregistered...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap from camera. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print('*** DEVICE INFORMATION ***') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex.message) + result = False + + return result + + +def acquire_images(cam, nodemap, image_event_handler): + """ + This function passively waits for images by calling wait_for_images(). Notice that + this function is much shorter than the acquire_images() function of other examples. + This is because most of the code has been moved to the image event's OnImageEvent() + method. + + :param cam: Camera instance to grab images from. + :param nodemap: Device nodemap. + :param image_event_handler: Image event handler. + :type cam: CameraPtr + :type nodemap: INodeMap + :type image_event_handler: ImageEventHandler + :return: True if successful, False otherwise. + :rtype: bool + """ + print('*** IMAGE ACQUISITION ***\n') + try: + result = True + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (enum retrieval). Aborting...') + return False + + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable(node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...') + return False + + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Begin acquiring images + cam.BeginAcquisition() + + print('Acquiring images...') + + # Retrieve images using image event handler + wait_for_images(image_event_handler) + + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure image events + err, image_event_handler = configure_image_events(cam) + if not err: + return err + + # Acquire images using the image event handler + result &= acquire_images(cam, nodemap, image_event_handler) + + # Reset image event handlers + result &= reset_image_events(cam, image_event_handler) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for additional + comments on the steps in this function. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cams = cam_list.GetSize() + + print('Number of cameras detected: %i' % num_cams) + + # Finish if there are no cameras + if num_cams == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + input('Done! Press Enter to exit...') + + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageFormatControl.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageFormatControl.py new file mode 100644 index 0000000..e8b19f2 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageFormatControl.py @@ -0,0 +1,501 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# ImageFormatControl.py shows how to apply custom image settings to +# the camera. It relies on information provided in the Enumeration, +# Acquisition, and NodeMapInfo examples. +# +# This example demonstrates setting minimums to offsets, X and Y, and maximums +# to width and height. It also shows the setting of a new pixel format, which +# is an enumeration type node. +# +# Following this, we suggest familiarizing yourself with the Exposure example +# if you haven't already. Exposure is another example on camera customization +# that is shorter and simpler than many of the others. Once comfortable with +# Exposure and ImageFormatControl, we suggest checking out any of the longer, +# more complicated examples related to camera configuration: ChunkData, +# LookupTable, Sequencer, or Trigger. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def configure_custom_image_settings(nodemap): + """ + Configures a number of settings on the camera including offsets X and Y, width, + height, and pixel format. These settings must be applied before BeginAcquisition() + is called; otherwise, they will be read only. Also, it is important to note that + settings are applied immediately. This means if you plan to reduce the width and + move the x offset accordingly, you need to apply such changes in the appropriate order. + + :param nodemap: GenICam nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print('\n*** CONFIGURING CUSTOM IMAGE SETTINGS *** \n') + + try: + result = True + + # Apply mono 8 pixel format + # + # *** NOTES *** + # Enumeration nodes are slightly more complicated to set than other + # nodes. This is because setting an enumeration node requires working + # with two nodes instead of the usual one. + # + # As such, there are a number of steps to setting an enumeration node: + # retrieve the enumeration node from the nodemap, retrieve the desired + # entry node from the enumeration node, retrieve the integer value from + # the entry node, and set the new value of the enumeration node with + # the integer value from the entry node. + # + # Retrieve the enumeration node from the nodemap + node_pixel_format = PySpin.CEnumerationPtr(nodemap.GetNode('PixelFormat')) + if PySpin.IsAvailable(node_pixel_format) and PySpin.IsWritable(node_pixel_format): + + # Retrieve the desired entry node from the enumeration node + node_pixel_format_mono8 = PySpin.CEnumEntryPtr(node_pixel_format.GetEntryByName('Mono8')) + if PySpin.IsAvailable(node_pixel_format_mono8) and PySpin.IsReadable(node_pixel_format_mono8): + + # Retrieve the integer value from the entry node + pixel_format_mono8 = node_pixel_format_mono8.GetValue() + + # Set integer as new value for enumeration node + node_pixel_format.SetIntValue(pixel_format_mono8) + + print('Pixel format set to %s...' % node_pixel_format.GetCurrentEntry().GetSymbolic()) + + else: + print('Pixel format mono 8 not available...') + + else: + print('Pixel format not available...') + + # Apply minimum to offset X + # + # *** NOTES *** + # Numeric nodes have both a minimum and maximum. A minimum is retrieved + # with the method GetMin(). Sometimes it can be important to check + # minimums to ensure that your desired value is within range. + node_offset_x = PySpin.CIntegerPtr(nodemap.GetNode('OffsetX')) + if PySpin.IsAvailable(node_offset_x) and PySpin.IsWritable(node_offset_x): + + node_offset_x.SetValue(node_offset_x.GetMin()) + print('Offset X set to %i...' % node_offset_x.GetMin()) + + else: + print('Offset X not available...') + + # Apply minimum to offset Y + # + # *** NOTES *** + # It is often desirable to check the increment as well. The increment + # is a number of which a desired value must be a multiple of. Certain + # nodes, such as those corresponding to offsets X and Y, have an + # increment of 1, which basically means that any value within range + # is appropriate. The increment is retrieved with the method GetInc(). + node_offset_y = PySpin.CIntegerPtr(nodemap.GetNode('OffsetY')) + if PySpin.IsAvailable(node_offset_y) and PySpin.IsWritable(node_offset_y): + + node_offset_y.SetValue(node_offset_y.GetMin()) + print('Offset Y set to %i...' % node_offset_y.GetMin()) + + else: + print('Offset Y not available...') + + # Set maximum width + # + # *** NOTES *** + # Other nodes, such as those corresponding to image width and height, + # might have an increment other than 1. In these cases, it can be + # important to check that the desired value is a multiple of the + # increment. However, as these values are being set to the maximum, + # there is no reason to check against the increment. + node_width = PySpin.CIntegerPtr(nodemap.GetNode('Width')) + if PySpin.IsAvailable(node_width) and PySpin.IsWritable(node_width): + + width_to_set = node_width.GetMax() + node_width.SetValue(width_to_set) + print('Width set to %i...' % node_width.GetValue()) + + else: + print('Width not available...') + + # Set maximum height + # + # *** NOTES *** + # A maximum is retrieved with the method GetMax(). A node's minimum and + # maximum should always be a multiple of its increment. + node_height = PySpin.CIntegerPtr(nodemap.GetNode('Height')) + if PySpin.IsAvailable(node_height) and PySpin.IsWritable(node_height): + + height_to_set = node_height.GetMax() + node_height.SetValue(height_to_set) + print('Height set to %i...' % node_height.GetValue()) + + else: + print('Height not available...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print('*** DEVICE INFORMATION ***\n') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** IMAGE ACQUISITION ***\n') + try: + result = True + + # Set acquisition mode to continuous + # + # *** NOTES *** + # Because the example acquires and saves 10 images, setting acquisition + # mode to continuous lets the example finish. If set to single frame + # or multiframe (at a lower number of images), the example would just + # hang. This would happen because the example has been written to + # acquire 10 images while the camera would have been programmed to + # retrieve less than that. + # + # Setting the value of an enumeration node is slightly more complicated + # than other node types. Two nodes must be retrieved: first, the + # enumeration node is retrieved from the nodemap; and second, the entry + # node is retrieved from the enumeration node. The integer value of the + # entry node is then set as the new value of the enumeration node. + # + # Notice that both the enumeration and the entry nodes are checked for + # availability and readability/writability. Enumeration nodes are + # generally readable and writable whereas their entry nodes are only + # ever readable. + # + # Retrieve enumeration node from nodemap + + # In order to access the node entries, they have to be casted to a pointer type (CEnumerationPtr here) + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (enum retrieval). Aborting...') + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...') + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Begin acquiring images + # + # *** NOTES *** + # What happens when the camera begins acquiring images depends on the + # acquisition mode. Single frame captures only a single image, multi + # frame catures a set number of images, and continuous captures a + # continuous stream of images. Because the example calls for the + # retrieval of 10 images, continuous mode has been set. + # + # *** LATER *** + # Image acquisition must be ended when no more images are needed. + cam.BeginAcquisition() + + print('Acquiring images...') + + # Retrieve device serial number for filename + # + # *** NOTES *** + # The device serial number is retrieved in order to keep cameras from + # overwriting one another. Grabbing image IDs could also accomplish + # this. + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Device serial number retrieved as %s...' % device_serial_number) + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve next received image + # + # *** NOTES *** + # Capturing an image houses images on the camera buffer. Trying + # to capture an image that does not exist will hang the camera. + # + # *** LATER *** + # Once an image from the buffer is saved and/or no longer + # needed, the image must be released in order to keep the + # buffer from filling up. + image_result = cam.GetNextImage(1000) + + # Ensure image completion + # + # *** NOTES *** + # Images can easily be checked for completion. This should be + # done whenever a complete image is expected or required. + # Further, check image status for a little more insight into + # why an image is incomplete. + if image_result.IsIncomplete(): + print('Image incomplete with image status %d ...' % image_result.GetImageStatus()) + + else: + + # Print image information; height and width recorded in pixels + # + # *** NOTES *** + # Images have quite a bit of available metadata including + # things such as CRC, image status, and offset values, to + # name a few. + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Grabbed Image %d, width = %d, height = %d' % (i, width, height)) + + # Convert image to mono 8 + # + # *** NOTES *** + # Images can be converted between pixel formats by using + # the appropriate enumeration value. Unlike the original + # image, the converted one does not need to be released as + # it does not affect the camera buffer. + # + # When converting images, color processing algorithm is an + # optional parameter. + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'ImageFormatControl-%s-%d.jpg' % (device_serial_number, i) + else: # if serial number is empty + filename = 'ImageFormatControl-%d.jpg' % i + + # Save image + # + # *** NOTES *** + # The standard practice of the examples is to use device + # serial numbers to keep images of one device from + # overwriting those of another. + image_converted.Save(filename) + print('Image saved at %s' % filename) + + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + print('') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + # End acquisition + # + # *** NOTES *** + # Ending acquisition appropriately helps ensure that devices clean up + # properly and do not need to be power-cycled to maintain integrity. + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure custom image settings + if not configure_custom_image_settings(nodemap): + return False + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageFormatControl_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageFormatControl_QuickSpin.py new file mode 100644 index 0000000..8fba164 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/ImageFormatControl_QuickSpin.py @@ -0,0 +1,358 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# ImageFormatControl_QuickSpin.py shows how to apply custom image +# settings to the camera using the QuickSpin API. QuickSpin is a subset of +# the Spinnaker library that allows for simpler node access and control. +# +# This example demonstrates customizing offsets X and Y, width and height, +# and the pixel format. Ensuring custom values fall within an acceptable +# range is also touched on. Retrieving and setting node values using +# QuickSpin is the only portion of the example that differs from +# ImageFormatControl. +# +# A much wider range of topics is covered in the full Spinnaker examples than +# in the QuickSpin ones. There are only enough QuickSpin examples to +# demonstrate node access and to get started with the API; please see full +# Spinnaker examples for further or specific knowledge on a topic. + +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def configure_custom_image_settings(cam): + """ + Configures a number of settings on the camera including offsets X and Y, + width, height, and pixel format. These settings must be applied before + BeginAcquisition() is called; otherwise, those nodes would be read only. + Also, it is important to note that settings are applied immediately. + This means if you plan to reduce the width and move the x offset accordingly, + you need to apply such changes in the appropriate order. + + :param cam: Camera to configure settings on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + print('\n*** CONFIGURING CUSTOM IMAGE SETTINGS ***\n') + + try: + result = True + + # Apply mono 8 pixel format + # + # *** NOTES *** + # In QuickSpin, enumeration nodes are as easy to set as other node + # types. This is because enum values representing each entry node + # are added to the API. + if cam.PixelFormat.GetAccessMode() == PySpin.RW: + cam.PixelFormat.SetValue(PySpin.PixelFormat_Mono8) + print('Pixel format set to %s...' % cam.PixelFormat.GetCurrentEntry().GetSymbolic()) + + else: + print('Pixel format not available...') + result = False + + # Apply minimum to offset X + # + # *** NOTES *** + # Numeric nodes have both a minimum and maximum. A minimum is retrieved + # with the method GetMin(). Sometimes it can be important to check + # minimums to ensure that your desired value is within range. + if cam.OffsetX.GetAccessMode() == PySpin.RW: + cam.OffsetX.SetValue(cam.OffsetX.GetMin()) + print('Offset X set to %d...' % cam.OffsetX.GetValue()) + + else: + print('Offset X not available...') + result = False + + # Apply minimum to offset Y + # + # *** NOTES *** + # It is often desirable to check the increment as well. The increment + # is a number of which a desired value must be a multiple. Certain + # nodes, such as those corresponding to offsets X and Y, have an + # increment of 1, which basically means that any value within range + # is appropriate. The increment is retrieved with the method GetInc(). + if cam.OffsetY.GetAccessMode() == PySpin.RW: + cam.OffsetY.SetValue(cam.OffsetY.GetMin()) + print('Offset Y set to %d...' % cam.OffsetY.GetValue()) + + else: + print('Offset Y not available...') + result = False + + # Set maximum width + # + # *** NOTES *** + # Other nodes, such as those corresponding to image width and height, + # might have an increment other than 1. In these cases, it can be + # important to check that the desired value is a multiple of the + # increment. + # + # This is often the case for width and height nodes. However, because + # these nodes are being set to their maximums, there is no real reason + # to check against the increment. + if cam.Width.GetAccessMode() == PySpin.RW and cam.Width.GetInc() != 0 and cam.Width.GetMax != 0: + cam.Width.SetValue(cam.Width.GetMax()) + print('Width set to %i...' % cam.Width.GetValue()) + + else: + print('Width not available...') + result = False + + # Set maximum height + # + # *** NOTES *** + # A maximum is retrieved with the method GetMax(). A node's minimum and + # maximum should always be a multiple of its increment. + if cam.Height.GetAccessMode() == PySpin.RW and cam.Height.GetInc() != 0 and cam.Height.GetMax != 0: + cam.Height.SetValue(cam.Height.GetMax()) + print('Height set to %i...' % cam.Height.GetValue()) + + else: + print('Height not available...') + result = False + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_device_info(cam): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param cam: Camera to get device information from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('\n*** DEVICE INFORMATION ***\n') + + try: + result = True + nodemap = cam.GetTLDeviceNodeMap() + + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex.message) + return False + + return result + + +def acquire_images(cam): + """ + This function acquires and saves 10 images from a device; please see + Acquisition example for more in-depth comments on the acquisition of images. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + print('\n*** IMAGE ACQUISITION ***\n') + + try: + result = True + + # Set acquisition mode to continuous + if cam.AcquisitionMode.GetAccessMode() != PySpin.RW: + print('Unable to set acquisition mode to continuous. Aborting...') + return False + + cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous) + print('Acquisition mode set to continuous...') + + # Begin acquiring images + cam.BeginAcquisition() + + print('Acquiring images...') + + # Get device serial number for filename + device_serial_number = '' + if cam.TLDevice.DeviceSerialNumber is not None and cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + device_serial_number = cam.TLDevice.DeviceSerialNumber.GetValue() + + print('Device serial number retrieved as %s...' % device_serial_number) + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + + try: + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print('Image incomplete with image status %d...' % image_result.GetImageStatus()) + + else: + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Grabbed Image %d, width = %d, height = %d' % (i, width, height)) + + # Convert image to Mono8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8) + + # Create a unique filename + if device_serial_number: + filename = 'ImageFormatControlQS-%s-%d.jpg' % (device_serial_number, i) + else: + filename = 'ImageFormatControlQS-%d.jpg' % i + + # Save image + image_converted.Save(filename) + + print('Image saved at %s' % filename) + + # Release image + image_result.Release() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo_QuickSpin example for more + in-depth comments on setting up cameras. + + :param cam: Camera to run example on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + # Initialize camera + cam.Init() + + # Print device info + result = print_device_info(cam) + + # Configure exposure + if not configure_custom_image_settings(cam): + return False + + # Acquire images + result &= acquire_images(cam) + + # Deinitialize camera + cam.DeInit() + + return result + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + +def main(): + """ + Example entry point; please see Enumeration_QuickSpin example for more + in-depth comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Release example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Inference.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Inference.py new file mode 100644 index 0000000..524d8ca --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Inference.py @@ -0,0 +1,1218 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Inference.py shows how to perform the following: +# - Upload custom inference neural networks to the camera (DDR or Flash) +# - Inject sample test image +# - Enable/Configure chunk data +# - Enable/Configure trigger inference ready sync +# - Acquire images +# - Display inference data from acquired image chunk data +# - Disable previously configured camera configurations +# +# Inference is only available for Firefly deep learning cameras. +# See the related content section on the Firefly DL product page for relevant +# documentation. +# https://www.flir.com/products/firefly-dl/ +# It can also be helpful to familiarize yourself with the Acquisition, +# ChunkData and FileAccess_QuickSpin examples. + +import PySpin +import numpy as np +import os +import sys +from enum import Enum + +# Use the following enum and global constant to select whether inference network +# type is Detection or Classification. + +class InferenceNetworkType(Enum): + # This network determines the most likely class given a set of predetermined, + # trained options. Object detection can also provide a location within the + # image (in the form of a "bounding box" surrounding the class), and can + # detect multiple objects. + DETECTION = 1 + # This network determines the best option from a list of predetermined options; + # the camera gives a percentage that determines the likelihood of the currently + # perceived image being one of the classes it has been trained to recognize. + CLASSIFICATION = 2 + +CHOSEN_INFERENCE_NETWORK_TYPE = InferenceNetworkType.DETECTION + +# Use the following enum and global constant to select whether uploaded inference +# network and injected image should be written to camera flash or DDR +class FileUploadPersistence(Enum): + FLASH = 1 # Slower upload but data persists after power cycling the camera + DDR = 2 # Faster upload but data clears after power cycling the camera + +CHOSEN_FILE_UPLOAD_PERSISTENCE = FileUploadPersistence.DDR + +# The example provides two existing custom networks that can be uploaded +# on to the camera to demonstrate classification and detection capabilities. +# "Network_Classification" file is created with Tensorflow using a mobilenet +# neural network for classifying flowers. +# "Network_Detection" file is created with Caffe using mobilenet SSD network +# for people object detection. +# Note: Make sure these files exist on the system and are accessible by the example +NETWORK_FILE_PATH = ("Network_Classification" if ((CHOSEN_INFERENCE_NETWORK_TYPE) \ + == InferenceNetworkType.CLASSIFICATION) \ + else "Network_Detection") + +# The example provides two raw images that can be injected into the camera +# to demonstrate camera inference classification and detection capabilities. Jpeg +# representation of the raw images can be found packaged with the example with +# the names "Injected_Image_Classification_Daisy.jpg" and "Injected_Image_Detection_Aeroplane.jpg". +# Note: Make sure these files exist on the system and are accessible by the example +INJECTED_IMAGE_FILE_PATH = ("Injected_Image_Classification.raw" if ((CHOSEN_INFERENCE_NETWORK_TYPE) \ + == InferenceNetworkType.CLASSIFICATION) \ + else "Injected_Image_Detection.raw") + +# The injected images have different ROI sizes so the camera needs to be +# configured to the appropriate width and height to match the injected image +INJECTED_IMAGE_WIDTH = 640 if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.CLASSIFICATION else 720 +INJECTED_IMAGE_HEIGHT = 400 if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.CLASSIFICATION else 540 + +# Use the following enum to represent the inference bounding box type +class InferenceBoundingBoxType(Enum): + INFERENCE_BOX_TYPE_RECTANGLE = 0 + INFERENCE_BOX_TYPE_CIRCLE = 1 + INFERENCE_BOX_TYPE_ROTATED_RECTANGLE = 2 + +# The sample classification inference network file was trained with the following +# data set labels +# Note: This list should match the list of labels used during the training +# stage of the network file +LABEL_CLASSIFICATION = ["daisy", "dandelion", "roses", "sunflowers", "tulips"] + +# The sample detection inference network file was trained with the following +# data set labels +# Note: This list should match the list of labels used during the training +# stage of the network file +LABEL_DETECTION = ["background", "aeroplane", "bicycle", "bird", "boat", "bottle", "bus", + "car", "cat", "chair", "cow", "diningtable", "dog", "horse", + "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "monitor"] + +# This function prints the device information of the camera from the transport +# layer; please see NodeMapInfo example for more in-depth comments on printing +# device information from the nodemap. +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print('*** DEVICE INFORMATION ***\n') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + +# This function executes a file delete operation on the camera. +def camera_delete_file(nodemap): + ptr_file_size = PySpin.CIntegerPtr(nodemap.GetNode("FileSize")) + if not PySpin.IsReadable(ptr_file_size): + print('Unable to query FileSize. Aborting...') + return False + + if ptr_file_size.GetValue() == 0: + # No file uploaded yet. Skip delete + print('No files found, skipping file deletion.') + return True + + print('Deleting file...') + try: + ptr_file_operation_selector = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationSelector")) + if not PySpin.IsWritable(ptr_file_operation_selector): + print('Unable to configure FileOperationSelector. Aborting...') + return False + + ptr_file_operation_delete = PySpin.CEnumEntryPtr(ptr_file_operation_selector.GetEntryByName("Delete")) + if not PySpin.IsReadable(ptr_file_operation_delete): + print('Unable to configure FileOperationSelector Delete. Aborting...') + return False + + ptr_file_operation_selector.SetIntValue(int(ptr_file_operation_delete.GetNumericValue())) + + ptr_file_operation_execute = PySpin.CCommandPtr(nodemap.GetNode("FileOperationExecute")) + if not PySpin.IsWritable(ptr_file_operation_execute): + print('Unable to configure FileOperationExecute. Aborting...') + return False + + ptr_file_operation_execute.Execute() + + ptr_file_operation_status = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationStatus")) + if not PySpin.IsReadable(ptr_file_operation_status): + print('Unable to query FileOperationStatus. Aborting...') + return False + + ptr_file_operation_status_success = PySpin.CEnumEntryPtr(ptr_file_operation_status.GetEntryByName("Success")) + if not PySpin.IsReadable(ptr_file_operation_status_success): + print('Unable to query FileOperationStatus. Aborting...') + return False + + if ptr_file_operation_status.GetCurrentEntry().GetNumericValue() != ptr_file_operation_status_success.GetNumericValue(): + print('Failed to delete file! File Operation Status : %s' %ptr_file_operation_status.GetCurrentEntry().GetSymbolic()) + return False + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return True + +# This function executes file open/write on the camera, sets the uploaded file persistence +# and attempt to set FileAccessLength to FileAccessBufferNode length to speed up the write. +def camera_open_file(nodemap): + print('Opening file for writing...') + try: + ptr_file_operation_selector = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationSelector")) + if not PySpin.IsWritable(ptr_file_operation_selector): + print('Unable to configure FileOperationSelector. Aborting...') + return False + + ptr_file_operation_open = PySpin.CEnumEntryPtr(ptr_file_operation_selector.GetEntryByName("Open")) + if not PySpin.IsReadable(ptr_file_operation_open): + print('Unable to configure FileOperationSelector Open. Aborting...') + return False + + ptr_file_operation_selector.SetIntValue(int(ptr_file_operation_open.GetNumericValue())) + + ptr_file_open_mode = PySpin.CEnumerationPtr(nodemap.GetNode("FileOpenMode")) + if not PySpin.IsWritable(ptr_file_open_mode): + print('Unable to configure ptr_file_open_mode. Aborting...') + return False + + ptr_file_open_mode_write = PySpin.CEnumEntryPtr(ptr_file_open_mode.GetEntryByName("Write")) + if not PySpin.IsReadable(ptr_file_open_mode_write): + print('Unable to configure FileOperationSelector Write. Aborting...') + return False + + ptr_file_open_mode.SetIntValue(int(ptr_file_open_mode_write.GetNumericValue())) + + ptr_file_operation_execute = PySpin.CCommandPtr(nodemap.GetNode("FileOperationExecute")) + if not PySpin.IsWritable(ptr_file_operation_execute): + print('Unable to configure FileOperationExecute. Aborting...') + return False + + ptr_file_operation_execute.Execute() + + ptr_file_operation_status = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationStatus")) + if not PySpin.IsReadable(ptr_file_operation_status): + print('Unable to query FileOperationStatus. Aborting...') + return False + + ptr_file_operation_status_success = PySpin.CEnumEntryPtr(ptr_file_operation_status.GetEntryByName("Success")) + if not PySpin.IsReadable(ptr_file_operation_status_success): + print('Unable to query FileOperationStatus. Aborting...') + return False + + if ptr_file_operation_status.GetCurrentEntry().GetNumericValue() != ptr_file_operation_status_success.GetNumericValue(): + print('Failed to open file for writing! File Operation Status : %s' %ptr_file_operation_status.GetCurrentEntry().GetSymbolic()) + return False + + # Set file upload persistence settings + ptr_file_write_to_flash = PySpin.CBooleanPtr(nodemap.GetNode("FileWriteToFlash")) + if PySpin.IsWritable(ptr_file_write_to_flash): + if CHOSEN_FILE_UPLOAD_PERSISTENCE == FileUploadPersistence.FLASH: + ptr_file_write_to_flash.SetValue(True) + print('FileWriteToFlash is set to true') + else: + ptr_file_write_to_flash.SetValue(False) + print('FileWriteToFlash is set to false') + + # Attempt to set FileAccessLength to FileAccessBufferNode length to speed up the write + ptr_file_access_length = PySpin.CIntegerPtr(nodemap.GetNode("FileAccessLength")) + if not PySpin.IsReadable(ptr_file_access_length) or not PySpin.IsWritable(ptr_file_access_length): + print('Unable to query/configure FileAccessLength. Aborting...') + return False + + # Attempt to set FileAccessLength to FileAccessBufferNode length to speed up the write + ptr_file_access_buffer = PySpin.CRegisterPtr(nodemap.GetNode("FileAccessBuffer")) + if not PySpin.IsReadable(ptr_file_access_buffer): + print('Unable to query FileAccessBuffer. Aborting...') + return False + + if ptr_file_access_length.GetValue() < ptr_file_access_buffer.GetLength(): + try: + ptr_file_access_length.SetValue(ptr_file_access_buffer.GetLength()) + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + + # Set File Access Offset to zero + ptr_file_access_offset = PySpin.CIntegerPtr(nodemap.GetNode("FileAccessOffset")) + if not PySpin.IsReadable(ptr_file_access_offset) or not PySpin.IsWritable(ptr_file_access_offset): + print('Unable to query/configure ptrFileAccessOffset. Aborting...') + return False + ptr_file_access_offset.SetValue(0) + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return True + +# This function executes a file write operation on the camera. +def camera_write_to_file(nodemap): + try: + ptr_file_operation_selector = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationSelector")) + if not PySpin.IsWritable(ptr_file_operation_selector): + print('Unable to configure FileOperationSelector. Aborting...') + return False + + ptr_file_operation_write = PySpin.CEnumEntryPtr(ptr_file_operation_selector.GetEntryByName("Write")) + if not PySpin.IsReadable(ptr_file_operation_write): + print('Unable to configure FileOperationSelector Write. Aborting...') + return False + + ptr_file_operation_selector.SetIntValue(int(ptr_file_operation_write.GetNumericValue())) + + ptr_file_operation_execute = PySpin.CCommandPtr(nodemap.GetNode("FileOperationExecute")) + if not PySpin.IsWritable(ptr_file_operation_execute): + print('Unable to configure FileOperationExecute. Aborting...') + return False + + ptr_file_operation_execute.Execute() + + ptr_file_operation_status = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationStatus")) + if not PySpin.IsReadable(ptr_file_operation_status): + print('Unable to query FileOperationStatus. Aborting...') + return False + + ptr_file_operation_status_success = PySpin.CEnumEntryPtr(ptr_file_operation_status.GetEntryByName("Success")) + if not PySpin.IsReadable(ptr_file_operation_status_success): + print('Unable to query FileOperationStatus Success. Aborting...') + return False + + if ptr_file_operation_status.GetCurrentEntry().GetNumericValue() != ptr_file_operation_status_success.GetNumericValue(): + print('Failed to write to file! File Operation Status : %s' %ptr_file_operation_status.GetCurrentEntry().GetSymbolic()) + return False + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return True + +# This function executes a file close operation on the camera. +def camera_close_file(nodemap): + print('Closing file...') + try: + ptr_file_operation_selector = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationSelector")) + if not PySpin.IsWritable(ptr_file_operation_selector): + print('Unable to configure FileOperationSelector. Aborting...') + return False + + ptr_file_operation_close = PySpin.CEnumEntryPtr(ptr_file_operation_selector.GetEntryByName("Close")) + if not PySpin.IsReadable(ptr_file_operation_close): + print('Unable to configure FileOperationSelector Close. Aborting...') + return False + + ptr_file_operation_selector.SetIntValue(int(ptr_file_operation_close.GetNumericValue())) + + ptr_file_operation_execute = PySpin.CCommandPtr(nodemap.GetNode("FileOperationExecute")) + if not PySpin.IsWritable(ptr_file_operation_execute): + print('Unable to configure FileOperationExecute. Aborting...') + return False + + ptr_file_operation_execute.Execute() + + ptr_file_operation_status = PySpin.CEnumerationPtr(nodemap.GetNode("FileOperationStatus")) + if not PySpin.IsReadable(ptr_file_operation_status): + print('Unable to query FileOperationStatus. Aborting...') + return False + + ptr_file_operation_status_success = PySpin.CEnumEntryPtr(ptr_file_operation_status.GetEntryByName("Success")) + if not PySpin.IsReadable(ptr_file_operation_status_success): + print('Unable to query FileOperationStatus. Aborting...') + return False + + if ptr_file_operation_status.GetCurrentEntry().GetNumericValue() != ptr_file_operation_status_success.GetNumericValue(): + print('Failed to close the file! File Operation Status : %s' %ptr_file_operation_status.GetCurrentEntry().GetSymbolic()) + return False + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return True + +# This function uploads a file on the system to the camera given the selected +# file selector entry. +def upload_file_to_camera(nodemap, file_selector_entry_name, file_path): + print('\n*** CONFIGURING FILE SELECTOR ***') + + ptr_file_selector = PySpin.CEnumerationPtr(nodemap.GetNode('FileSelector')) + if not PySpin.IsWritable(ptr_file_selector): + print('Unable to configure FileSelector. Aborting...') + return False + + ptr_inference_selector_entry = PySpin.CEnumEntryPtr(ptr_file_selector.GetEntryByName(file_selector_entry_name)) + if not PySpin.IsReadable(ptr_inference_selector_entry): + print('Unable to query FileSelector entry %s ' %file_selector_entry_name + '. Aborting...') + return False + + # Set file selector to entry + print('Setting FileSelector to %s ' %ptr_inference_selector_entry.GetSymbolic() + '...\n') + ptr_file_selector.SetIntValue(int(ptr_inference_selector_entry.GetNumericValue())) + + # Delete file on camera before writing in case camera runs out of space + if camera_delete_file(nodemap) != True: + print('Failed to delete existing file for selector entry %s' %ptr_inference_selector_entry.GetSymbolic() + '. Aborting...') + return False + + # Open file on camera for write + if camera_open_file(nodemap) != True: + if not camera_close_file(nodemap): + print('Problem opening file node. Aborting...') + return False + if not camera_open_file(nodemap): + print('Problem opening file node. Aborting...') + return False + + # check node + ptr_file_access_length = PySpin.CIntegerPtr(nodemap.GetNode('FileAccessLength')) + if not PySpin.IsReadable(ptr_file_access_length) or not PySpin.IsWritable(ptr_file_access_length): + print('Unable to query FileAccessLength. Aborting...') + return False + + ptr_file_access_buffer = PySpin.CRegisterPtr(nodemap.GetNode('FileAccessBuffer')) + if not PySpin.IsReadable(ptr_file_access_buffer) or not PySpin.IsWritable(ptr_file_access_buffer): + print('Unable to query FileAccessBuffer. Aborting...') + return False + + ptr_file_access_offset = PySpin.CIntegerPtr(nodemap.GetNode('FileAccessOffset')) + if not PySpin.IsReadable(ptr_file_access_offset) or not PySpin.IsWritable(ptr_file_access_offset): + print('Unable to query FileAccessOffset. Aborting...') + return False + + ptr_file_access_result = PySpin.CIntegerPtr(nodemap.GetNode('FileOperationResult')) + if not PySpin.IsReadable(ptr_file_access_result): + print('Unable to query FileOperationResult. Aborting...') + return False + + # Load network file from path depending on network type + with open(file_path, 'rb') as fd: + fd.seek(0, os.SEEK_END) + num_bytes = fd.tell() + fd.seek(0,0) + file_bytes = np.fromfile(fd, dtype=np.ubyte, count=num_bytes) + + if len(file_bytes) == 0: + print('Failed to load file path : %s' %file_path + '. Aborting...') + return False + + total_bytes_to_write = len(file_bytes) + intermediate_buffer_size = ptr_file_access_length.GetValue() + write_iterations = (total_bytes_to_write // intermediate_buffer_size) + \ + (0 if ((total_bytes_to_write % intermediate_buffer_size) == 0) else 1) + + if total_bytes_to_write == 0: + print('Empty Image. No data will be written to camera. Aborting...') + return False + + print('Start uploading %s' %file_path + ' to device...') + + print('Total bytes to write: %s' % total_bytes_to_write) + print('FileAccessLength: %s' % intermediate_buffer_size) + print('Write iterations: %s' % write_iterations) + + bytes_left_to_write = total_bytes_to_write + total_bytes_written = 0 + + print('Writing data to device...') + + # Splitting the file into equal chunks (except the last chunk) + sections = [] + for index in range(write_iterations): + num = index * intermediate_buffer_size + if num == 0: + continue + sections.append(num) + split_data = np.array_split(file_bytes, sections) + + # Writing split data to camera + for i in range(write_iterations): + # Set up data to write + tmp_buffer = split_data[i] + + # Write to AccessBufferNode + ptr_file_access_buffer.Set(tmp_buffer) + + if intermediate_buffer_size > bytes_left_to_write: + ptr_file_access_length.SetValue(bytes_left_to_write) + + # Perform Write command + if not camera_write_to_file(nodemap): + print('Writing to stream failed. Aborting...') + return False + + # Verify size of bytes written + size_written = ptr_file_access_result.GetValue() + + # Keep track of total bytes written + total_bytes_written += size_written + + # Keep track of bytes left to write + bytes_left_to_write = total_bytes_to_write - total_bytes_written + + sys.stdout.write('\r') + sys.stdout.write('Progress: %s' % int((i*100 / write_iterations)) + '%' ) + sys.stdout.flush() + + print('\nWriting complete') + + if not camera_close_file(nodemap): + print('Failed to close file!') + + return True + +# This function deletes the file uploaded to the camera given the selected +# file selector entry. +def delete_file_on_camera(nodemap, file_selector_entry_name): + print('\n*** CLEANING UP FILE SELECTOR **') + + ptr_file_selector = PySpin.CEnumerationPtr(nodemap.GetNode("FileSelector")) + if not PySpin.IsWritable(ptr_file_selector): + print('Unable to configure FileSelector. Aborting...') + return False + + ptr_inference_selector_entry = PySpin.CEnumEntryPtr(ptr_file_selector.GetEntryByName(file_selector_entry_name)) + if not PySpin.IsReadable(ptr_inference_selector_entry): + print('Unable to query FileSelector entry ' + file_selector_entry_name + '. Aborting...') + return False + + # Set file Selector entry + print('Setting FileSelector to %s ' %ptr_inference_selector_entry.GetSymbolic() + '...\n') + ptr_file_selector.SetIntValue(int(ptr_inference_selector_entry.GetNumericValue())) + + if camera_delete_file(nodemap) != True: + print('Failed to delete existing file for selector entry') + return False + + return True + +# This function enables or disables the given chunk data type based on +# the specified entry name. +def set_chunk_enable(nodemap, entry_name, enable): + result = True + ptr_chunk_selector = PySpin.CEnumerationPtr(nodemap.GetNode("ChunkSelector")) + + ptr_entry = PySpin.CEnumEntryPtr(ptr_chunk_selector.GetEntryByName(entry_name)) + if not PySpin.IsReadable(ptr_entry): + print('Unable to find ' + entry_name + ' in ChunkSelector...') + return False + + ptr_chunk_selector.SetIntValue(ptr_entry.GetValue()) + + # Enable the boolean, thus enabling the corresponding chunk data + print('Enabling ' + entry_name + '...') + ptr_chunk_enable = PySpin.CBooleanPtr(nodemap.GetNode("ChunkEnable")) + if not PySpin.IsAvailable(ptr_chunk_enable): + print('not available') + return False + + if enable: + if ptr_chunk_enable.GetValue(): + print('enabled') + elif PySpin.IsWritable(ptr_chunk_enable): + ptr_chunk_enable.SetValue(True) + print('enabled') + else: + print('not writable') + result = False + else: + if not ptr_chunk_enable.GetValue(): + print('disabled') + elif PySpin.IsWritable(ptr_chunk_enable): + ptr_chunk_enable.SetValue(False) + print('disabled') + else: + print('not writable') + result = False + + return result + +# This function configures the camera to add inference chunk data to each image. +# When chunk data is turned on, the data is made available in both the nodemap +# and each image. +def configure_chunk_data(nodemap): + result = True + print('\n*** CONFIGURING CHUNK DATA ***') + + try: + # Activate chunk mode + # + # *** NOTES *** + # Once enabled, chunk data will be available at the end of the payload + # of every image captured until it is disabled. Chunk data can also be + # retrieved from the nodemap. + + ptr_chunk_mode_active = PySpin.CBooleanPtr(nodemap.GetNode("ChunkModeActive")) + if not PySpin.IsWritable(ptr_chunk_mode_active): + print('Unable to active chunk mode. Aborting...') + return False + + ptr_chunk_mode_active.SetValue(True) + print('Chunk mode activated...') + + # Enable inference related chunks in chunk data + + # Retrieve the chunk data selector node + ptr_chunk_selector = PySpin.CEnumerationPtr(nodemap.GetNode("ChunkSelector")) + if not PySpin.IsReadable(ptr_chunk_selector): + print('Unable to retrieve chunk selector (enum retrieval). Aborting...') + return False + + # Enable chunk data inference Frame Id + result = set_chunk_enable(nodemap, "InferenceFrameId", True) + if result == False: + print("Unable to enable Inference Frame Id chunk data. Aborting...") + return result + + if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.DETECTION: + # Detection network type + + # Enable chunk data inference bounding box + result = set_chunk_enable(nodemap, "InferenceBoundingBoxResult", True) + if result == False: + print("Unable to enable Inference Bounding Box chunk data. Aborting...") + return result + else: + # Enable chunk data inference result + result = set_chunk_enable(nodemap, "InferenceResult", True) + if result == False: + print("Unable to enable Inference Result chunk data. Aborting...") + return result + + # Enable chunk data inference confidence + result = set_chunk_enable(nodemap, "InferenceConfidence", True) + if result == False: + print("Unable to enable Inference Confidence chunk data. Aborting...") + return result + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return result + +# This function disables each type of chunk data before disabling chunk data mode. +def disable_chunk_data(nodemap): + print('\n*** DISABLING CHUNK DATA ***') + + result = True + try: + ptr_chunk_selector = PySpin.CEnumerationPtr(nodemap.GetNode("ChunkSelector")) + + if not PySpin.IsReadable(ptr_chunk_selector): + print('Unable to retrieve chunk selector. Aborting...') + return False + + result = set_chunk_enable(nodemap, "InferenceFrameId", False) + if result == False: + print('Unable to disable Inference Frame Id chunk data. Aborting...') + return result + + if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.DETECTION: + # Detection network type + + # Disable chunk data inference bounding box + result = set_chunk_enable(nodemap, "InferenceBoundingBoxResult", False) + if result == False: + print('Unable to disable Inference Bounding Box chunk data. Aborting...') + return result + else: + # Classification network type + + # Disable chunk data inference result + result = set_chunk_enable(nodemap, "InferenceResult", False) + if result == False: + print('Unable to disable Inference Result chunk data. Aborting...') + return result + + # Disable chunk data inference confidence + result = set_chunk_enable(nodemap, "InferenceConfidence", False) + if result == False: + print('Unable to disable Inference Confidence chunk data. Aborting...') + return result + + # Deactivate ChunkMode + ptr_chunk_mode_active = PySpin.CBooleanPtr(nodemap.GetNode("ChunkModeActive")) + if not PySpin.IsWritable(ptr_chunk_mode_active): + print('Unable to deactivate chunk mode. Aborting...') + return False + + ptr_chunk_mode_active.SetValue(False) + print('Chunk mode deactivated...') + + # Disable Inference + ptr_inference_enable = PySpin.CBooleanPtr(nodemap.GetNode("InferenceEnable")) + if not PySpin.IsWritable(ptr_inference_enable): + print('Unable to disable inference. Aborting...') + return False + + ptr_inference_enable.SetValue(False) + print('Inference disabled...') + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return result + +# This function displays the inference-related chunk data from the image. +def display_chunk_data(image): + result = True + print('Printing chunk data from image...') + + try: + chunk_data = image.GetChunkData() + + inference_frame_ID = chunk_data.GetInferenceFrameId() + print('\tInference Frame ID: %s' % inference_frame_ID) + + if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.DETECTION: + box_result = chunk_data.GetInferenceBoundingBoxResult() + box_count = box_result.GetBoxCount() + + print('\tInference Bounding Box Result:') + if box_count == 0: + print('\t No bounding box') + + for i in range(box_count): + box = box_result.GetBoxAt(i) + if box.boxType == InferenceBoundingBoxType.INFERENCE_BOX_TYPE_RECTANGLE.value: + print('\t\tBox {0}: Class {1} ({2}): - {3:.4f}% - {4} (X={5} Y={6} W={7} H={8})' + .format(i+1, + box.classId, + LABEL_DETECTION[box.classId] if box.classId < len(LABEL_DETECTION) else "N/A", + box.confidence * 100, + "Rectangle", + box.rect.topLeftXCoord, + box.rect.topLeftYCoord, + box.rect.bottomRightXCoord - box.rect.topLeftXCoord, + box.rect.bottomRightYCoord - box.rect.topLeftYCoord)) + elif box.boxType == InferenceBoundingBoxType.INFERENCE_BOX_TYPE_CIRCLE.value: + print('\t\tBox {0}: Class {1} ({2}): - {3:.4f}% - {4} (X={5} Y={6} R={7})' + .format(i+1, + box.classId, + LABEL_DETECTION[box.classId] if box.classId < len(LABEL_DETECTION) else "N/A", + box.confidence * 100, + "Circle", + box.rect.topLeftXCoord, + box.rect.topLeftYCoord, + box.circle.radius)) + elif box.boxType == InferenceBoundingBoxType.INFERENCE_BOX_TYPE_ROTATED_RECTANGLE.value: + print('\t\tBox {0}: Class {1} ({2}): - {3:.4f}% - {4} (X1={5} Y1={6} X2={7} Y2={8} angle={9})' + .format(i+1, + box.classId, + LABEL_DETECTION[box.classId] if box.classId < len(LABEL_DETECTION) else "N/A", + box.confidence * 100, + "Rotated Rectangle", + box.rotatedRect.topLeftXCoord, + box.rotatedRect.topLeftYCoord, + box.rotatedRect.bottomRightXCoord, + box.rotatedRect.bottomRightYCoord, + box.rotatedRect.rotationAngle)) + else: + print('\t\tBox {0}: Class {1} ({2}): - {3:.4f}% - {4})' + .format(i+1, + box.classId, + LABEL_DETECTION[box.classId] if box.classId < len(LABEL_DETECTION) else "N/A", + box.confidence * 100, + "Unknown bounding box type (not supported)")) + else: + inference_result = chunk_data.GetInferenceResult() + print('\t Inference Result: %s' %inference_result, end = '') + print(' (%s)' % LABEL_CLASSIFICATION[inference_result] if inference_result < len(LABEL_CLASSIFICATION) else "N/A") + + inference_confidence = chunk_data.GetInferenceConfidence() + print('\t Inference Confidence: %.6f' %inference_confidence) + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return result + +# This function disables trigger mode on the camera. +def disable_trigger(nodemap): + print('\n*** IMAGE ACQUISITION ***') + + try: + ptr_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode("TriggerMode")) + if not PySpin.IsWritable(ptr_trigger_mode): + print('Unable to configure TriggerMode. Aborting...') + return False + + ptr_trigger_off = PySpin.CEnumEntryPtr(ptr_trigger_mode.GetEntryByName("Off")) + if not PySpin.IsReadable(ptr_trigger_off): + print('Unable to query TriggerMode Off. Aborting...') + return False + + print('Configure TriggerMode to ' + ptr_trigger_off.GetSymbolic()) + ptr_trigger_mode.SetIntValue(int(ptr_trigger_off.GetNumericValue())) + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return True + +# This function configures camera to run in "inference sync" trigger mode. +def configure_trigger(nodemap): + print('\n*** CONFIGURING TRIGGER ***') + + try: + # Configure TriggerSelector + ptr_trigger_selector = PySpin.CEnumerationPtr(nodemap.GetNode("TriggerSelector")) + if not PySpin.IsWritable(ptr_trigger_selector): + print('Unable to configure TriggerSelector. Aborting...') + return False + + ptr_frame_start = PySpin.CEnumEntryPtr(ptr_trigger_selector.GetEntryByName("FrameStart")) + if not PySpin.IsReadable(ptr_frame_start): + print('Unable to query TriggerSelector FrameStart. Aborting...') + return False + + print('Configure TriggerSelector to ' + ptr_frame_start.GetSymbolic()) + ptr_trigger_selector.SetIntValue(int(ptr_frame_start.GetNumericValue())) + + # Configure TriggerSource + ptr_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode("TriggerSource")) + if not PySpin.IsWritable(ptr_trigger_source): + print('Unable to configure TriggerSource. Aborting...') + return False + + ptr_inference_ready = PySpin.CEnumEntryPtr(ptr_trigger_source.GetEntryByName("InferenceReady")) + if not PySpin.IsReadable(ptr_inference_ready): + print('Unable to query TriggerSource InferenceReady. Aborting...') + return False + + print('Configure TriggerSource to ' + ptr_inference_ready.GetSymbolic()) + ptr_trigger_source.SetIntValue(int(ptr_inference_ready.GetNumericValue())) + + # Configure TriggerMode + ptr_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode("TriggerMode")) + if not PySpin.IsWritable(ptr_trigger_mode): + print('Unable to configure TriggerMode. Aborting...') + return False + + ptr_trigger_on = PySpin.CEnumEntryPtr(ptr_trigger_mode.GetEntryByName("On")) + if not PySpin.IsReadable(ptr_trigger_on): + print('Unable to query TriggerMode On. Aborting...') + return False + + print('Configure TriggerMode to ' + ptr_trigger_on.GetSymbolic()) + ptr_trigger_mode.SetIntValue(int(ptr_trigger_on.GetNumericValue())) + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return True + +# This function enables/disables inference on the camera and configures the inference network type +def configure_inference(nodemap, is_enabled): + if is_enabled: + print('\n*** CONFIGURING INFERENCE (' + ("DETECTION" if ((CHOSEN_INFERENCE_NETWORK_TYPE) \ + == InferenceNetworkType.DETECTION) \ + else 'CLASSIFICATION') + ') ***') + else: + print('\n*** DISABLING INFERENCE ***') + + try: + if is_enabled: + ptr_inference_network_type_selector = PySpin.CEnumerationPtr(nodemap.GetNode("InferenceNetworkTypeSelector")) + if not PySpin.IsWritable(ptr_inference_network_type_selector): + print('Unable to query InferenceNetworkTypeSelector. Aborting...') + return False + + network_type_string = ("Detection" if CHOSEN_INFERENCE_NETWORK_TYPE == InferenceNetworkType.DETECTION + else "Classification") + + # Retrieve entry node from enumeration node + ptr_inference_network_type = PySpin.CEnumEntryPtr(ptr_inference_network_type_selector.GetEntryByName(network_type_string)) + if not PySpin.IsReadable(ptr_inference_network_type): + print('Unable to set inference network type to %s' %network_type_string + ' (entry retrieval). Aborting...') + return False + + inference_network_value = ptr_inference_network_type.GetNumericValue() + ptr_inference_network_type_selector.SetIntValue(int(inference_network_value)) + + print('Inference network type set to' + network_type_string + '...') + + print(('Enabling' if is_enabled else 'Disabling') + ' inference...') + ptr_inference_enable = PySpin.CBooleanPtr(nodemap.GetNode("InferenceEnable")) + if not PySpin.IsWritable(ptr_inference_enable): + print('Unable to enable inference. Aborting...') + return False + + ptr_inference_enable.SetValue(is_enabled) + print('Inference '+'enabled...' if is_enabled else 'disabled...') + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return True + +# This function configures camera test pattern to make use of the injected test image for inference +def configure_test_pattern(nodemap, is_enabled): + if is_enabled: + print('\n*** CONFIGURING TEST PATTERN ***') + else: + print('\n*** DISABLING TEST PATTERN ***') + + try: + # Set TestPatternGeneratorSelector to PipelineStart + ptr_test_pattern_generator_selector = PySpin.CEnumerationPtr(nodemap.GetNode("TestPatternGeneratorSelector")) + if not PySpin.IsWritable(ptr_test_pattern_generator_selector): + print('Unable to query TestPatternGeneratorSelector. Aborting...') + return False + + if is_enabled: + ptr_test_pattern_generator_pipeline_start = PySpin.CEnumEntryPtr(ptr_test_pattern_generator_selector.GetEntryByName("PipelineStart")) + if not PySpin.IsReadable(ptr_test_pattern_generator_pipeline_start): + print('Unable to query TestPatternGeneratorSelector PipelineStart. Aborting...') + return False + + ptr_test_pattern_generator_selector.SetIntValue(int(ptr_test_pattern_generator_pipeline_start.GetNumericValue())) + print('TestPatternGeneratorSelector set to ' + ptr_test_pattern_generator_pipeline_start.GetSymbolic() + '...') + + else: + ptr_test_pattern_generator_sensor = PySpin.CEnumEntryPtr(ptr_test_pattern_generator_selector.GetEntryByName("Sensor")) + if not PySpin.IsReadable(ptr_test_pattern_generator_sensor): + print('Unable to query TestPatternGeneratorSelector Sensor. Aborting...') + return False + + ptr_test_pattern_generator_selector.SetIntValue(int(ptr_test_pattern_generator_sensor.GetNumericValue())) + print('TestPatternGeneratorSelector set to ' + ptr_test_pattern_generator_sensor.GetSymbolic() + '...') + + # Set TestPattern to InjectedImage + ptr_test_pattern = PySpin.CEnumerationPtr(nodemap.GetNode("TestPattern")) + if not PySpin.IsWritable(ptr_test_pattern): + print('Unable to query TestPattern. Aborting...') + return False + + if is_enabled: + ptr_injected_image = PySpin.CEnumEntryPtr(ptr_test_pattern.GetEntryByName("InjectedImage")) + if not PySpin.IsReadable(ptr_injected_image): + print('Unable to query TestPattern InjectedImage. Aborting...') + return False + + ptr_test_pattern.SetIntValue(int(ptr_injected_image.GetNumericValue())) + print('TestPattern set to ' + ptr_injected_image.GetSymbolic() + '...') + else: + ptr_test_pattern_off = PySpin.CEnumEntryPtr(ptr_test_pattern.GetEntryByName("Off")) + if not PySpin.IsReadable(ptr_test_pattern_off): + print('Unable to query TestPattern Off. Aborting...') + return False + + ptr_test_pattern.SetIntValue(int(ptr_test_pattern_off.GetNumericValue())) + print('TestPattern set to ' + ptr_test_pattern_off.GetSymbolic() + '...') + + if is_enabled: + # The inject images have different ROI sizes so camera needs to be configured to the appropriate + # injected width and height + ptr_injected_width = PySpin.CIntegerPtr(nodemap.GetNode("InjectedWidth")) + if not PySpin.IsWritable(ptr_injected_width): + print('Unable to query InjectedWidth. Aborting...') + return False + + ptr_injected_width.SetValue(INJECTED_IMAGE_WIDTH if is_enabled else ptr_injected_width.GetMax()) + + ptr_injected_height = PySpin.CIntegerPtr(nodemap.GetNode("InjectedHeight")) + if not PySpin.IsWritable(ptr_injected_height): + print('Unable to query InjectedHeight. Aborting...') + return False + + ptr_injected_height.SetValue(INJECTED_IMAGE_HEIGHT if is_enabled else ptr_injected_height.GetMax()) + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return True + +# This function acquires and saves 10 images from a device; please see +# Acquisition example for more in-depth comments on acquiring images. +def acquire_images(cam, nodemap, nodemap_tldevice): + result = True + print('\n*** IMAGE ACQUISITION ***') + + try: + # Set acquisition mode to continuous + ptr_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode("AcquisitionMode")) + if not PySpin.IsWritable(ptr_acquisition_mode): + print('Unable to set acquisition mode to continuous (node retrieval). Aborting...') + return False + + ptr_acquisition_mode_continuous = PySpin.CEnumEntryPtr(ptr_acquisition_mode.GetEntryByName("Continuous")) + if not PySpin.IsReadable(ptr_acquisition_mode_continuous): + print("'Unable to set acquisition mode to continuous (entry 'continuous' retrieval). Aborting...") + return False + + acquisition_mode_continuous = ptr_acquisition_mode_continuous.GetValue() + + ptr_acquisition_mode.SetIntValue(int(acquisition_mode_continuous)) + + # Begin acquiring images + cam.BeginAcquisition() + + print('Acquiring images...') + + ptr_string_serial = PySpin.CStringPtr(nodemap.GetNode("DeviceSerialNumber")) + if PySpin.IsReadable(ptr_string_serial): + device_serial_number = ptr_string_serial.GetValue() + print('Device serial number retrieved as %s' %device_serial_number) + print('\n') + + # Retrieve, convert, and save images + num_images = 10 + + for i in range(num_images): + try: + result_image = cam.GetNextImage(1000) + + if result_image.IsIncomplete(): + print('Image incomplete with image status %d ...' % result_image.GetImageStatus()) + else: + print('Grabbed Image %d, width = %d, height = %d' \ + % (i, result_image.GetWidth(), result_image.GetHeight())) + + result = display_chunk_data(result_image) + + # Release image + result_image.Release() + print('') + + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + result = False + + cam.EndAcquisition() + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + return False + + return result + +# This function acts as the body of the example; please see NodeMapInfo example +# for more in-depth comments on setting up cameras. +def run_single_camera(cam): + result = False + err = 0 + + try: + nodemap_tldevice = cam.GetTLDeviceNodeMap() + result = print_device_info(nodemap_tldevice) + + cam.Init() + + nodemap = cam.GetNodeMap() + + # Check to make sure camera supports inference + print('Checking camera inference support...') + ptr_inference_enable = PySpin.CBooleanPtr(nodemap.GetNode('InferenceEnable')) + if not PySpin.IsWritable(ptr_inference_enable): + print('Inference is not supported on this camera. Aborting...') + return False + + # Upload custom inference network onto the camera + # The inference network file is in a movidius specific neural network format. + # Uploading the network to the camera allows for "inference on the edge" where + # camera can apply deep learning on a live stream. Refer to "Getting Started + # with Firefly-DL" for information on how to create your own custom inference + # network files using pre-existing neural network. + err = upload_file_to_camera(nodemap, "InferenceNetwork", NETWORK_FILE_PATH) + if err != True: + return err + + # Upload injected test image + # Instead of applying deep learning on a live stream, the camera can be + # tested with an injected test image. + err = upload_file_to_camera(nodemap, "InjectedImage", INJECTED_IMAGE_FILE_PATH) + if err != True: + return err + + # Configure inference + err = configure_inference(nodemap, True) + if err != True: + return err + + # Configure test pattern to make use of the injected image + err = configure_test_pattern(nodemap, True) + if err != True: + return err + + # Configure trigger + # When enabling inference results via chunk data, the results that accompany a frame + # will likely not be the frame that inference was run on. In order to guarantee that + # the chunk inference results always correspond to the frame that they are sent with, + # the camera needs to be put into the "inference sync" trigger mode. + # Note: Enabling this setting will limit frame rate so that every frame contains new + # inference dataset. To not limit the frame rate, you can enable InferenceFrameID + # chunk data to help determine which frame is associated with a particular + # inference data. + err = configure_trigger(nodemap) + if err != True: + return err + + # Configure chunk data + err = configure_chunk_data(nodemap) + if err != True: + return err + + # Acquire images and display chunk data + result = result | acquire_images(cam, nodemap, nodemap_tldevice) + + # Disable chunk data + err = disable_chunk_data(nodemap) + if err != True: + return err + + # Disable trigger + err = disable_trigger(nodemap) + if err != True: + return err + + # Disable test pattern + err = configure_test_pattern(nodemap, False) + if err != True: + return err + + # Disable inference + err = configure_inference(nodemap, False) + if err != True: + return err + + # Clear injected test image + err = delete_file_on_camera(nodemap, "InjectedImage") + if err != True: + return err + + # Clear uploaded inference network + err = delete_file_on_camera(nodemap, "InferenceNetwork") + if err != True: + return err + + # Deinitialize camera + cam.DeInit() + except PySpin.SpinnakerException as ex: + print('Unexpected exception: %s' % ex) + result = False + + return result + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = False + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %s\n' % num_cameras) + + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + for i, cam in enumerate(cam_list): + print('Running example for camera %d...' % i) + result = result | run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Classification.raw b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Classification.raw new file mode 100644 index 0000000..e79db8f Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Classification.raw differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Classification_Daisy.jpg b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Classification_Daisy.jpg new file mode 100644 index 0000000..128f332 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Classification_Daisy.jpg differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Detection.raw b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Detection.raw new file mode 100644 index 0000000..e1c3100 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Detection.raw differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Detection_Aeroplane.jpg b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Detection_Aeroplane.jpg new file mode 100644 index 0000000..8e3cefc Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Injected_Image_Detection_Aeroplane.jpg differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Logging.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Logging.py new file mode 100644 index 0000000..4501a54 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Logging.py @@ -0,0 +1,130 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Logging.py shows how to create a handler to access logging events. +# It relies on information provided in the Enumeration, Acquisition, and +# NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the NodeMapCallback +# example, as nodemap callbacks follow the same general procedure as +# events, but with a few less steps. +# +# This example creates a user-defined class, LoggingEventHandler, that inherits +# from the Spinnaker class, LoggingEventHandler. The child class allows the user to +# define any properties, parameters, and the event handler itself while LoggingEventHandler +# allows the child class to appropriately interface with the Spinnaker SDK. + +import PySpin + + +# Define callback priority threshold; please see documentation for additional +# information on logging level philosophy. +LOGGING_LEVEL = PySpin.LOG_LEVEL_DEBUG # change to any LOG_LEVEL_* constant + + +class LoggingEventHandler(PySpin.LoggingEventHandler): + """ + Although logging events are just as flexible and extensible as other events, + they are generally only used for logging purposes, which is why a number of + helpful functions that provide logging information have been added. Generally, + if the purpose is not logging, one of the other event types is probably more + appropriate. + """ + + def __init__(self): + super(LoggingEventHandler, self).__init__() + + def OnLogEvent(self, logging_event_data): + """ + This function displays readily available logging information. + + :param logging_event_data: Logging data. + :type logging_event_data: LoggingEventData + :rtype: None + """ + print('--------Log Event Received----------') + print('Category: %s' % logging_event_data.GetCategoryName()) + print('Priority Value: %s' % logging_event_data.GetPriority()) + print('Priority Name: %s' % logging_event_data.GetPriorityName()) + print('Timestamp: %s' % logging_event_data.GetTimestamp()) + print('NDC: %s' % logging_event_data.GetNDC()) + print('Thread: %s' % logging_event_data.GetThreadName()) + print('Message: %s' % logging_event_data.GetLogMessage()) + print('------------------------------------\n') + + +def main(): + """ + Example entry point; notice the volume of data that the logging event handler + prints out on debug despite the fact that very little really happens in this + example. Because of this, it may be better to have the logger set to lower + level in order to provide a more concise, focused log. + + :rtype: None + """ + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Create and register the logging event handler + # + # *** NOTES *** + # Logging event handlers are registered to the system. Take note that a logging + # event handler is very verbose when the logging level is set to debug. + # + # *** LATER *** + # Logging event handlers must be unregistered manually. This must be done prior to + # releasing the system and while the logging event handlers are still in scope. + logging_event_handler = LoggingEventHandler() + system.RegisterLoggingEventHandler(logging_event_handler) + + # Set callback priority level + # + # *** NOTES *** + # Please see documentation for up-to-date information on the logging + # philosophies of the Spinnaker SDK. + system.SetLoggingEventPriorityLevel(LOGGING_LEVEL) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cams = cam_list.GetSize() + + print('Number of cameras detected: %i' % num_cams) + + # Clear camera list before releasing system + cam_list.Clear() + + # Unregister logging event handler + # + # *** NOTES *** + # It is important to unregister all logging event handlers from the system. + system.UnregisterLoggingEventHandler(logging_event_handler) + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + + +if __name__ == '__main__': + main() diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/LookupTable.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/LookupTable.py new file mode 100644 index 0000000..851b6d0 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/LookupTable.py @@ -0,0 +1,440 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= + +# LookupTable.py +# +# LookupTable.py shows how to configure lookup tables on the camera. +# It relies on information provided in the Enumeration, Acquisition, and +# NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the ImageFormatControl +# and Exposure examples. As they are somewhat shorter and simpler, either +# provides a strong introduction to camera customization. +# +# Lookup tables allow for the customization and control of individual pixels. +# This can be a very powerful and deeply useful tool; however, because use +# cases are context dependent, this example only explores lookup table +# configuration. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def print_retrieve_node_failure(node, name): + """" + This function handles the error prints when a node or entry is unavailable or + not readable on the connected camera. + + :param node: Node type. "Node" or "Entry" + :param name: Node name. + :type node: String + :type name: String + :rtype: None + """ + print("Unable to get {} ({} {} retrieval failed.)".format(node, name, node)) + print("The {} may not be available on all camera models...".format(node)) + print("Please try a Blackfly S camera.") + + +def configure_lookup_tables(nodemap): + """ + This function configures lookup tables linearly. This involves selecting the + type of lookup table, finding the appropriate increment calculated from the + maximum value, and enabling lookup tables on the camera. + + :param nodemap: Device nodemap + :type nodemap: INodeMap + :return: returns True if successful, False otherwise + :rtype: bool + """ + result = True + print("***CONFIGURING LOOKUP TABLES***\n") + + # Select lookup table type + # + # ***NOTES *** + # Setting the lookup table selector. It is important to note that this + # does not enable lookup tables. + + try: + lut_selector = PySpin.CEnumerationPtr(nodemap.GetNode("LUTSelector")) + if not PySpin.IsAvailable(lut_selector) or not PySpin.IsWritable(lut_selector): + print_retrieve_node_failure("node", "LUTSelector") + return False + + lut_selector_lut1 = lut_selector.GetEntryByName("LUT1") + if not PySpin.IsAvailable(lut_selector_lut1) or not PySpin.IsReadable(lut_selector_lut1): + print_retrieve_node_failure("entry", "LUTSelector LUT1") + return False + + lut_selector.SetIntValue(lut_selector_lut1.GetValue()) + print("Lookup table selector set to LUT 1...\n") + + # Determine pixel increment and set indexes and values as desired + # + # *** NOTES *** + # To get the pixel increment, the maximum range of the value node must + # first be retrieved. The value node represents an index, so its value + # should be one less than a power of 2 (e.g. 511, 1023, etc.). Add 1 to + # this index to get the maximum range. Divide the maximum range by 512 + # to calculate the pixel increment. + # + # Finally, all values (in the value node) and their corresponding + # indexes (in the index node) need to be set. The goal of this example + # is to set the lookup table linearly. As such, the slope of the values + # should be set according to the increment, but the slope of the + # indexes is inconsequential. + + # Retrieve value node + lut_value = PySpin.CIntegerPtr(nodemap.GetNode("LUTValue")) + if not PySpin.IsAvailable(lut_value) or not PySpin.IsWritable(lut_value): + print_retrieve_node_failure("node", "LUTValue") + return False + + # Retrieve maximum range + max_range = lut_value.GetMax() + 1 + print("\tMaximum Range: {}".format(max_range)) + + # Calculate increment + increment = max_range / 512 + print("\tIncrement: {}".format(increment)) + + # Retrieve index node + lut_index = PySpin.CIntegerPtr(nodemap.GetNode("LUTIndex")) + if not PySpin.IsAvailable(lut_index) or not PySpin.IsWritable(lut_index): + print_retrieve_node_failure("node", "LUTIndex") + return False + + # Set values and indexes + i = 0 + while i < max_range: + lut_index.SetValue(int(i)) + lut_value.SetValue(int(i)) + i += increment + + print("All lookup table values set...\n") + + # Enable lookup tables + # + # *** NOTES *** + # Once lookup tables have been configured, don"t forget to enable them + # with the appropriate node. + # + # *** LATER *** + # Once the images with lookup tables have been collected, turn the + # feature off with the same node. + + lut_enable = PySpin.CBooleanPtr(nodemap.GetNode("LUTEnable")) + if not PySpin.IsAvailable(lut_enable) or not PySpin.IsWritable(lut_enable): + print_retrieve_node_failure("node", "LUTEnable") + return False + + lut_enable.SetValue(True) + print("Lookup tables enabled...\n") + + except PySpin.SpinnakerException as ex: + print("Error: {}".format(ex)) + result = False + + return result + + +def reset_lookup_tables(nodemap): + """ + This function resets the camera by disabling lookup tables. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: returns True if successful, False otherwise + :rtype: bool + """ + result = True + + # Disable lookup tables + # + # *** NOTES *** + # Turn lookup tables off when they are not needed to reduce overhead + + try: + lut_enable = PySpin.CBooleanPtr(nodemap.GetNode("LUTEnable")) + if not PySpin.IsAvailable(lut_enable) or not PySpin.IsWritable(lut_enable): + print("Unable to disable lookup tables. Non-fatal error...\n") + return False + + lut_enable.SetValue(False) + print("Lookup tables disabled...\n") + + except PySpin.SpinnakerException as ex: + print("Error: {}".format(ex)) + result = False + + return result + + +def print_device_info(nodemap): + """ + # This function prints the device information of the camera from the transport + # layer; please see NodeMapInfo example for more in-depth comments on printing + # device information from the nodemap. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: returns True if successful, False otherwise + :rtype: bool + """ + result = True + print("*** DEVICE INFORMATION ***\n") + + try: + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + if PySpin.IsReadable(node_feature): + feature_string = node_feature.ToString() + else: + feature_string = "Node not readable" + + print("{}: {}".format(node_feature.GetName(), feature_string)) + + else: + print("Device control information not available.") + + except PySpin.SpinnakerException as ex: + print("Error: {}".format(ex)) + result = False + + return result + + +def acquire_images(cam, nodemap, nodemap_tl_device): + """ + This function acquires and saves 10 images from a device; please see + Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from + :param nodemap: Device nodemap + :param nodemap_tl_device: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tl_device: INodeMap + :return: returns True if successful, False otherwise + :rtype: bool + """ + result = True + print("*** IMAGE ACQUISITION ***\n") + + # Set acquisition mode to continuous + try: + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode("AcquisitionMode")) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print("Unable to set acquisition mode to continuous (node retrieval). Aborting...\n") + return False + + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName("Continuous") + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or \ + not PySpin.IsReadable(node_acquisition_mode_continuous): + print("Unable to set acquisition mode to continuous (entry 'continuous' retrieval). Aborting...\n") + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + print("Acquisition mode set to continuous...\n") + + # Begin acquiring images + cam.BeginAcquisition() + print("Acquiring images...\n") + + # Retrieve device serial number for filename + device_serial_number = "" + node_device_serial_number = PySpin.CStringPtr(nodemap_tl_device.GetNode("DeviceSerialNumber")) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print("Device serial number retrieved as {}...".format(device_serial_number)) + + print("") + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(1000) + + if image_result.IsIncomplete(): + print("Image incomplete with image status {}...".format(image_result.GetImageStatus())) + + else: + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print("Grabbed image {}, width = {}, height = {}".format(i, width, height)) + + # Convert image to mono 8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = "LookupTable-{}-{}.jpg".format(device_serial_number, i) + else: # if serial number is empty + filename = "LookupTable-{}.jpg".format(i) + + # Save image + image_converted.Save(filename) + print("Image saved at {}".format(filename)) + + # Release image + image_result.Release() + print("") + + except PySpin.SpinnakerException as ex: + print("Error: {}".format(ex)) + result = False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print("Error: {}".format(ex)) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: returns True if successful, False otherwise + :rtype: bool + """ + result = True + + try: + # Retrieve TL device nodemap and print device information + nodemap_tl_device = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tl_device) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure lookup tables + result &= configure_lookup_tables(nodemap) + if not result: + return result + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tl_device) + + # Reset lookup tables + result &= reset_lookup_tables(nodemap) + + # Deinitialize camera + cam.DeInit() + except PySpin.SpinnakerException as ex: + print("Error: {}".format(ex)) + result = False + + return result + + +def main(): + """ + Since this application saves images in the current folder + we must ensure that we have permission to write to this folder. + If we do not have permission, fail right away. + + :return: returns True if successful, False otherwise + :rtype: bool + """ + try: + test_file = open("test.txt", "w+") + except IOError: + print("Unable to write to current directory. Please check permissions.\n") + input("Press Enter to exit...") + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print("Library version: {}.{}.{}.{}\n".format(version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print("Number of cameras detected: {}\n".format(num_cameras)) + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + # Release system instance + system.ReleaseInstance() + print("Not enough cameras!\n") + input("Done! Press Enter to exit...") + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + print("Running example for camera {}...\n".format(i)) + + result &= run_single_camera(cam) + print("Camera {} example complete...\n".format(i)) + + # Release reference to camera + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input("Done! Press Enter to exit...") + return result + + +if __name__ == "__main__": + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Network_Classification b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Network_Classification new file mode 100644 index 0000000..a7a5513 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Network_Classification differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Network_Detection b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Network_Detection new file mode 100644 index 0000000..838b384 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Network_Detection differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/NodeMapCallback.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/NodeMapCallback.py new file mode 100644 index 0000000..0db4cc7 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/NodeMapCallback.py @@ -0,0 +1,424 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# NodeMapCallback.py shows how to use nodemap callbacks. It relies +# on information provided in the Enumeration, Acquisition, and NodeMapInfo +# examples. As callbacks are very similar to events, it may be a good idea to +# explore this example prior to tackling the events examples. +# +# This example focuses on creating, registering, using, and unregistering +# callbacks. A callback requires a callback class with a callback function signature, +# which allows it to be registered to and access a node. Events follow this same pattern. +# +# Once comfortable with NodeMapCallback, we suggest checking out any of the +# events examples: DeviceEvents, EnumerationEvents, ImageEvents, or Logging. + +import PySpin +import sys + + +class HeightNodeCallback(PySpin.NodeCallback): + """ + This is the first of two callback classes. This callback will be registered to the height node. + Node callbacks must inherit from NodeCallback, and must implement CallbackFunction with the same function signature. + + NOTE: Instances of callback classes must not go out of scope until they are deregistered, otherwise segfaults + will occur. + """ + def __init__(self): + super(HeightNodeCallback, self).__init__() + + def CallbackFunction(self, node): + """ + This function gets called when the height node changes and triggers a callback. + + :param node: Height node. + :type node: INode + :rtype: None + """ + node_height = PySpin.CIntegerPtr(node) + print('Height callback message:\n\tLook! Height changed to %f...\n' % node_height.GetValue()) + + +class GainNodeCallback(PySpin.NodeCallback): + """ + This is the second callback class, registered to the gain node. + """ + def __init__(self): + super(GainNodeCallback, self).__init__() + + def CallbackFunction(self, node): + """ + This function gets called when the gain node changes and triggers a callback. + + :param node: Gain node. + :type node: INode + :rtype: None + """ + node_gain = PySpin.CFloatPtr(node) + print('Gain callback message:\n\tLook! Gain changed to %f...\n' % node_gain.GetValue()) + + +def configure_callbacks(nodemap): + """ + This function sets up the example by disabling automatic gain, creating the callbacks, and registering them to + their specific nodes. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :returns: tuple (result, callback_height, callback_gain) + WHERE + result is True if successful, False otherwise + callback_height is the HeightNodeCallback instance registered to the height node + callback_gain is the GainNodeCallback instance registered to the gain node + :rtype: (bool, HeightNodeCallback, GainNodeCallback) + """ + print('\n*** CONFIGURING CALLBACKS ***\n') + try: + result = True + + # Turn off automatic gain + # + # *** NOTES *** + # Automatic gain prevents the manual configuration of gain and needs to + # be turned off for this example. + # + # *** LATER *** + # Automatic exposure is turned off at the end of the example in order + # to restore the camera to its default state. + node_gain_auto = PySpin.CEnumerationPtr(nodemap.GetNode('GainAuto')) + if not PySpin.IsAvailable(node_gain_auto) or not PySpin.IsWritable(node_gain_auto): + print('Unable to disable automatic gain (node retrieval). Aborting...') + return False + + node_gain_auto_off = PySpin.CEnumEntryPtr(node_gain_auto.GetEntryByName('Off')) + if not PySpin.IsAvailable(node_gain_auto_off) or not PySpin.IsReadable(node_gain_auto_off): + print('Unable to disable automatic gain (enum entry retrieval). Aborting...') + return False + + node_gain_auto.SetIntValue(node_gain_auto_off.GetValue()) + print('Automatic gain disabled...') + + # Register callback to height node + # + # *** NOTES *** + # Callbacks need to be registered to nodes, which should be writable + # if the callback is to ever be triggered. Also ensure that the callback + # instance does not go out of scope, as it will get garbage-collected + # and a segfault will result once the callback actually occurs. + # + # *** LATER *** + # Each callback needs to be unregistered individually before releasing + # the system or an exception will be thrown. + node_height = PySpin.CIntegerPtr(nodemap.GetNode('Height')) + if not PySpin.IsAvailable(node_height) or not PySpin.IsWritable(node_height): + print('Unable to retrieve height. Aborting...\n') + return False + + print('Height ready...') + + callback_height = HeightNodeCallback() + PySpin.RegisterNodeCallback(node_height.GetNode(), callback_height) + + print('Height callback registered...') + + # Register callback to gain node + # + # *** NOTES *** + # Depending on the specific goal of the function, it can be important + # to notice the node type that a callback is registered to. Notice in + # the callback functions above that the callback registered to height + # casts its node as an integer whereas the callback registered to gain + # casts as a float. + # + # *** LATER *** + # Each callback needs to be unregistered individually before releasing + # the system or an exception will be thrown. + node_gain = PySpin.CFloatPtr(nodemap.GetNode('Gain')) + if not PySpin.IsAvailable(node_gain) or not PySpin.IsWritable(node_gain): + print('Unable to retrieve gain. Aborting...\n') + return False + + print('Gain ready...') + + callback_gain = GainNodeCallback() + PySpin.RegisterNodeCallback(node_gain.GetNode(), callback_gain) + print('Gain callback registered...\n') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result, callback_height, callback_gain + + +def change_height_and_gain(nodemap): + """ + This function demonstrates the triggering of the nodemap callbacks. First it + changes height, which executes the callback registered to the height node, and + then it changes gain, which executes the callback registered to the gain node. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print('\n***CHANGE HEIGHT & GAIN ***\n') + + try: + result = True + + # Change height to trigger height callback + # + # *** NOTES *** + # Notice that changing the height only triggers the callback function + # registered to the height node. + node_height = PySpin.CIntegerPtr(nodemap.GetNode('Height')) + if not PySpin.IsAvailable(node_height) or not PySpin.IsWritable(node_height) \ + or node_height.GetInc() == 0 or node_height.GetMax() == 0: + + print('Unable to retrieve height. Aborting...') + return False + + height_to_set = node_height.GetMax() + + print('Regular function message:\n\tHeight about to be changed to %i...\n' % height_to_set) + + node_height.SetValue(height_to_set) + + # Change gain to trigger gain callback + # + # *** NOTES *** + # The same is true of changing the gain node; changing a node will + # only ever trigger the callback function (or functions) currently + # registered to it. + node_gain = PySpin.CFloatPtr(nodemap.GetNode('Gain')) + if not PySpin.IsAvailable(node_gain) or not PySpin.IsWritable(node_gain) or node_gain.GetMax() == 0: + print('Unable to retrieve gain...') + return False + + gain_to_set = node_gain.GetMax() / 2.0 + + print('Regular function message:\n\tGain about to be changed to %f...\n' % gain_to_set) + node_gain.SetValue(gain_to_set) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def reset_callbacks(nodemap, callback_height, callback_gain): + """ + This function cleans up the example by deregistering the callbacks and + turning automatic gain back on. + + :param nodemap: Device nodemap. + :param callback_height: Height node callback instance to deregister. + :param callback_gain: Gain node callback instance to deregister. + :type nodemap: INodeMap + :type callback_height: HeightNodeCallback + :type callback_gain: GainNodeCallback + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Deregister callbacks + # + # *** NOTES *** + # It is important to deregister each callback function from each node + # that it is registered to. + PySpin.DeregisterNodeCallback(callback_height) + PySpin.DeregisterNodeCallback(callback_gain) + + print('Callbacks deregistered...') + + # Turn automatic gain back on + # + # *** NOTES *** + # Automatic gain is turned back on in order to restore the camera to + # its default state. + node_gain_auto = PySpin.CEnumerationPtr(nodemap.GetNode('GainAuto')) + if not PySpin.IsAvailable(node_gain_auto) or not PySpin.IsWritable(node_gain_auto): + print('Unable to enable automatic gain (node retrieval). Aborting...') + return False + + node_gain_auto_continuous = PySpin.CEnumEntryPtr(node_gain_auto.GetEntryByName('Continuous')) + if not PySpin.IsAvailable(node_gain_auto_continuous) or not PySpin.IsReadable(node_gain_auto_continuous): + print('Unable to enable automatic gain (enum entry retrieval). Aborting...') + return False + + node_gain_auto.SetIntValue(node_gain_auto_continuous.GetValue()) + print('Automatic gain disabled...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print('*** DEVICE INFORMATION ***\n') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to setup and run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure callbacks + err, callback_height, callback_gain = configure_callbacks(nodemap) + if not err: + return err + + # Change height and gain to trigger callbacks + result &= change_height_and_gain(nodemap) + + # Reset callbacks + result &= reset_callbacks(nodemap, callback_height, callback_gain) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + + cam_list.Clear() + + # Release instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/NodeMapInfo.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/NodeMapInfo.py new file mode 100644 index 0000000..c8224cc --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/NodeMapInfo.py @@ -0,0 +1,576 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# NodeMapInfo.py shows how to retrieve node map information. It relies +# on information provided in the Enumeration example. Also, check out the +# Acquisition and ExceptionHandling examples if you haven't already. +# Acquisition demonstrates image acquisition while ExceptionHandling shows the +# handling of standard and Spinnaker exceptions. +# +# This example explores retrieving information from all major node types on the +# camera. This includes string, integer, float, boolean, command, enumeration, +# category, and value types. Looping through multiple child nodes is also +# covered. A few node types are not covered - base, port, and register - as +# they are not fundamental. The final node type - enumeration entry - is +# explored only in terms of its parent node type - enumeration. +# +# Once comfortable with NodeMapInfo, we suggest checking out ImageFormatControl +# and Exposure. ImageFormatControl explores customizing image settings on a +# camera while Exposure introduces the standard structure of configuring a +# device, acquiring some images, and then returning the device to a default +# state. + +import PySpin +import sys + +# Defines max number of characters that will be printed out for any node information +MAX_CHARS = 35 + + +class ReadType: + """ + Use the following constants to determine whether nodes are read + as Value nodes or their individual types. + """ + VALUE = 0, + INDIVIDUAL = 1 + +CHOSEN_READ = ReadType.INDIVIDUAL + + +def print_with_indent(level, text): + """ + Helper function for printing a string prefix with a specifc number of indents. + :param level: Number of indents to generate + :type level: int + :param text: String to print after indent + :type text: str + """ + ind = '' + for i in range(level): + ind += ' ' + print('%s%s' % (ind, text)) + + +def print_value_node(node, level): + """ + Retrieves and prints the display name and value of all node types as value nodes. + A value node is a general node type that allows for the reading and writing of any node type as a string. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create value node + node_value = PySpin.CValuePtr(node) + + # Retrieve display name + # + # *** NOTES *** + # A node's 'display name' is generally more appropriate for output and + # user interaction whereas its 'name' is what the camera understands. + # Generally, its name is the same as its display name but without + # spaces - for instance, the name of the node that houses a camera's + # serial number is 'DeviceSerialNumber' while its display name is + # 'Device Serial Number'. + display_name = node_value.GetDisplayName() + + # Retrieve value of any node type as string + # + # *** NOTES *** + # Because value nodes return any node type as a string, it can be much + # easier to deal with nodes as value nodes rather than their actual + # individual types. + value = node_value.ToString() + + # Cap length at MAX_CHARS + value = value[:MAX_CHARS] + '...' if len(value) > MAX_CHARS else value + + # Print value + print_with_indent(level, '%s: %s' % (display_name, value)) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_string_node(node, level): + """ + Retrieves and prints the display name and value of a string node. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create string node + node_string = PySpin.CStringPtr(node) + + # Retrieve string node value + # + # *** NOTES *** + # Functions in Spinnaker C++ that use gcstring types + # are substituted with Python strings in PySpin. + # The only exception is shown in the DeviceEvents example, where + # the callback function still uses a wrapped gcstring type. + display_name = node_string.GetDisplayName() + + # Ensure that the value length is not excessive for printing + value = node_string.GetValue() + value = value[:MAX_CHARS] + '...' if len(value) > MAX_CHARS else value + + # Print value; 'level' determines the indentation level of output + print_with_indent(level, '%s: %s' % (display_name, value)) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_integer_node(node, level): + """ + Retrieves and prints the display name and value of an integer node. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create integer node + node_integer = PySpin.CIntegerPtr(node) + + # Get display name + display_name = node_integer.GetDisplayName() + + # Retrieve integer node value + # + # *** NOTES *** + # All node types except base nodes have a ToString() + # method which returns a value as a string. + value = node_integer.GetValue() + + # Print value + print_with_indent(level, '%s: %s' % (display_name, value)) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_float_node(node, level): + """ + Retrieves and prints the display name and value of a float node. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create float node + node_float = PySpin.CFloatPtr(node) + + # Get display name + display_name = node_float.GetDisplayName() + + # Retrieve float value + value = node_float.GetValue() + + # Print value + print_with_indent(level, '%s: %s' % (display_name, value)) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_boolean_node(node, level): + """ + Retrieves and prints the display name and value of a Boolean node. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create Boolean node + node_boolean = PySpin.CBooleanPtr(node) + + # Get display name + display_name = node_boolean.GetDisplayName() + + # Retrieve Boolean value + value = node_boolean.GetValue() + + # Print Boolean value + # NOTE: In Python a Boolean will be printed as "True" or "False". + print_with_indent(level, '%s: %s' % (display_name, value)) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_command_node(node, level): + """ + This function retrieves and prints the display name and tooltip of a command + node, limiting the number of printed characters to a macro-defined maximum. + The tooltip is printed below because command nodes do not have an intelligible + value. + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create command node + node_command = PySpin.CCommandPtr(node) + + # Get display name + display_name = node_command.GetDisplayName() + + # Retrieve tooltip + # + # *** NOTES *** + # All node types have a tooltip available. Tooltips provide useful + # information about nodes. Command nodes do not have a method to + # retrieve values as their is no intelligible value to retrieve. + tooltip = node_command.GetToolTip() + + # Ensure that the value length is not excessive for printing + tooltip = tooltip[:MAX_CHARS] + '...' if len(tooltip) > MAX_CHARS else tooltip + + # Print display name and tooltip + print_with_indent(level, '%s: %s' % (display_name, tooltip)) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_enumeration_node_and_current_entry(node, level): + """ + This function retrieves and prints the display names of an enumeration node + and its current entry (which is actually housed in another node unto itself). + + :param node: Node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create enumeration node + node_enumeration = PySpin.CEnumerationPtr(node) + + # Retrieve current entry as enumeration node + # + # *** NOTES *** + # Enumeration nodes have three methods to differentiate between: first, + # GetIntValue() returns the integer value of the current entry node; + # second, GetCurrentEntry() returns the entry node itself; and third, + # ToString() returns the symbolic of the current entry. + node_enum_entry = PySpin.CEnumEntryPtr(node_enumeration.GetCurrentEntry()) + + # Get display name + display_name = node_enumeration.GetDisplayName() + + # Retrieve current symbolic + # + # *** NOTES *** + # Rather than retrieving the current entry node and then retrieving its + # symbolic, this could have been taken care of in one step by using the + # enumeration node's ToString() method. + entry_symbolic = node_enum_entry.GetSymbolic() + + # Print current entry symbolic + print_with_indent(level, '%s: %s' % (display_name, entry_symbolic)) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_category_node_and_all_features(node, level): + """ + This function retrieves and prints out the display name of a category node + before printing all child nodes. Child nodes that are also category nodes are + printed recursively. + + :param node: Category node to get information from. + :type node: INode + :param level: Depth to indent output. + :type level: int + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Create category node + node_category = PySpin.CCategoryPtr(node) + + # Get and print display name + display_name = node_category.GetDisplayName() + print_with_indent(level, display_name) + + # Retrieve and iterate through all children + # + # *** NOTES *** + # The two nodes that typically have children are category nodes and + # enumeration nodes. Throughout the examples, the children of category nodes + # are referred to as features while the children of enumeration nodes are + # referred to as entries. Keep in mind that enumeration nodes can be cast as + # category nodes, but category nodes cannot be cast as enumerations. + for node_feature in node_category.GetFeatures(): + + # Ensure node is available and readable + if not PySpin.IsAvailable(node_feature) or not PySpin.IsReadable(node_feature): + continue + + # Category nodes must be dealt with separately in order to retrieve subnodes recursively. + if node_feature.GetPrincipalInterfaceType() == PySpin.intfICategory: + result &= print_category_node_and_all_features(node_feature, level + 1) + + # Cast all non-category nodes as value nodes + # + # *** NOTES *** + # If dealing with a variety of node types and their values, it may be + # simpler to cast them as value nodes rather than as their individual types. + # However, with this increased ease-of-use, functionality is sacrificed. + elif CHOSEN_READ == ReadType.VALUE: + result &= print_value_node(node_feature, level + 1) + + # Cast all non-category nodes as actual types + elif CHOSEN_READ == ReadType.INDIVIDUAL: + if node_feature.GetPrincipalInterfaceType() == PySpin.intfIString: + result &= print_string_node(node_feature, level + 1) + elif node_feature.GetPrincipalInterfaceType() == PySpin.intfIInteger: + result &= print_integer_node(node_feature, level + 1) + elif node_feature.GetPrincipalInterfaceType() == PySpin.intfIFloat: + result &= print_float_node(node_feature, level + 1) + elif node_feature.GetPrincipalInterfaceType() == PySpin.intfIBoolean: + result &= print_boolean_node(node_feature, level + 1) + elif node_feature.GetPrincipalInterfaceType() == PySpin.intfICommand: + result &= print_command_node(node_feature, level + 1) + elif node_feature.GetPrincipalInterfaceType() == PySpin.intfIEnumeration: + result &= print_enumeration_node_and_current_entry(node_feature, level + 1) + + print('') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example. First nodes from the TL + device and TL stream nodemaps are retrieved and printed. Following this, + the camera is initialized and then nodes from the GenICam nodemap are + retrieved and printed. + + :param cam: Camera to get nodemaps from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + level = 0 + + # Retrieve TL device nodemap + # + # *** NOTES *** + # The TL device nodemap is available on the transport layer. As such, + # camera initialization is unnecessary. It provides mostly immutable + # information fundamental to the camera such as the serial number, + # vendor, and model. + print('\n*** PRINTING TRANSPORT LAYER DEVICE NODEMAP *** \n') + + nodemap_gentl = cam.GetTLDeviceNodeMap() + + result &= print_category_node_and_all_features(nodemap_gentl.GetNode('Root'), level) + + # Retrieve TL stream nodemap + # + # *** NOTES *** + # The TL stream nodemap is also available on the transport layer. Camera + # initialization is again unnecessary. As you can probably guess, it + # provides information on the camera's streaming performance at any + # given moment. Having this information available on the transport layer + # allows the information to be retrieved without affecting camera performance. + print('*** PRINTING TL STREAM NODEMAP ***\n') + + nodemap_tlstream = cam.GetTLStreamNodeMap() + + result &= print_category_node_and_all_features(nodemap_tlstream.GetNode('Root'), level) + + # Initialize camera + # + # *** NOTES *** + # The camera becomes connected upon initialization. This provides + # access to configurable options and additional information, accessible + # through the GenICam nodemap. + # + # *** LATER *** + # Cameras should be deinitialized when no longer needed. + print('*** PRINTING GENICAM NODEMAP ***\n') + + cam.Init() + + # Retrieve GenICam nodemap + # + # *** NOTES *** + # The GenICam nodemap is the primary gateway to customizing + # and configuring the camera to suit your needs. Configuration options + # such as image height and width, trigger mode enabling and disabling, + # and the sequencer are found on this nodemap. + nodemap_applayer = cam.GetNodeMap() + + result &= print_category_node_and_all_features(nodemap_applayer.GetNode('Root'), level) + + # Deinitialize camera + # + # *** NOTES *** + # Camera deinitialization helps ensure that devices clean up properly + # and do not need to be power-cycled to maintain integrity. + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return True + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + + cam_list.Clear() + + # Release instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/NodeMapInfo_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/NodeMapInfo_QuickSpin.py new file mode 100644 index 0000000..3381bb6 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/NodeMapInfo_QuickSpin.py @@ -0,0 +1,359 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# NodeMapInfo_QuickSpin.py shows how to interact with nodes +# using the QuickSpin API. QuickSpin is a subset of the Spinnaker library +# that allows for simpler node access and control. +# +# This example demonstrates the retrieval of information from both the +# transport layer and the camera. Because the focus of this example is node +# access, which is where QuickSpin and regular Spinnaker differ, this +# example differs from NodeMapInfo quite a bit. +# +# A much wider range of topics is covered in the full Spinnaker examples than +# in the QuickSpin ones. There are only enough QuickSpin examples to +# demonstrate node access and to get started with the API; please see full +# Spinnaker examples for further or specific knowledge on a topic. + +import PySpin +import sys + + +def print_transport_layer_device_info(cam): + """ + Prints device information from the transport layer. + + *** NOTES *** + In QuickSpin, accessing device information on the transport layer is + accomplished via a camera's TLDevice property. The TLDevice property + houses nodes related to general device information such as the three + demonstrated below, device access status, XML and GUI paths and + locations, and GEV information to name a few. The TLDevice property + allows access to nodes that would generally be retrieved through the + TL device nodemap in full Spinnaker. + + Notice that each node is checked for availability and readability + prior to value retrieval. Checking for availability and readability + (or writability when applicable) whenever a node is accessed is + important in terms of error handling. If a node retrieval error + occurs but remains unhandled, an exception is thrown. + + :param cam: Camera to get information from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Print device serial number + if cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + print('Device serial number: %s' % cam.TLDevice.DeviceSerialNumber.ToString()) + + else: + print('Device serial number: unavailable') + result = False + + # Print device vendor name + # + # *** NOTE *** + # To check node readability/writability, you can either + # compare its access mode with RO, RW, etc. or you can use + # the IsReadable/IsWritable functions on the node. + if PySpin.IsReadable(cam.TLDevice.DeviceVendorName): + print('Device vendor name: %s' % cam.TLDevice.DeviceVendorName.ToString()) + else: + print('Device vendor name: unavailable') + result = False + + # Print device display name + if PySpin.IsReadable(cam.TLDevice.DeviceDisplayName): + print('Device display name: %s' % cam.TLDevice.DeviceDisplayName.ToString()) + else: + print('Device display name: unavailable') + result = False + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_transport_layer_stream_info(cam): + """ + Prints stream information from transport layer. + + *** NOTES *** + In QuickSpin, accessing stream information on the transport layer is + accomplished via a camera's TLStream property. The TLStream property + houses nodes related to streaming such as the two demonstrated below, + buffer information, and GEV packet information to name a few. The + TLStream property allows access to nodes that would generally be + retrieved through the TL stream nodemap in full Spinnaker. + + :param cam: Camera to get information from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Print stream ID + if cam.TLStream.StreamID.GetAccessMode() == PySpin.RO: + print('Stream ID: %s' % cam.TLStream.StreamID.ToString()) + else: + print('Stream ID: unavailable') + result = False + + # Print stream type + if PySpin.IsReadable(cam.TLStream.StreamType): + print('Stream type: %s' % cam.TLStream.StreamType.ToString()) + else: + print('Stream type: unavailable') + result = False + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_transport_layer_interface_info(interface): + """ + Prints stream information from the transport layer. + + *** NOTES *** + In QuickSpin, accessing interface information is accomplished via an + interface's TLInterface property. The TLInterface property houses + nodes that hold information about the interface such as the three + demonstrated below, other general interface information, and + GEV addressing information. The TLInterface property allows access to + nodes that would generally be retrieved through the interface nodemap + in full Spinnaker. + + Interface nodes should also always be checked for availability and + readability (or writability when applicable). If a node retrieval + error occurs but remains unhandled, an exception is thrown. + + :param interface: Interface to get information from. + :type interface: InterfacePtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Print interface display name + if interface.TLInterface.InterfaceDisplayName.GetAccessMode() == PySpin.RO: + print('Interface display name: %s' % interface.TLInterface.InterfaceDisplayName.ToString()) + else: + print('Interface display name: unavailable') + result = False + + # Print interface ID + if interface.TLInterface.InterfaceID.GetAccessMode() == PySpin.RO: + print('Interface ID: %s' % interface.TLInterface.InterfaceID.ToString()) + else: + print('Interface ID: unavailable') + result = False + + # Print interface type + if PySpin.IsReadable(interface.TLInterface.InterfaceType.GetAccessMode()): + print('Interface type: %s' % interface.TLInterface.InterfaceType.ToString()) + else: + print('Interface type: unavailable') + result = False + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_genicam_device_info(cam): + """ + Prints device information from the camera. + + *** NOTES *** + Most camera interaction happens through GenICam nodes. The + advantages of these nodes is that there is a lot more of them, they + allow for a much deeper level of interaction with a camera, and no + intermediate property (i.e. TLDevice or TLStream) is required. The + disadvantage is that they require initialization. + + :param cam: Camera to get information from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + + # Print exposure time + if cam.ExposureTime.GetAccessMode() == PySpin.RO or cam.ExposureTime.GetAccessMode() == PySpin.RW: + print('Exposure time: %s' % cam.ExposureTime.ToString()) + else: + print('Exposure time: unavailable') + result = False + + # Print black level + if PySpin.IsReadable(cam.BlackLevel): + print('Black level: %s' % cam.BlackLevel.ToString()) + else: + print('Black level: unavailable') + result = False + + # Print height + if PySpin.IsReadable(cam.Height): + print('Height: %s' % cam.Height.ToString()) + else: + print('Height: unavailable') + result = False + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def main(): + """ + Example entry point; this function prints transport layer information from + each interface and transport and GenICam information from each camera. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + sys = PySpin.System.GetInstance() + + # Get current library version + version = sys.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = sys.GetCameras() + + num_cams = cam_list.GetSize() + + print('Number of cameras detected: %i \n' % num_cams) + + # Finish if there are no cameras + if num_cams == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + sys.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Retrieve list of interfaces from the system + iface_list = sys.GetInterfaces() + + num_ifaces = iface_list.GetSize() + + print('Number of interfaces detected: %i \n' % num_ifaces) + + # Print information on each interface + # + # *** NOTES *** + # All USB 3 Vision and GigE Vision interfaces should enumerate for + # Spinnaker. + print('\n*** PRINTING INTERFACE INFORMATION ***\n') + + for iface in iface_list: + result &= print_transport_layer_interface_info(iface) + + # Release reference to interface + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del iface + + # Print general device information on each camera from transport layer + # + # *** NOTES *** + # Transport layer nodes do not require initialization in order to interact + # with them. + print('\n*** PRINTING TRANSPORT LAYER DEVICE INFORMATION ***\n') + + for cam in cam_list: + result &= print_transport_layer_device_info(cam) + + # Print streaming information on each camera from transport layer + # + # *** NOTES *** + # Again, initialization is not required to print information from the + # transport layer; this is equally true of streaming information. + print('\n*** PRINTING TRANSPORT LAYER STREAMING INFORMATION ***\n') + + for cam in cam_list: + result &= print_transport_layer_stream_info(cam) + + # Print device information on each camera from GenICam nodemap + # + # *** NOTES *** + # GenICam nodes require initialization in order to interact with + # them; as such, this loop initializes the camera, prints some information + # from the GenICam nodemap, and then deinitializes it. If the camera were + # not initialized, node availability would fail. + print('\n*** PRINTING GENICAM INFORMATION ***\n') + + for cam in cam_list: + # Initialize camera + cam.Init() + + # Print info + result &= print_genicam_device_info(cam) + + # Deinitialize camera + cam.DeInit() + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Clear interface list before releasing system + iface_list.Clear() + + # Release system instance + sys.ReleaseInstance() + + input('\nDone! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/SaveToAvi.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/SaveToAvi.py new file mode 100644 index 0000000..1f79203 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/SaveToAvi.py @@ -0,0 +1,378 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# SaveToAvi.py shows how to create an AVI video from a vector of +# images. It relies on information provided in the Enumeration, Acquisition, +# and NodeMapInfo examples. +# +# This example introduces the SpinVideo class, which is used to quickly and +# easily create various types of AVI videos. It demonstrates the creation of +# three types: uncompressed, MJPG, and H264. + +import PySpin +import sys + + +class AviType: + """'Enum' to select AVI video type to be created and saved""" + UNCOMPRESSED = 0 + MJPG = 1 + H264 = 2 + +chosenAviType = AviType.UNCOMPRESSED # change me! +NUM_IMAGES = 10 # number of images to use in AVI file + + +def save_list_to_avi(nodemap, nodemap_tldevice, images): + """ + This function prepares, saves, and cleans up an AVI video from a vector of images. + + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :param images: List of images to save to an AVI video. + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :type images: list of ImagePtr + :return: True if successful, False otherwise. + :rtype: bool + """ + print('*** CREATING VIDEO ***') + + try: + result = True + + # Retrieve device serial number for filename + device_serial_number = '' + node_serial = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + + if PySpin.IsAvailable(node_serial) and PySpin.IsReadable(node_serial): + device_serial_number = node_serial.GetValue() + print('Device serial number retrieved as %s...' % device_serial_number) + + # Get the current frame rate; acquisition frame rate recorded in hertz + # + # *** NOTES *** + # The video frame rate can be set to anything; however, in order to + # have videos play in real-time, the acquisition frame rate can be + # retrieved from the camera. + + node_acquisition_framerate = PySpin.CFloatPtr(nodemap.GetNode('AcquisitionFrameRate')) + + if not PySpin.IsAvailable(node_acquisition_framerate) and not PySpin.IsReadable(node_acquisition_framerate): + print('Unable to retrieve frame rate. Aborting...') + return False + + framerate_to_set = node_acquisition_framerate.GetValue() + + print('Frame rate to be set to %d...' % framerate_to_set) + + # Select option and open AVI filetype with unique filename + # + # *** NOTES *** + # Depending on the filetype, a number of settings need to be set in + # an object called an option. An uncompressed option only needs to + # have the video frame rate set whereas videos with MJPG or H264 + # compressions should have more values set. + # + # Once the desired option object is configured, open the AVI file + # with the option in order to create the image file. + # + # Note that the filename does not need to be appended to the + # name of the file. This is because the AVI recorder object takes care + # of the file extension automatically. + # + # *** LATER *** + # Once all images have been added, it is important to close the file - + # this is similar to many other standard file streams. + + avi_recorder = PySpin.SpinVideo() + + if chosenAviType == AviType.UNCOMPRESSED: + avi_filename = 'SaveToAvi-Uncompressed-%s' % device_serial_number + + option = PySpin.AVIOption() + option.frameRate = framerate_to_set + + elif chosenAviType == AviType.MJPG: + avi_filename = 'SaveToAvi-MJPG-%s' % device_serial_number + + option = PySpin.MJPGOption() + option.frameRate = framerate_to_set + option.quality = 75 + + elif chosenAviType == AviType.H264: + avi_filename = 'SaveToAvi-H264-%s' % device_serial_number + + option = PySpin.H264Option() + option.frameRate = framerate_to_set + option.bitrate = 1000000 + option.height = images[0].GetHeight() + option.width = images[0].GetWidth() + + else: + print('Error: Unknown AviType. Aborting...') + return False + + avi_recorder.Open(avi_filename, option) + + # Construct and save AVI video + # + # *** NOTES *** + # Although the video file has been opened, images must be individually + # appended in order to construct the video. + print('Appending %d images to AVI file: %s.avi...' % (len(images), avi_filename)) + + for i in range(len(images)): + avi_recorder.Append(images[i]) + print('Appended image %d...' % i) + + # Close AVI file + # + # *** NOTES *** + # Once all images have been appended, it is important to close the + # AVI file. Notice that once an AVI file has been closed, no more + # images can be added. + + avi_recorder.Close() + print('Video saved at %s.avi' % avi_filename) + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print('\n*** DEVICE INFORMATION ***\n') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def acquire_images(cam, nodemap): + """ + This function acquires 10 images from a device, stores them in a list, and returns the list. + please see the Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + print('*** IMAGE ACQUISITION ***\n') + try: + result = True + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (enum retrieval). Aborting...') + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable(node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...') + return False + + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Begin acquiring images + cam.BeginAcquisition() + + print('Acquiring images...') + + # Retrieve, convert, and save images + images = list() + + for i in range(NUM_IMAGES): + try: + # Retrieve next received image + image_result = cam.GetNextImage(1000) + + # Ensure image completion + if image_result.IsIncomplete(): + print('Image incomplete with image status %d...' % image_result.GetImageStatus()) + + else: + # Print image information; height and width recorded in pixels + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Grabbed Image %d, width = %d, height = %d' % (i, width, height)) + + # Convert image to mono 8 and append to list + images.append(image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR)) + + # Release image + image_result.Release() + print('') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result, images + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run example on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Acquire list of images + err, images = acquire_images(cam, nodemap) + if err < 0: + return err + + result &= save_list_to_avi(nodemap, nodemap_tldevice, images) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected:', num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Sequencer.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Sequencer.py new file mode 100644 index 0000000..23035c7 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Sequencer.py @@ -0,0 +1,873 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Sequencer.py shows how to use the sequencer to grab images with +# various settings. It relies on information provided in the Enumeration, +# Acquisition, and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the ImageFormatControl +# and Exposure examples as these examples provide a strong introduction to +# camera customization. +# +# The sequencer is another very powerful tool, which can be used to create +# and store multiple states of customized image settings. A very useful +# application of the sequencer is creating high dynamic range images. +# +# This example is probably the most complex and definitely the longest. As +# such, the configuration has been split between three functions. The first +# prepares the camera to set the sequences, the second sets the settings for +# a single state (it is run five times), and the third configures the +# camera to use the sequencer when it acquires images. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +def print_retrieve_node_failure(node, name): + """" + This function handles the error prints when a node or entry is unavailable or + not readable on the connected camera. + + :param node: Node type. "Node' or 'Entry' + :param name: Node name. + :type node: String + :type name: String + :rtype: None + """ + print('Unable to get {} ({} {} retrieval failed.)'.format(node, name, node)) + print('The {} may not be available on all camera models...'.format(node)) + print('Please try a Blackfly S camera.') + + +def configure_sequencer_part_one(nodemap): + """" + This function prepares the sequencer to accept custom configurations by + ensuring sequencer mode is off (this is a requirement to the enabling of + sequencer configuration mode), disabling automatic gain and exposure, and + turning sequencer configuration mode on. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** CONFIGURING SEQUENCER ***\n') + try: + result = True + + # Ensure sequencer is off for configuration + # + # *** NOTES *** + # In order to configure a new sequence, sequencer configuration mode + # needs to be turned on. To do this, sequencer mode must be disabled. + # However, simply disabling sequencer mode might throw an exception if + # the current sequence is an invalid configuration. + # + # Thus, in order to ensure that sequencer mode is disabled, we first + # check whether the current sequence is valid. If it + # isn't, then we know that sequencer mode is off and we can move on; + # if it is, then we can manually disable sequencer mode. + # + # Also note that sequencer configuration mode needs to be off in order + # to manually disable sequencer mode. It should be off by default, so + # the example skips checking this. + # + # Validate sequencer configuration + node_sequencer_configuration_valid = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerConfigurationValid')) + if not PySpin.IsAvailable(node_sequencer_configuration_valid) \ + or not PySpin.IsReadable(node_sequencer_configuration_valid): + print_retrieve_node_failure('node', 'SequencerConfigurationValid') + return False + + sequencer_configuration_valid_yes = node_sequencer_configuration_valid.GetEntryByName('Yes') + if not PySpin.IsAvailable(sequencer_configuration_valid_yes) \ + or not PySpin.IsReadable(sequencer_configuration_valid_yes): + print_retrieve_node_failure('entry', 'SequencerConfigurationValid Yes') + return False + + # If valid, disable sequencer mode; otherwise, do nothing + node_sequencer_mode = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerMode')) + if node_sequencer_configuration_valid.GetCurrentEntry().GetValue() == \ + sequencer_configuration_valid_yes.GetValue(): + if not PySpin.IsAvailable(node_sequencer_mode) or not PySpin.IsWritable(node_sequencer_mode): + print_retrieve_node_failure('node', 'SequencerMode') + return False + + sequencer_mode_off = node_sequencer_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(sequencer_mode_off) or not PySpin.IsReadable(sequencer_mode_off): + print_retrieve_node_failure('entry', 'SequencerMode Off') + return False + + node_sequencer_mode.SetIntValue(sequencer_mode_off.GetValue()) + + print('Sequencer mode disabled...') + + # Turn off automatic exposure + # + # *** NOTES *** + # Automatic exposure prevents the manual configuration of exposure + # times and needs to be turned off for this example. + # + # *** LATER *** + # Automatic exposure is turned back on at the end of the example in + # order to restore the camera to its default state. + node_exposure_auto = PySpin.CEnumerationPtr(nodemap.GetNode('ExposureAuto')) + if not PySpin.IsAvailable(node_exposure_auto) or not PySpin.IsWritable(node_exposure_auto): + print_retrieve_node_failure('node', 'ExposureAuto') + return False + + exposure_auto_off = node_exposure_auto.GetEntryByName('Off') + if not PySpin.IsAvailable(exposure_auto_off) or not PySpin.IsReadable(exposure_auto_off): + print_retrieve_node_failure('entry', 'ExposureAuto Off') + return False + + node_exposure_auto.SetIntValue(exposure_auto_off.GetValue()) + + print('Automatic exposure disabled...') + + # Turn off automatic gain + # + # *** NOTES *** + # Automatic gain prevents the manual configuration of gain and needs + # to be turned off for this example. + # + # *** LATER *** + # Automatic gain is turned back on at the end of the example in + # order to restore the camera to its default state. + node_gain_auto = PySpin.CEnumerationPtr(nodemap.GetNode('GainAuto')) + if not PySpin.IsAvailable(node_gain_auto) or not PySpin.IsWritable(node_gain_auto): + print_retrieve_node_failure('node', 'GainAuto') + return False + + gain_auto_off = node_gain_auto.GetEntryByName('Off') + if not PySpin.IsAvailable(gain_auto_off) or not PySpin.IsReadable(gain_auto_off): + print_retrieve_node_failure('entry', 'GainAuto Off') + return False + + node_gain_auto.SetIntValue(gain_auto_off.GetValue()) + + print('Automatic gain disabled...') + + # Turn configuration mode on + # + # *** NOTES *** + # Once sequencer mode is off, enabling sequencer configuration mode + # allows for the setting of each state. + # + # *** LATER *** + # Before sequencer mode is turned back on, sequencer configuration + # mode must be turned back off. + node_sequencer_configuration_mode = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerConfigurationMode')) + if not PySpin.IsAvailable(node_sequencer_configuration_mode) \ + or not PySpin.IsWritable(node_sequencer_configuration_mode): + print_retrieve_node_failure('node', 'SequencerConfigurationMode') + return False + + sequencer_configuration_mode_on = node_sequencer_configuration_mode.GetEntryByName('On') + if not PySpin.IsAvailable(sequencer_configuration_mode_on)\ + or not PySpin.IsReadable(sequencer_configuration_mode_on): + print_retrieve_node_failure('entry', 'SequencerConfigurationMode On') + return False + + node_sequencer_configuration_mode.SetIntValue(sequencer_configuration_mode_on.GetValue()) + + print('Sequencer configuration mode enabled...\n') + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + result = False + + return result + + +def set_single_state(nodemap, sequence_number, width_to_set, height_to_set, exposure_time_to_set, gain_to_set): + """ + This function sets a single state. It sets the sequence number, applies + custom settings, selects the trigger type and next state number, and saves + the state. The custom values that are applied are all calculated in the + function that calls this one, run_single_camera(). + + :param nodemap: Device nodemap. + :param sequence_number: Sequence number. + :param width_to_set: Width to set for sequencer. + :param height_to_set: Height to set fpr sequencer. + :param exposure_time_to_set: Exposure time to set for sequencer. + :param gain_to_set: Gain to set for sequencer. + :type nodemap: INodeMap + :type sequence_number: int + :type width_to_set: int + :type height_to_set: int + :type exposure_time_to_set: float + :type gain_to_set: float + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Select the current sequence number + # + # *** NOTES *** + # Select the index of the state to be set. + # + # *** LATER *** + # The next state - i.e. the state to be linked to - + # also needs to be set before saving the current state. + node_sequencer_set_selector = PySpin.CIntegerPtr(nodemap.GetNode('SequencerSetSelector')) + if not PySpin.IsAvailable(node_sequencer_set_selector) or not PySpin.IsWritable(node_sequencer_set_selector): + print_retrieve_node_failure('node', 'SequencerSetSelector') + return False + + node_sequencer_set_selector.SetValue(sequence_number) + + print('Setting state {}...'.format(sequence_number)) + + # Set desired settings for the current state + # + # *** NOTES *** + # Width, height, exposure time, and gain are set in this example. If + # the sequencer isn't working properly, it may be important to ensure + # that each feature is enabled on the sequencer. Features are enabled + # by default, so this is not explored in this example. + # + # Changing the height and width for the sequencer is not available + # for all camera models. + # + # Set width; width recorded in pixels + node_width = PySpin.CIntegerPtr(nodemap.GetNode('Width')) + if PySpin.IsAvailable(node_width) and PySpin.IsWritable(node_width): + width_inc = node_width.GetInc() + + if width_to_set % width_inc != 0: + width_to_set = int(width_to_set / width_inc) * width_inc + + node_width.SetValue(width_to_set) + + print('\tWidth set to {}...'.format(node_width.GetValue())) + + else: + print('\tUnable to set width; width for sequencer not available on all camera models...') + + # Set height; height recorded in pixels + node_height = PySpin.CIntegerPtr(nodemap.GetNode('Height')) + if PySpin.IsAvailable(node_height) and PySpin.IsWritable(node_height): + height_inc = node_height.GetInc() + + if height_to_set % height_inc != 0: + height_to_set = int(height_to_set / height_inc) * height_inc + + node_height.SetValue(height_to_set) + + print('\tHeight set to %d...' % node_height.GetValue()) + + else: + print('\tUnable to set height; height for sequencer not available on all camera models...') + + # Set exposure time; exposure time recorded in microseconds + node_exposure_time = PySpin.CFloatPtr(nodemap.GetNode('ExposureTime')) + if not PySpin.IsAvailable(node_exposure_time) or not PySpin.IsWritable(node_exposure_time): + print_retrieve_node_failure('node', 'ExposureTime') + return False + + exposure_time_max = node_exposure_time.GetMax() + + if exposure_time_to_set > exposure_time_max: + exposure_time_to_set = exposure_time_max + + node_exposure_time.SetValue(exposure_time_to_set) + + print('\tExposure set to {0:.0f}...'.format(node_exposure_time.GetValue())) + + # Set gain; gain recorded in decibels + node_gain = PySpin.CFloatPtr(nodemap.GetNode('Gain')) + if not PySpin.IsAvailable(node_gain) or not PySpin.IsWritable(node_gain): + print_retrieve_node_failure('node', 'Gain') + return False + + gain_max = node_gain.GetMax() + + if gain_to_set > gain_max: + gain_to_set = gain_max + + node_gain.SetValue(gain_to_set) + + print('\tGain set to {0:.5f}...'.format(node_gain.GetValue())) + + # Set the trigger type for the current state + # + # *** NOTES *** + # It is a requirement of every state to have its trigger source set. + # The trigger source refers to the moment when the sequencer changes + # from one state to the next. + node_sequencer_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerTriggerSource')) + if not PySpin.IsAvailable(node_sequencer_trigger_source) or not PySpin.IsWritable(node_sequencer_trigger_source): + print_retrieve_node_failure('node', 'SequencerTriggerSource') + return False + + sequencer_trigger_source_frame_start = node_sequencer_trigger_source.GetEntryByName('FrameStart') + if not PySpin.IsAvailable(sequencer_trigger_source_frame_start) or \ + not PySpin.IsReadable(sequencer_trigger_source_frame_start): + print_retrieve_node_failure('entry', 'SequencerTriggerSource FrameStart') + return False + + node_sequencer_trigger_source.SetIntValue(sequencer_trigger_source_frame_start.GetValue()) + + print('\tTrigger source set to start of frame...') + + # Set the next state in the sequence + # + # *** NOTES *** + # When setting the next state in the sequence, ensure it does not + # exceed the maximum and that the states loop appropriately. + final_sequence_index = 4 + + node_sequencer_set_next = PySpin.CIntegerPtr(nodemap.GetNode('SequencerSetNext')) + if not PySpin.IsAvailable(node_sequencer_set_next) or not PySpin.IsWritable(node_sequencer_set_next): + print('Unable to select next state. Aborting...\n') + return False + + if sequence_number == final_sequence_index: + node_sequencer_set_next.SetValue(0) + else: + node_sequencer_set_next.SetValue(sequence_number + 1) + + print('\tNext state set to {}...'.format(node_sequencer_set_next.GetValue())) + + # Save current state + # + # *** NOTES *** + # Once all appropriate settings have been configured, make sure to + # save the state to the sequence. Notice that these settings will be + # lost when the camera is power-cycled. + node_sequencer_set_save = PySpin.CCommandPtr(nodemap.GetNode('SequencerSetSave')) + if not PySpin.IsAvailable(node_sequencer_set_save) or not PySpin.IsWritable(node_sequencer_set_save): + print('Unable to save state. Aborting...\n') + return False + + node_sequencer_set_save.Execute() + + print('Current state saved...\n') + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + result = False + + return result + + +def configure_sequencer_part_two(nodemap): + """" + Now that the states have all been set, this function readies the camera + to use the sequencer during image acquisition. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Turn configuration mode off + # + # *** NOTES *** + # Once all desired states have been set, turn sequencer + # configuration mode off in order to turn sequencer mode on. + node_sequencer_configuration_mode = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerConfigurationMode')) + if not PySpin.IsAvailable(node_sequencer_configuration_mode) \ + or not PySpin.IsWritable(node_sequencer_configuration_mode): + print_retrieve_node_failure('node', 'SequencerConfigurationMode') + return False + + sequencer_configuration_mode_off = node_sequencer_configuration_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(sequencer_configuration_mode_off)\ + or not PySpin.IsReadable(sequencer_configuration_mode_off): + print_retrieve_node_failure('entry', 'SequencerConfigurationMode Off') + return False + + node_sequencer_configuration_mode.SetIntValue(sequencer_configuration_mode_off.GetValue()) + + print('Sequencer configuration mode disabled...') + + # Turn sequencer mode on + # + # *** NOTES *** + # After sequencer mode has been turned on, the camera will begin using the + # saved states in the order that they were set. + # + # *** LATER *** + # Once all images have been captured, disable the sequencer in order + # to restore the camera to its initial state. + node_sequencer_mode = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerMode')) + if not PySpin.IsAvailable(node_sequencer_mode) or not PySpin.IsWritable(node_sequencer_mode): + print_retrieve_node_failure('node', 'SequencerMode') + return False + + sequencer_mode_on = node_sequencer_mode.GetEntryByName('On') + if not PySpin.IsAvailable(sequencer_mode_on) or not PySpin.IsReadable(sequencer_mode_on): + print_retrieve_node_failure('entry', 'SequencerMode On') + return False + + node_sequencer_mode.SetIntValue(sequencer_mode_on.GetValue()) + + print('Sequencer mode enabled...') + + # Validate sequencer settings + # + # *** NOTES *** + # Once all states have been set, it is a good idea to + # validate them. Although this node cannot ensure that the states + # have been set up correctly, it does ensure that the states have + # been set up in such a way that the camera can function. + node_sequencer_configuration_valid = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerConfigurationValid')) + if not PySpin.IsAvailable(node_sequencer_configuration_valid) \ + or not PySpin.IsReadable(node_sequencer_configuration_valid): + print_retrieve_node_failure('node', 'SequencerConfigurationValid') + return False + + sequencer_configuration_valid_yes = node_sequencer_configuration_valid.GetEntryByName('Yes') + if not PySpin.IsAvailable(sequencer_configuration_valid_yes) \ + or not PySpin.IsReadable(sequencer_configuration_valid_yes): + print_retrieve_node_failure('entry', 'SequencerConfigurationValid Yes') + return False + + if node_sequencer_configuration_valid.GetCurrentEntry().GetValue() != \ + sequencer_configuration_valid_yes.GetValue(): + print('Sequencer configuration not valid. Aborting...\n') + return False + + print('Sequencer configuration valid...\n') + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + result = False + + return result + + +def reset_sequencer(nodemap): + """" + This function restores the camera to its default state by turning sequencer mode + off and re-enabling automatic exposure and gain. + + :param nodemap: Device nodemap. + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Turn sequencer mode back off + # + # *** NOTES *** + # The sequencer is turned off in order to return the camera to its default state. + node_sequencer_mode = PySpin.CEnumerationPtr(nodemap.GetNode('SequencerMode')) + if not PySpin.IsAvailable(node_sequencer_mode) or not PySpin.IsWritable(node_sequencer_mode): + print_retrieve_node_failure('node', 'SequencerMode') + return False + + sequencer_mode_off = node_sequencer_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(sequencer_mode_off) or not PySpin.IsReadable(sequencer_mode_off): + print_retrieve_node_failure('entry', 'SequencerMode Off') + return False + + node_sequencer_mode.SetIntValue(sequencer_mode_off.GetValue()) + + print('Turning off sequencer mode...') + + # Turn automatic exposure back on + # + # *** NOTES *** + # Automatic exposure is turned on in order to return the camera to its default state. + node_exposure_auto = PySpin.CEnumerationPtr(nodemap.GetNode('ExposureAuto')) + if PySpin.IsAvailable(node_exposure_auto) and PySpin.IsWritable(node_exposure_auto): + exposure_auto_continuous = node_exposure_auto.GetEntryByName('Continuous') + if PySpin.IsAvailable(exposure_auto_continuous) and PySpin.IsReadable(exposure_auto_continuous): + node_exposure_auto.SetIntValue(exposure_auto_continuous.GetValue()) + print('Turning automatic exposure back on...') + + # Turn automatic gain back on + # + # *** NOTES *** + # Automatic gain is turned on in order to return the camera to its default state. + node_gain_auto = PySpin.CEnumerationPtr(nodemap.GetNode('GainAuto')) + if PySpin.IsAvailable(node_gain_auto) and PySpin.IsWritable(node_gain_auto): + gain_auto_continuous = node_exposure_auto.GetEntryByName('Continuous') + if PySpin.IsAvailable(gain_auto_continuous) and PySpin.IsReadable(gain_auto_continuous): + node_gain_auto.SetIntValue(gain_auto_continuous.GetValue()) + print('Turning automatic gain mode back on...\n') + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print('*** DEVICE INFORMATION ***\n') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + feature_string = node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable' + print('{}: {}'.format(node_feature.GetName(), feature_string)) + + else: + print('Device control information not available.') + + print('') + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + return False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice, timeout): + """ + This function acquires and saves 10 images from a device. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :param timeout: Timeout for image acquisition. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :type timeout: int + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** IMAGE ACQUISITION ***\n') + try: + result = True + + # Set acquisition mode to continuous + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or \ + not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (enum retrieval). Aborting...') + return False + + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or \ + not PySpin.IsReadable(node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...') + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Begin acquiring images + cam.BeginAcquisition() + + print('Acquiring images...') + + # Retrieve device serial number for filename + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Device serial number retrieved as {}...'.format(device_serial_number)) + + print('') + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve next received image and ensure image completion + image_result = cam.GetNextImage(timeout) + + if image_result.IsIncomplete(): + print('Image incomplete with image status {}...'.format(image_result.GetImageStatus())) + + else: + + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Grabbed image {}, width = {}, height = {}'.format(i, width, height)) + + # Convert image to mono 8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'Sequencer-{}-{}.jpg'.format(device_serial_number, i) + else: # if serial number is empty + filename = 'Sequencer-{}.jpg'.format(i) + + # Save image + image_converted.Save(filename) + print('Image saved at {}'.format(filename)) + + # Release image + image_result.Release() + print('') + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + return False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts very similarly to the run_single_camera() functions of other + examples, except that the values for the sequences are also calculated here; + please see NodeMapInfo example for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + try: + result = True + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure sequencer to be ready to set sequences + result &= configure_sequencer_part_one(nodemap) + if not result: + return result + + # Set sequences + # + # *** NOTES *** + # In the following section, the sequencer values are calculated. This + # section does not appear in the configuration, as the values + # calculated are somewhat arbitrary: width and height are both set to + # 25% of their maximum values, incrementing by 10%; exposure time is + # set to its minimum, also incrementing by 10% of its maximum; and gain + # is set to its minimum, incrementing by 2% of its maximum. + num_sequences = 5 + + # Retrieve maximum width; width recorded in pixels + node_width = PySpin.CIntegerPtr(nodemap.GetNode('Width')) + if not PySpin.IsAvailable(node_width) or not PySpin.IsReadable(node_width): + print('Unable to retrieve maximum width. Aborting...\n') + return False + + width_max = node_width.GetMax() + + # Retrieve maximum height; height recorded in pixels + node_height = PySpin.CIntegerPtr(nodemap.GetNode('Height')) + if not PySpin.IsAvailable(node_height) or not PySpin.IsReadable(node_height): + print('Unable to retrieve maximum height. Aborting...\n') + return False + + height_max = node_height.GetMax() + + # Retrieve maximum exposure time; exposure time recorded in microseconds + exposure_time_max_to_set = 2000000 + + node_exposure_time = PySpin.CFloatPtr(nodemap.GetNode('ExposureTime')) + if not PySpin.IsAvailable(node_exposure_time) or not PySpin.IsReadable(node_exposure_time): + print('Unable to retrieve maximum exposure time. Aborting...\n') + return False + + exposure_time_max = node_exposure_time.GetMax() + + if exposure_time_max > exposure_time_max_to_set: + exposure_time_max = exposure_time_max_to_set + + # Retrieve maximum gain; gain recorded in decibels + node_gain = PySpin.CFloatPtr(nodemap.GetNode('Gain')) + if not PySpin.IsAvailable(node_exposure_time) or not PySpin.IsReadable(node_exposure_time): + print('Unable to retrieve maximum gain. Aborting...\n') + return False + + gain_max = node_gain.GetMax() + + # Set initial values + width_to_set = width_max / 4 + height_to_set = height_max / 4 + exposure_time_to_set = node_exposure_time.GetMin() + gain_to_set = node_gain.GetMin() + + # Set custom values of each sequence + for sequence_num in range(num_sequences): + result &= set_single_state(nodemap, + sequence_num, + int(width_to_set), + int(height_to_set), + exposure_time_to_set, + gain_to_set) + if not result: + return result + + # Increment values + width_to_set += width_max / 10 + height_to_set += height_max / 10 + exposure_time_to_set += exposure_time_max / 10.0 + gain_to_set += gain_max / 50.0 + + # Calculate appropriate acquisition grab timeout window based on exposure time + # Note: exposure_time_to_set is in microseconds and needs to be converted to milliseconds + timeout = (exposure_time_to_set / 1000) + 1000 + + # Configure sequencer to acquire images + result &= configure_sequencer_part_two(nodemap) + if not result: + return result + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice, int(timeout)) + + # Reset sequencer + result &= reset_sequencer(nodemap) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: {}'.format(ex)) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: {}.{}.{}.{}\n'.format(version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: {}\n'.format(num_cameras)) + + # Finish if there are no cameras + if num_cameras == 0: + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera {}...\n'.format(i)) + + result &= run_single_camera(cam) + print('Camera {} example complete...\n'.format(i)) + + # Release reference to camera + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/SpinUpdate.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/SpinUpdate.py new file mode 100644 index 0000000..409fb80 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/SpinUpdate.py @@ -0,0 +1,89 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# SpinUpdate.py is a sample firmware updater application that takes in +# command line arguments. The example also demonstrates usage of callback +# functions to keep track of current update progress. +# +# Run with arguments in format (no quotes): "-R -P -UU " + +import PySpin +import sys + + +last_action = '' + + +def progress_callback(action, address, global_percent, curr_percent): + """ + Example progress callback function. + NOTE: This function must take exactly 4 arguments, + otherwise the update process will hang/crash! + + :param action: Current action being done in firmware update (as a byte string). + :param address: Address in camera being written to. + :param global_percent: Global completion percentage of update. + :param curr_percent: Completion percentage of current action. + :type action: str + :type address: int + :type global_percent: int + :type curr_percent: int + :rtype: int + """ + global last_action + if action != last_action: + # Prints action only if changed from previous one + print('Action: %s' % action) + last_action = action + + return 1 + + +def message_callback(message): + """ + Example message callback function. + NOTE: This function must take exactly 1 argument, + otherwise the update process will hang/crash! + + :param message: Message from updator (as a byte string). + :type message: str + :rtype: None + """ + print('Message: %s' % message) + + return 1 + + +def main(): + # Register callbacks + PySpin.SetProgressCallback(progress_callback) + PySpin.SetMessageCallback(message_callback) + + # Example usage for firmware update: + # Use either UpdateFirmware() or UpdateFirmwareConsole(): + # + # cmd = "-R3932019 C:\\firmware\\bfly2_u3_python1300.zim" # Add -P to argument list for callbacks + # return UpdateFirmware(cmd); + + return PySpin.UpdateFirmwareConsole(sys.argv) # uses command line args + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Trigger.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Trigger.py new file mode 100644 index 0000000..7917fc3 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Trigger.py @@ -0,0 +1,519 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Trigger.py shows how to trigger the camera. It relies on information +# provided in the Enumeration, Acquisition, and NodeMapInfo examples. +# +# It can also be helpful to familiarize yourself with the ImageFormatControl +# and Exposure examples. As they are somewhat shorter and simpler, either +# provides a strong introduction to camera customization. +# +# This example shows the process of configuring, using, and cleaning up a +# camera for use with both a software and a hardware trigger. + +import os +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +class TriggerType: + SOFTWARE = 1 + HARDWARE = 2 + + +CHOSEN_TRIGGER = TriggerType.SOFTWARE + + +def configure_trigger(cam): + """ + This function configures the camera to use a trigger. First, trigger mode is + set to off in order to select the trigger source. Once the trigger source + has been selected, trigger mode is then enabled, which has the camera + capture only a single image upon the execution of the chosen trigger. + + :param cam: Camera to configure trigger for. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + print('*** CONFIGURING TRIGGER ***\n') + + print('Note that if the application / user software triggers faster than frame time, the trigger may be dropped / skipped by the camera.\n') + print('If several frames are needed per trigger, a more reliable alternative for such case, is to use the multi-frame mode.\n\n') + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + print('Software trigger chosen ...') + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + print('Hardware trigger chose ...') + + try: + # Ensure trigger mode off + # The trigger must be disabled in order to configure whether the source + # is software or hardware. + nodemap = cam.GetNodeMap() + node_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(node_trigger_mode) or not PySpin.IsReadable(node_trigger_mode): + print('Unable to disable trigger mode (node retrieval). Aborting...') + return False + + node_trigger_mode_off = node_trigger_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(node_trigger_mode_off) or not PySpin.IsReadable(node_trigger_mode_off): + print('Unable to disable trigger mode (enum entry retrieval). Aborting...') + return False + + node_trigger_mode.SetIntValue(node_trigger_mode_off.GetValue()) + + print('Trigger mode disabled...') + + # Set TriggerSelector to FrameStart + # For this example, the trigger selector should be set to frame start. + # This is the default for most cameras. + node_trigger_selector= PySpin.CEnumerationPtr(nodemap.GetNode('TriggerSelector')) + if not PySpin.IsAvailable(node_trigger_selector) or not PySpin.IsWritable(node_trigger_selector): + print('Unable to get trigger selector (node retrieval). Aborting...') + return False + + node_trigger_selector_framestart = node_trigger_selector.GetEntryByName('FrameStart') + if not PySpin.IsAvailable(node_trigger_selector_framestart) or not PySpin.IsReadable( + node_trigger_selector_framestart): + print('Unable to set trigger selector (enum entry retrieval). Aborting...') + return False + node_trigger_selector.SetIntValue(node_trigger_selector_framestart.GetValue()) + + print('Trigger selector set to frame start...') + + # Select trigger source + # The trigger source must be set to hardware or software while trigger + # mode is off. + node_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerSource')) + if not PySpin.IsAvailable(node_trigger_source) or not PySpin.IsWritable(node_trigger_source): + print('Unable to get trigger source (node retrieval). Aborting...') + return False + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + node_trigger_source_software = node_trigger_source.GetEntryByName('Software') + if not PySpin.IsAvailable(node_trigger_source_software) or not PySpin.IsReadable( + node_trigger_source_software): + print('Unable to set trigger source (enum entry retrieval). Aborting...') + return False + node_trigger_source.SetIntValue(node_trigger_source_software.GetValue()) + print('Trigger source set to software...') + + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + node_trigger_source_hardware = node_trigger_source.GetEntryByName('Line0') + if not PySpin.IsAvailable(node_trigger_source_hardware) or not PySpin.IsReadable( + node_trigger_source_hardware): + print('Unable to set trigger source (enum entry retrieval). Aborting...') + return False + node_trigger_source.SetIntValue(node_trigger_source_hardware.GetValue()) + print('Trigger source set to hardware...') + + # Turn trigger mode on + # Once the appropriate trigger source has been set, turn trigger mode + # on in order to retrieve images using the trigger. + node_trigger_mode_on = node_trigger_mode.GetEntryByName('On') + if not PySpin.IsAvailable(node_trigger_mode_on) or not PySpin.IsReadable(node_trigger_mode_on): + print('Unable to enable trigger mode (enum entry retrieval). Aborting...') + return False + + node_trigger_mode.SetIntValue(node_trigger_mode_on.GetValue()) + print('Trigger mode turned back on...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def grab_next_image_by_trigger(nodemap, cam): + """ + This function acquires an image by executing the trigger node. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + # Use trigger to capture image + # The software trigger only feigns being executed by the Enter key; + # what might not be immediately apparent is that there is not a + # continuous stream of images being captured; in other examples that + # acquire images, the camera captures a continuous stream of images. + # When an image is retrieved, it is plucked from the stream. + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + # Get user input + input('Press the Enter key to initiate software trigger.') + + # Execute software trigger + node_softwaretrigger_cmd = PySpin.CCommandPtr(nodemap.GetNode('TriggerSoftware')) + if not PySpin.IsAvailable(node_softwaretrigger_cmd) or not PySpin.IsWritable(node_softwaretrigger_cmd): + print('Unable to execute trigger. Aborting...') + return False + + node_softwaretrigger_cmd.Execute() + + # TODO: Blackfly and Flea3 GEV cameras need 2 second delay after software trigger + + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + print('Use the hardware to trigger image acquisition.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def acquire_images(cam, nodemap, nodemap_tldevice): + """ + This function acquires and saves 10 images from a device. + Please see Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from. + :param nodemap: Device nodemap. + :param nodemap_tldevice: Transport layer device nodemap. + :type cam: CameraPtr + :type nodemap: INodeMap + :type nodemap_tldevice: INodeMap + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** IMAGE ACQUISITION ***\n') + try: + result = True + + # Set acquisition mode to continuous + # In order to access the node entries, they have to be casted to a pointer type (CEnumerationPtr here) + node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode('AcquisitionMode')) + if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): + print('Unable to set acquisition mode to continuous (enum retrieval). Aborting...') + return False + + # Retrieve entry node from enumeration node + node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName('Continuous') + if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( + node_acquisition_mode_continuous): + print('Unable to set acquisition mode to continuous (entry retrieval). Aborting...') + return False + + # Retrieve integer value from entry node + acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() + + # Set integer value from entry node as new value of enumeration node + node_acquisition_mode.SetIntValue(acquisition_mode_continuous) + + print('Acquisition mode set to continuous...') + + # Begin acquiring images + cam.BeginAcquisition() + + print('Acquiring images...') + + # Retrieve device serial number for filename + # + # *** NOTES *** + # The device serial number is retrieved in order to keep cameras from + # overwriting one another. Grabbing image IDs could also accomplish + # this. + device_serial_number = '' + node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode('DeviceSerialNumber')) + if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): + device_serial_number = node_device_serial_number.GetValue() + print('Device serial number retrieved as %s...' % device_serial_number) + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve the next image from the trigger + result &= grab_next_image_by_trigger(nodemap, cam) + + # Retrieve next received image + image_result = cam.GetNextImage(1000) + + # Ensure image completion + if image_result.IsIncomplete(): + print('Image incomplete with image status %d ...' % image_result.GetImageStatus()) + + else: + + # Print image information; height and width recorded in pixels + # + # *** NOTES *** + # Images have quite a bit of available metadata including + # things such as CRC, image status, and offset values, to + # name a few. + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Grabbed Image %d, width = %d, height = %d' % (i, width, height)) + + # Convert image to mono 8 + # + # *** NOTES *** + # Images can be converted between pixel formats by using + # the appropriate enumeration value. Unlike the original + # image, the converted one does not need to be released as + # it does not affect the camera buffer. + # + # When converting images, color processing algorithm is an + # optional parameter. + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'Trigger-%s-%d.jpg' % (device_serial_number, i) + else: # if serial number is empty + filename = 'Trigger-%d.jpg' % i + + # Save image + # + # *** NOTES *** + # The standard practice of the examples is to use device + # serial numbers to keep images of one device from + # overwriting those of another. + image_converted.Save(filename) + print('Image saved at %s\n' % filename) + + # Release image + # + # *** NOTES *** + # Images retrieved directly from the camera (i.e. non-converted + # images) need to be released in order to keep from filling the + # buffer. + image_result.Release() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + # End acquisition + # + # *** NOTES *** + # Ending acquisition appropriately helps ensure that devices clean up + # properly and do not need to be power-cycled to maintain integrity. + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def reset_trigger(nodemap): + """ + This function returns the camera to a normal state by turning off trigger mode. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + node_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode')) + if not PySpin.IsAvailable(node_trigger_mode) or not PySpin.IsReadable(node_trigger_mode): + print('Unable to disable trigger mode (node retrieval). Aborting...') + return False + + node_trigger_mode_off = node_trigger_mode.GetEntryByName('Off') + if not PySpin.IsAvailable(node_trigger_mode_off) or not PySpin.IsReadable(node_trigger_mode_off): + print('Unable to disable trigger mode (enum entry retrieval). Aborting...') + return False + + node_trigger_mode.SetIntValue(node_trigger_mode_off.GetValue()) + + print('Trigger mode disabled...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print('*** DEVICE INFORMATION ***\n') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + err = False + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure trigger + if configure_trigger(cam) is False: + return False + + # Acquire images + result &= acquire_images(cam, nodemap, nodemap_tldevice) + + # Reset trigger + result &= reset_trigger(nodemap) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + + # Since this application saves images in the current folder + # we must ensure that we have permission to write to this folder. + # If we do not have permission, fail right away. + try: + test_file = open('test.txt', 'w+') + except IOError: + print('Unable to write to current directory. Please check permissions.') + input('Press Enter to exit...') + return False + + test_file.close() + os.remove(test_file.name) + + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Trigger_QuickSpin.py b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Trigger_QuickSpin.py new file mode 100644 index 0000000..9a33cb4 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/Examples/Python3/Trigger_QuickSpin.py @@ -0,0 +1,422 @@ +# coding=utf-8 +# ============================================================================= +# Copyright (c) 2001-2019 FLIR Systems, Inc. All Rights Reserved. +# +# This software is the confidential and proprietary information of FLIR +# Integrated Imaging Solutions, Inc. ("Confidential Information"). You +# shall not disclose such Confidential Information and shall use it only in +# accordance with the terms of the license agreement you entered into +# with FLIR Integrated Imaging Solutions, Inc. (FLIR). +# +# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +# THIS SOFTWARE OR ITS DERIVATIVES. +# ============================================================================= +# +# Trigger_QuickSpin.py shows how to capture images with the +# trigger using the QuickSpin API. QuickSpin is a subset of the Spinnaker +# library that allows for simpler node access and control. +# +# This example demonstrates how to prepare, execute, and clean up the camera +# in regards to using both software and hardware triggers. Retrieving and +# setting node values using QuickSpin is the only portion of the example +# that differs from Trigger. +# +# A much wider range of topics is covered in the full Spinnaker examples than +# in the QuickSpin ones. There are only enough QuickSpin examples to +# demonstrate node access and to get started with the API; please see full +# Spinnaker examples for further or specific knowledge on a topic. + +import PySpin +import sys + +NUM_IMAGES = 10 # number of images to grab + + +class TriggerType: + SOFTWARE = 1 + HARDWARE = 2 + +CHOSEN_TRIGGER = TriggerType.SOFTWARE + + +def configure_trigger(cam): + """ + This function configures the camera to use a trigger. First, trigger mode is + ensured to be off in order to select the trigger source. Trigger mode is + then enabled, which has the camera capture only a single image upon the + execution of the chosen trigger. + + :param cam: Camera to configure trigger for. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** CONFIGURING TRIGGER ***\n') + + print('Note that if the application / user software triggers faster than frame time, the trigger may be dropped / skipped by the camera.\n') + print('If several frames are needed per trigger, a more reliable alternative for such case, is to use the multi-frame mode.\n\n') + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + print('Software trigger chosen...') + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + print('Hardware trigger chose...') + + try: + result = True + + # Ensure trigger mode off + # The trigger must be disabled in order to configure whether the source + # is software or hardware. + if cam.TriggerMode.GetAccessMode() != PySpin.RW: + print('Unable to disable trigger mode (node retrieval). Aborting...') + return False + + cam.TriggerMode.SetValue(PySpin.TriggerMode_Off) + + print('Trigger mode disabled...') + + # Set TriggerSelector to FrameStart + # For this example, the trigger selector should be set to frame start. + # This is the default for most cameras. + if cam.TriggerSelector.GetAccessMode() != PySpin.RW: + print('Unable to get trigger selector (node retrieval). Aborting...') + return False + + cam.TriggerSource.SetValue(PySpin.TriggerSelector_FrameStart) + + print('Trigger selector set to frame start...') + + # Select trigger source + # The trigger source must be set to hardware or software while trigger + # mode is off. + if cam.TriggerSource.GetAccessMode() != PySpin.RW: + print('Unable to get trigger source (node retrieval). Aborting...') + return False + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + cam.TriggerSource.SetValue(PySpin.TriggerSource_Software) + print('Trigger source set to software...') + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + cam.TriggerSource.SetValue(PySpin.TriggerSource_Line0) + print('Trigger source set to hardware...') + + # Turn trigger mode on + # Once the appropriate trigger source has been set, turn trigger mode + # on in order to retrieve images using the trigger. + cam.TriggerMode.SetValue(PySpin.TriggerMode_On) + print('Trigger mode turned back on...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def grab_next_image_by_trigger(cam): + """ + This function acquires an image by executing the trigger node. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + # Use trigger to capture image + # The software trigger only feigns being executed by the Enter key; + # what might not be immediately apparent is that there is not a + # continuous stream of images being captured; in other examples that + # acquire images, the camera captures a continuous stream of images. + # When an image is retrieved, it is plucked from the stream. + + if CHOSEN_TRIGGER == TriggerType.SOFTWARE: + # Get user input + input('Press the Enter key to initiate software trigger.') + + # Execute software trigger + if cam.TriggerSoftware.GetAccessMode() != PySpin.WO: + print('Unable to execute trigger. Aborting...') + return False + + cam.TriggerSoftware.Execute() + + # TODO: Blackfly and Flea3 GEV cameras need 2 second delay after software trigger + + elif CHOSEN_TRIGGER == TriggerType.HARDWARE: + print('Use the hardware to trigger image acquisition.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def acquire_images(cam): + """ + This function acquires and saves 10 images from a device. + Please see Acquisition example for more in-depth comments on acquiring images. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + + print('*** IMAGE ACQUISITION ***\n') + try: + result = True + + # Set acquisition mode to continuous + if cam.AcquisitionMode.GetAccessMode() != PySpin.RW: + print('Unable to set acquisition mode to continuous. Aborting...') + return False + + cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous) + print('Acquisition mode set to continuous...') + + # Begin acquiring images + cam.BeginAcquisition() + + print('Acquiring images...') + + # Get device serial number for filename + device_serial_number = '' + if cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: + device_serial_number = cam.TLDevice.DeviceSerialNumber.GetValue() + + print('Device serial number retrieved as %s...' % device_serial_number) + + # Retrieve, convert, and save images + for i in range(NUM_IMAGES): + try: + + # Retrieve the next image from the trigger + result &= grab_next_image_by_trigger(cam) + + # Retrieve next received image + image_result = cam.GetNextImage(1000) + + # Ensure image completion + if image_result.IsIncomplete(): + print('Image incomplete with image status %d ...' % image_result.GetImageStatus()) + + else: + + # Print image information + width = image_result.GetWidth() + height = image_result.GetHeight() + print('Grabbed Image %d, width = %d, height = %d' % (i, width, height)) + + # Convert image to mono 8 + image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) + + # Create a unique filename + if device_serial_number: + filename = 'Trigger-%s-%d.jpg' % (device_serial_number, i) + else: # if serial number is empty + filename = 'Trigger-%d.jpg' % i + + # Save image + image_converted.Save(filename) + + print('Image saved at %s\n' % filename) + + # Release image + image_result.Release() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + # End acquisition + cam.EndAcquisition() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def reset_trigger(cam): + """ + This function returns the camera to a normal state by turning off trigger mode. + + :param cam: Camera to acquire images from. + :type cam: CameraPtr + :returns: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + # Ensure trigger mode off + # The trigger must be disabled in order to configure whether the source + # is software or hardware. + if cam.TriggerMode.GetAccessMode() != PySpin.RW: + print('Unable to disable trigger mode (node retrieval). Aborting...') + return False + + cam.TriggerMode.SetValue(PySpin.TriggerMode_Off) + + print('Trigger mode disabled...') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def print_device_info(nodemap): + """ + This function prints the device information of the camera from the transport + layer; please see NodeMapInfo example for more in-depth comments on printing + device information from the nodemap. + + :param nodemap: Transport layer device nodemap. + :type nodemap: INodeMap + :returns: True if successful, False otherwise. + :rtype: bool + """ + + print('*** DEVICE INFORMATION ***\n') + + try: + result = True + node_device_information = PySpin.CCategoryPtr(nodemap.GetNode('DeviceInformation')) + + if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): + features = node_device_information.GetFeatures() + for feature in features: + node_feature = PySpin.CValuePtr(feature) + print('%s: %s' % (node_feature.GetName(), + node_feature.ToString() if PySpin.IsReadable(node_feature) else 'Node not readable')) + + else: + print('Device control information not available.') + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + return False + + return result + + +def run_single_camera(cam): + """ + This function acts as the body of the example; please see NodeMapInfo example + for more in-depth comments on setting up cameras. + + :param cam: Camera to run on. + :type cam: CameraPtr + :return: True if successful, False otherwise. + :rtype: bool + """ + try: + result = True + err = False + + # Retrieve TL device nodemap and print device information + nodemap_tldevice = cam.GetTLDeviceNodeMap() + + result &= print_device_info(nodemap_tldevice) + + # Initialize camera + cam.Init() + + # Retrieve GenICam nodemap + nodemap = cam.GetNodeMap() + + # Configure trigger + if configure_trigger(cam) is False: + return False + + # Acquire images + result &= acquire_images(cam) + + # Reset trigger + result &= reset_trigger(cam) + + # Deinitialize camera + cam.DeInit() + + except PySpin.SpinnakerException as ex: + print('Error: %s' % ex) + result = False + + return result + + +def main(): + """ + Example entry point; please see Enumeration example for more in-depth + comments on preparing and cleaning up the system. + + :return: True if successful, False otherwise. + :rtype: bool + """ + result = True + + # Retrieve singleton reference to system object + system = PySpin.System.GetInstance() + + # Get current library version + version = system.GetLibraryVersion() + print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build)) + + # Retrieve list of cameras from the system + cam_list = system.GetCameras() + + num_cameras = cam_list.GetSize() + + print('Number of cameras detected: %d' % num_cameras) + + # Finish if there are no cameras + if num_cameras == 0: + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + print('Not enough cameras!') + input('Done! Press Enter to exit...') + return False + + # Run example on each camera + for i, cam in enumerate(cam_list): + + print('Running example for camera %d...' % i) + + result &= run_single_camera(cam) + print('Camera %d example complete... \n' % i) + + # Release reference to camera + # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically + # cleaned up when going out of scope. + # The usage of del is preferred to assigning the variable to None. + del cam + + # Clear camera list before releasing system + cam_list.Clear() + + # Release system instance + system.ReleaseInstance() + + input('Done! Press Enter to exit...') + return result + + +if __name__ == '__main__': + if main(): + sys.exit(0) + else: + sys.exit(1) diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/README.txt b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/README.txt new file mode 100644 index 0000000..8966c05 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/README.txt @@ -0,0 +1,362 @@ +============================================================================= +Copyright (c) 2001-2020 FLIR Systems, Inc. All Rights Reserved. + +This software is the confidential and proprietary information of FLIR +Integrated Imaging Solutions, Inc. ("Confidential Information"). You +shall not disclose such Confidential Information and shall use it only in +accordance with the terms of the license agreement you entered into +with FLIR Integrated Imaging Solutions, Inc. (FLIR). + +FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE +SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES +SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING +THIS SOFTWARE OR ITS DERIVATIVES. +============================================================================= + +============================================================================= +== +== README +== +============================================================================= + +PySpin is a wrapper for FLIR Integrated Imaging Solutions' Spinnaker library. + +FLIR Integrated Imaging Solutions' website is located at https://www.flir.com/iis/machine-vision + +The PySpin Python extension provides a common software interface +to control and acquire images from FLIR USB 3.0, GigE, +and USB 2.0 cameras using the same API under 32- or 64-bit Windows. + +============================================================================= +TABLE OF CONTENTS +============================================================================= +1. INSTALLATION +1.1 INSTALLATION ON WINDOWS +1.2 INSTALLATION ON LINUX +1.3 INSTALLATION ON MACOS +2. API DIFFERENCES +3. REMOVE PYSPIN + +============================================================================= +1. INSTALLATION +============================================================================= + +----------------------------------------------------------------------------- +1.1 WINDOWS +----------------------------------------------------------------------------- + +1. Install Python. Currently we support Python 2.7, 3.5-3.8. To download + Python, visit https://www.python.org/downloads/. Note that the Python + website defaults to 32-bit interpreters, so if you want a 64-bit version + of Python you have to click into the specific release version. + +2. (Optional) Set the PATH environment variable for your Python installation. + This may have been done automatically as part of installation, but to do + this manually you have to open Environment Variables through the following: + + My Computer > Properties > Advanced System Settings > Environment Variables + + Add your Python installation location to your PATH variable. For example, + if you installed Python at C:\Python38\, you would add the following entry + to the PATH variable: + + C:\Python38\ + +3. Configure your Python installation. From a command line, run the following + commands to update and install dependencies for your associated Python version: + + -m ensurepip + -m pip install --upgrade pip numpy matplotlib + + NumPy is a requirement for PySpin and needs to be at least version 1.15 or + above. Matplotlib is not required for the library itself but is used in some + of our examples to highlight possible usages of PySpin. For better support of + matplotlib output image file formats, Pillow is suggested to be installed. + Note: some versions of Pillow might NOT support some Python versions. + + The full list of supported Pillow versions given a Python version can be found here: + https://pillow.readthedocs.io/en/stable/installation.html#notes + + For example, with Python 3.8, install a supported Pillow using the following command: + + ex. py -3.8 -m pip install Pillow==7.0.0 + + Older installations of Python 2.7 do NOT come with enum34, which is required by + the Inference.py Python2 example. Install enum34 for Python 2.7 using the following command: + + py -2.7 -m pip install enum34 + +4. To ensure prerequisites such as drivers and Visual Studio redistributables + are installed on the system, run the Spinnaker SDK installer that corresponds + with the PySpin version number. For example, if installing PySpin 1.8.0.0, + install Spinnaker 1.8.0.0 beforehand, selecting only the Visual Studio + runtimes and drivers. + +5. Run the following command to install PySpin to your associated Python version. + This command assumes you have your PATH variable set correctly for Python: + + -m pip install spinnaker_python-2.x.x.x-cp3x-cp3x-win_amd64.whl + + Ensure that the wheel downloaded matches the Python version you are installing to! + +After installation, PySpin examples can be ran directly from the command prompt. +For example, if PySpin is installed for Python 3.8, run a preinstalled example +using the following: + + ex. py -3.8 Examples\Python3\Acquisition.py + +----------------------------------------------------------------------------- +1.2 LINUX +----------------------------------------------------------------------------- + +1. Check that pip is available for your respective Python versions + by running the following command: + + sudo apt-get install python-pip python3-pip + +2. Install library dependencies for PySpin: numpy and matplotlib. NumPy is a + requirement for PySpin and needs to be at least version 1.15 or above for Ubuntu + 18.04 and version 1.19 or above for Ubuntu 20.04. Matplotlib is not required for + the library itself but is used in some of our examples to highlight possible + usages of PySpin. Install these dependencies by running one of the following + commands. + + - Install for Python 2.7, user only: + python -m pip install --upgrade --user numpy matplotlib + + - Install for Python 2.7, site wide: + sudo python -m pip install --upgrade numpy matplotlib + + - Install for Python 3.5, user only (16.04 only): + python3.5 -m pip install --upgrade --user numpy matplotlib + + - Install for Python 3.5, site wide (16.04 only): + sudo python3.5 -m pip install --upgrade numpy matplotlib + + - Install for Python 3.6, user only: + python3.6 -m pip install --upgrade --user numpy matplotlib + + - Install for Python 3.6, site wide: + sudo python3.6 -m pip install --upgrade numpy matplotlib + + - Install for Python 3.7, user only: + python3.7 -m pip install --upgrade --user numpy matplotlib + + - Install for Python 3.7, site wide: + sudo python3.7 -m pip install --upgrade numpy matplotlib + + - Install for Python 3.8, user only: + python3.8 -m pip install --upgrade --user numpy matplotlib + + - Install for Python 3.8, site wide: + sudo python3.8 -m pip install --upgrade numpy matplotlib + + For better support of matplotlib output image file formats, Pillow is suggested to be installed. + Note: some versions of Pillow might NOT support some Python versions. + + The full list of supported Pillow versions given a Python version can be found here: + https://pillow.readthedocs.io/en/stable/installation.html#notes + + For example, with Python 3.8, install a supported Pillow using the following command: + + ex. python3.8 -m pip install Pillow==7.0.0 + + Older installations of Python 2.7 do NOT come with enum34, which is required by + the Inference.py Python2 example. Install enum34 for Python 2.7 using the following command: + + python2.7 -m pip install enum34 + +3. Ensure that the corresponding version of the Spinnaker SDK Debian packages + and their prerequisites are installed beforehand + (ex. install the 1.21.0.61 packages if the wheel version is also 1.21.0.61) + +4. Install wheel for specific Python version. This can be installed site-wide + for all users or for a specific user. + + - Python 2.7, site wide: + sudo python -m pip install spinnaker_python-2.x.x.x-cp27-cp27mu-linux_x86_64.whl + + - Python 2.7, user only: + python -m pip install --user spinnaker_python-2.x.x.x-cp27-cp27mu-linux_x86_64.whl + + - Python 3.5, site wide (16.04 only): + sudo python3.5 -m pip install spinnaker_python-2.x.x.x-cp35-cp35m-linux_x86_64.whl + + - Python 3.5, user only (16.04 only): + python3.5 -m pip install --user spinnaker_python-2.x.x.x-cp35-cp35m-linux_x86_64.whl + + - Python 3.6, site wide: + sudo python3.6 -m pip install spinnaker_python-2.x.x.x-cp36-cp36m-linux_x86_64.whl + + - Python 3.6, user only: + python3.6 -m pip install --user spinnaker_python-2.x.x.x-cp36-cp36m-linux_x86_64.whl + + - Python 3.7, site wide: + sudo python3.7 -m pip install spinnaker_python-2.x.x.x-cp37-cp37m-linux_x86_64.whl + + - Python 3.7, user only: + python3.7 -m pip install --user spinnaker_python-2.x.x.x-cp37-cp37m-linux_x86_64.whl + + - Python 3.8, site wide: + sudo python3.8 -m pip install spinnaker_python-2.x.x.x-cp38-cp38-linux_x86_64.whl + + - Python 3.8, user only: + python3.8 -m pip install --user spinnaker_python-2.x.x.x-cp38-cp38-linux_x86_64.whl + +5. The examples are located in the Examples folder of the extracted tarball. Run with: + ex. python3.8 Examples/Python3/DeviceEvents.py + +----------------------------------------------------------------------------- +1.3 MACOS +----------------------------------------------------------------------------- + +1. Check that Python is installed. MacOS comes with Python 2.7 installed, + but it may be an older build of Python. Up-to-date Python packages + can be downloaded from https://www.python.org/downloads. + +2. Update pip for Python. Run the following command for your version of Python: + + sudo -m ensurepip + + This will install a version of pip and allow you to update or install new wheels. + +3. Install library dependencies for PySpin: numpy and matplotlib. NumPy is a + requirement for PySpin and needs to be at least version 1.15 or above. + Matplotlib is not required for the library itself but is used in some of + our examples to highlight possible usages of PySpin. Install these + dependencies by running one of the following commands. + + - Install for Python 2.7, user only: + python -m pip install --upgrade --user numpy matplotlib + + - Install for Python 2.7, site wide: + sudo python -m pip install --upgrade numpy matplotlib + + - Install for Python 3.6, user only: + python3.6 -m pip install --upgrade --user numpy matplotlib + + - Install for Python 3.6, site wide: + sudo python3.6 -m pip install --upgrade numpy matplotlib + + - Install for Python 3.7, user only: + python3.7 -m pip install --upgrade --user numpy matplotlib + + - Install for Python 3.7, site wide: + sudo python3.7 -m pip install --upgrade numpy matplotlib + + - Install for Python 3.8, user only: + python3.8 -m pip install --upgrade --user numpy matplotlib + + - Install for Python 3.8, site wide: + sudo python3.8 -m pip install --upgrade numpy matplotlib + + + For better support of matplotlib output image file formats, Pillow is suggested to be installed. + Note: some versions of Pillow might NOT support some Python versions. + + The full list of supported Pillow versions given a Python version can be found here: + https://pillow.readthedocs.io/en/stable/installation.html#notes + + For example, with Python 3.8, install a supported Pillow using the following command: + + ex. python3.8 -m pip install Pillow==7.0.0 + + Older installations of Python 2.7 do NOT come with enum34, which is required by + the Inference.py Python2 example. Install enum34 for Python 2.7 using the following command: + + python2.7 -m pip install enum34 + +4. Ensure that the corresponding version of the Spinnaker SDK MacOS packages + and their prerequisites are installed beforehand. + (ex. install 1.21.0.61 packages if the wheel version is also 1.21.0.61) + +5. Install the PySpin wheel for specific Python version. + ex. sudo python3.7 -m pip install spinnaker_python-2.x.x.x-cp37-cp37mu-macos_x86_x64.whl" for 64-bit Python 3.7 + +6. The examples are located in the Examples folder of the extracted tarball. Run with: + ex. python3.7 Examples/Python3/DeviceEvents.py + +============================================================================= +2. API DIFFERENCES +============================================================================= + +Except for the changes listed below, most function names are exactly the same +as the C++ API. See examples for PySpin usage! + +- All methods of SpinnakerException no longer exist, please replace all + usages of SpinnakerException with any of the following attributes: + message: Normal exception message. + fullmessage: Exception message including line, file, function, + build date, and time (from C++ library). + errorcode: Integer error code of the exception. + The SpinnakerException instance itself can be printed, as it derives from + the BaseException class and has a default __str__ representation. + See examples for usage. + +- Image creation using NumPy arrays (although the int type of the array must be uint8) + +- The majority of headers from the C++ API have been wrapped, with the exception of: + - Headers with "Adapter" or "Port" in the name + - NodeMapRef.h, NodeMapFactory.h + - Synch.h, GCSynch.h, Counter.h, filestream.h + +- INode and IValue types (esp. returned from GetNode()) have to + be initialized to their respective pointer types + (ex. CFloatPtr, CEnumerationPtr) to access their functions + +- CameraPtr, CameraList, InterfacePtr, InterfaceList, and SystemPtr + have to be manually released and/or deleted before program exit (use del operator) + - See EnumerationEvents example + +- Image.GetData() returns a 1-D NumPy array of integers, the int type + depends on the pixel format of the image + +- Image.GetNDArray() returns a 2 or 3-D NumPy array of integers, only for select + image formats. This can be used in libraries such as PIL and/or OpenCV. + +- Node callbacks take in a callback class instead of a function pointer + - Register is now RegisterNodeCallback, Deregister is now DeregisterNodeCallback + - See NodeMapCallback example for more details + +- IImage.CalculateChannelStatistics(StatisticsChannel channel) returns + a ChannelStatistics object representing stats for the given channel + in the image. These stats are properties within the ChannelStatistics object, + Please see the docstring for details. This replaces ImageStatistics! + +- Pass-by-reference functions now return the type and take in void + - GetFeatures() returns a Python list of IValue, instead of taking + in a FeatureList_t reference + - GetChildren() returns a Python list of INode, instead of taking + in a NodeList_t reference + - Same with GetEntries(), GetNodes() + - GetPropertyNames() returns a Python list of str, + instead of taking in a gcstring_vector reference + - See DeviceEvents example for usage + +- Methods Get() and Set() for IRegister and register nodes use NumPy arrays + - Get() takes in the length of the register to read and two optional + bools, returns a NumPy array + - Set() takes in a single NumPy array + +============================================================================= +3. REMOVE PYSPIN +============================================================================= + +Removing or updating PySpin is similar to removing or updating other wheels. + +For Windows, if you need to remove PySpin, the following command needs to be +run from an administrator command prompt to remove your associated Python version: + + -m pip uninstall spinnaker-python + +For Linux or MacOS, if you need to remove PySpin from a user-specific install, run +the following command to remove your associated Python version: + + -m pip uninstall spinnaker-python + +For Linux or MacOS, if you need to remove PySpin from a site-wide install the +following command needs to be run as sudo to remove your associated Python version: + +sudo -m pip uninstall spinnaker-python \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/docs/PySpinDoc.chm b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/docs/PySpinDoc.chm new file mode 100644 index 0000000..4e69f95 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/docs/PySpinDoc.chm differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/docs/PySpinDoc.pdf b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/docs/PySpinDoc.pdf new file mode 100644 index 0000000..5b2a889 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/docs/PySpinDoc.pdf differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/licenses/FFmpeg_compliance_doc.txt b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/licenses/FFmpeg_compliance_doc.txt new file mode 100644 index 0000000..7b06e29 --- /dev/null +++ b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/licenses/FFmpeg_compliance_doc.txt @@ -0,0 +1,2 @@ +This software uses code of FFmpeg http://ffmpeg.org licensed under the LGPL v2.1 (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html). +The FFmpeg code can be found online at https://github.com/FFmpeg/FFmpeg/tree/5156578d1f486163d5b83f1d63246cd23d107933. \ No newline at end of file diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/licenses/Spinnaker-Open-Source-Licenses.pdf b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/licenses/Spinnaker-Open-Source-Licenses.pdf new file mode 100644 index 0000000..55a8894 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/licenses/Spinnaker-Open-Source-Licenses.pdf differ diff --git a/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64.whl b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64.whl new file mode 100644 index 0000000..79472e1 Binary files /dev/null and b/FLIR/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64/spinnaker_python-2.2.0.48-cp38-cp38-win_amd64.whl differ