├── Acquisition.py ├── DeviceEvents.py ├── Enumeration.py ├── EnumerationEvents.py ├── Enumeration_QuickSpin.py ├── Exposure_QuickSpin.py ├── ImageChannelStatistics.py ├── ImageEvents.py ├── ImageFormatControl.py ├── ImageFormatControl_QuickSpin.py ├── Logging.py ├── NodeMapCallback.py ├── NodeMapInfo.py ├── NodeMapInfo_QuickSpin.py ├── README.md ├── SaveToAvi.py ├── SpinUpdate.py ├── Trigger.py ├── Trigger_QuickSpin.py └── take_a_photo.py /Acquisition.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # Acquisition.py shows how to acquire images. It relies on 20 | # information provided in the Enumeration example. Also, check out the 21 | # ExceptionHandling and NodeMapInfo examples if you haven't already. 22 | # ExceptionHandling shows the handling of standard and Spinnaker exceptions 23 | # while NodeMapInfo explores retrieving information from various node types. 24 | # 25 | # This example touches on the preparation and cleanup of a camera just before 26 | # and just after the acquisition of images. Image retrieval and conversion, 27 | # grabbing image data, and saving images are all covered as well. 28 | # 29 | # Once comfortable with Acquisition, we suggest checking out 30 | # AcquisitionMultipleCamera, NodeMapCallback, or SaveToAvi. 31 | # AcquisitionMultipleCamera demonstrates simultaneously acquiring images from 32 | # a number of cameras, NodeMapCallback serves as a good introduction to 33 | # programming with callbacks and events, and SaveToAvi exhibits video creation. 34 | import pyspin 35 | from pyspin import PySpin 36 | import numpy as np 37 | 38 | NUM_IMAGES = 1 # number of images to grab 39 | 40 | 41 | def acquire_images(cam, nodemap, nodemap_tldevice): 42 | """ 43 | This function acquires and saves 10 images from a device. 44 | 45 | :param cam: Camera to acquire images from. 46 | :param nodemap: Device nodemap. 47 | :param nodemap_tldevice: Transport layer device nodemap. 48 | :type cam: CameraPtr 49 | :type nodemap: INodeMap 50 | :type nodemap_tldevice: INodeMap 51 | :return: True if successful, False otherwise. 52 | :rtype: bool 53 | """ 54 | 55 | print "*** IMAGE ACQUISITION ***\n" 56 | try: 57 | result = True 58 | 59 | # Set acquisition mode to continuous 60 | # 61 | # *** NOTES *** 62 | # Because the example acquires and saves 10 images, setting acquisition 63 | # mode to continuous lets the example finish. If set to single frame 64 | # or multiframe (at a lower number of images), the example would just 65 | # hang. This would happen because the example has been written to 66 | # acquire 10 images while the camera would have been programmed to 67 | # retrieve less than that. 68 | # 69 | # Setting the value of an enumeration node is slightly more complicated 70 | # than other node types. Two nodes must be retrieved: first, the 71 | # enumeration node is retrieved from the nodemap; and second, the entry 72 | # node is retrieved from the enumeration node. The integer value of the 73 | # entry node is then set as the new value of the enumeration node. 74 | # 75 | # Notice that both the enumeration and the entry nodes are checked for 76 | # availability and readability/writability. Enumeration nodes are 77 | # generally readable and writable whereas their entry nodes are only 78 | # ever readable. 79 | # 80 | # Retrieve enumeration node from nodemap 81 | 82 | # In order to access the node entries, they have to be casted to a pointer type (CEnumerationPtr here) 83 | node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode("AcquisitionMode")) 84 | if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): 85 | print "Unable to set acquisition mode to continuous (enum retrieval). Aborting..." 86 | return False 87 | 88 | # Retrieve entry node from enumeration node 89 | node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName("Continuous") 90 | if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable(node_acquisition_mode_continuous): 91 | print "Unable to set acquisition mode to continuous (entry retrieval). Aborting..." 92 | return False 93 | 94 | # Retrieve integer value from entry node 95 | acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() 96 | 97 | # Set integer value from entry node as new value of enumeration node 98 | node_acquisition_mode.SetIntValue(acquisition_mode_continuous) 99 | 100 | print "Acquisition mode set to continuous..." 101 | 102 | # Begin acquiring images 103 | # 104 | # *** NOTES *** 105 | # What happens when the camera begins acquiring images depends on the 106 | # acquisition mode. Single frame captures only a single image, multi 107 | # frame catures a set number of images, and continuous captures a 108 | # continuous stream of images. Because the example calls for the 109 | # retrieval of 10 images, continuous mode has been set. 110 | # 111 | # *** LATER *** 112 | # Image acquisition must be ended when no more images are needed. 113 | cam.BeginAcquisition() 114 | 115 | print "Acquiring images..." 116 | 117 | # Retrieve device serial number for filename 118 | # 119 | # *** NOTES *** 120 | # The device serial number is retrieved in order to keep cameras from 121 | # overwriting one another. Grabbing image IDs could also accomplish 122 | # this. 123 | device_serial_number = "" 124 | node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode("DeviceSerialNumber")) 125 | if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): 126 | device_serial_number = node_device_serial_number.GetValue() 127 | print "Device serial number retrieved as %s..." % device_serial_number 128 | 129 | # Retrieve, convert, and save images 130 | for i in range(NUM_IMAGES): 131 | try: 132 | 133 | # Retrieve next received image 134 | # 135 | # *** NOTES *** 136 | # Capturing an image houses images on the camera buffer. Trying 137 | # to capture an image that does not exist will hang the camera. 138 | # 139 | # *** LATER *** 140 | # Once an image from the buffer is saved and/or no longer 141 | # needed, the image must be released in order to keep the 142 | # buffer from filling up. 143 | image_result = cam.GetNextImage() 144 | 145 | # Ensure image completion 146 | # 147 | # *** NOTES *** 148 | # Images can easily be checked for completion. This should be 149 | # done whenever a complete image is expected or required. 150 | # Further, check image status for a little more insight into 151 | # why an image is incomplete. 152 | if image_result.IsIncomplete(): 153 | print "Image incomplete with image status %d ..." % image_result.GetImageStatus() 154 | 155 | else: 156 | 157 | # Print image information; height and width recorded in pixels 158 | # 159 | # *** NOTES *** 160 | # Images have quite a bit of available metadata including 161 | # things such as CRC, image status, and offset values, to 162 | # name a few. 163 | width = image_result.GetWidth() 164 | height = image_result.GetHeight() 165 | print "Grabbed Image %d, width = %d, height = %d" % (i, width, height) 166 | 167 | 168 | # Convert image to mono 8 169 | # 170 | # *** NOTES *** 171 | # Images can be converted between pixel formats by using 172 | # the appropriate enumeration value. Unlike the original 173 | # image, the converted one does not need to be released as 174 | # it does not affect the camera buffer. 175 | # 176 | # When converting images, color processing algorithm is an 177 | # optional parameter. 178 | image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) 179 | 180 | # Create a unique filename 181 | if device_serial_number: 182 | filename = "Acquisition-%s-%d.jpg" % (device_serial_number, i) 183 | else: # if serial number is empty 184 | filename = "Acquisition-%d.jpg" % i 185 | print " \/ " 186 | data = np.asarray( image_result, dtype="int32" ) 187 | print type(data) 188 | # Save image 189 | # 190 | # *** NOTES *** 191 | # The standard practice of the examples is to use device 192 | # serial numbers to keep images of one device from 193 | # overwriting those of another. 194 | image_converted.Save(filename) 195 | print "Image saved at %s" % filename 196 | 197 | # Release image 198 | # 199 | # *** NOTES *** 200 | # Images retrieved directly from the camera (i.e. non-converted 201 | # images) need to be released in order to keep from filling the 202 | # buffer. 203 | image_result.Release() 204 | print "" 205 | 206 | except PySpin.SpinnakerException as ex: 207 | print "Error: %s" % ex 208 | return False 209 | 210 | # End acquisition 211 | # 212 | # *** NOTES *** 213 | # Ending acquisition appropriately helps ensure that devices clean up 214 | # properly and do not need to be power-cycled to maintain integrity. 215 | cam.EndAcquisition() 216 | 217 | except PySpin.SpinnakerException as ex: 218 | print "Error: %s" % ex 219 | return False 220 | 221 | return result 222 | 223 | 224 | def print_device_info(nodemap): 225 | """ 226 | This function prints the device information of the camera from the transport 227 | layer; please see NodeMapInfo example for more in-depth comments on printing 228 | device information from the nodemap. 229 | 230 | :param nodemap: Transport layer device nodemap. 231 | :type nodemap: INodeMap 232 | :returns: True if successful, False otherwise. 233 | :rtype: bool 234 | """ 235 | 236 | print "*** DEVICE INFORMATION ***\n" 237 | 238 | try: 239 | result = True 240 | node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) 241 | 242 | if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): 243 | features = node_device_information.GetFeatures() 244 | for feature in features: 245 | node_feature = PySpin.CValuePtr(feature) 246 | print "%s: %s" % (node_feature.GetName(), 247 | node_feature.ToString() if PySpin.IsReadable(node_feature) else "Node not readable") 248 | 249 | else: 250 | print "Device control information not available." 251 | 252 | except PySpin.SpinnakerException as ex: 253 | print "Error: %s" % ex 254 | return False 255 | 256 | return result 257 | 258 | 259 | def run_single_camera(cam): 260 | """ 261 | This function acts as the body of the example; please see NodeMapInfo example 262 | for more in-depth comments on setting up cameras. 263 | 264 | :param cam: Camera to run on. 265 | :type cam: CameraPtr 266 | :return: True if successful, False otherwise. 267 | :rtype: bool 268 | """ 269 | try: 270 | result = True 271 | 272 | # Retrieve TL device nodemap and print device information 273 | nodemap_tldevice = cam.GetTLDeviceNodeMap() 274 | 275 | result &= print_device_info(nodemap_tldevice) 276 | 277 | # Initialize camera 278 | cam.Init() 279 | 280 | # Retrieve GenICam nodemap 281 | nodemap = cam.GetNodeMap() 282 | 283 | # Acquire images 284 | result &= acquire_images(cam, nodemap, nodemap_tldevice) 285 | 286 | # Deinitialize camera 287 | cam.DeInit() 288 | 289 | except PySpin.SpinnakerException as ex: 290 | print "Error: %s" % ex 291 | result = False 292 | 293 | return result 294 | 295 | 296 | def main(): 297 | """ 298 | Example entry point; please see Enumeration example for more in-depth 299 | comments on preparing and cleaning up the system. 300 | 301 | :return: True if successful, False otherwise. 302 | :rtype: bool 303 | """ 304 | # Retrieve singleton reference to system object 305 | system = PySpin.System.GetInstance() 306 | 307 | # Retrieve list of cameras from the system 308 | cam_list = system.GetCameras() 309 | 310 | num_cameras = cam_list.GetSize() 311 | 312 | print "Number of cameras detected: %d" % num_cameras 313 | 314 | # Finish if there are no cameras 315 | if num_cameras == 0: 316 | 317 | # Clear camera list before releasing system 318 | cam_list.Clear() 319 | 320 | # Release system 321 | system.ReleaseInstance() 322 | 323 | print "Not enough cameras!" 324 | raw_input("Done! Press Enter to exit...") 325 | return False 326 | 327 | # Run example on each camera 328 | for i in range(num_cameras): 329 | cam = cam_list.GetByIndex(i) 330 | 331 | print "Running example for camera %d..." % i 332 | 333 | result = run_single_camera(cam) 334 | print "Camera %d example complete..." % i 335 | 336 | # Release reference to camera 337 | # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically 338 | # cleaned up when going out of scope. 339 | # The usage of del is preferred to assigning the variable to None. 340 | del cam 341 | 342 | # Clear camera list before releasing system 343 | cam_list.Clear() 344 | 345 | # Release instance 346 | system.ReleaseInstance() 347 | 348 | raw_input("Done! Press Enter to exit...") 349 | return result 350 | 351 | if __name__ == "__main__": 352 | main() 353 | -------------------------------------------------------------------------------- /DeviceEvents.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # This software is the confidential and proprietary information of FLIR 5 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 6 | # shall not disclose such Confidential Information and shall use it only in 7 | # accordance with the terms of the license agreement you entered into 8 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 9 | # 10 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 11 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 12 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 13 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 14 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 15 | # THIS SOFTWARE OR ITS DERIVATIVES. 16 | # =============================================================================*/ 17 | # 18 | # DeviceEvents.py shows how to create a handler to access device 19 | # events. It relies on information provided in the Enumeration, Acquisition, 20 | # and NodeMapInfo examples. 21 | # 22 | # It can also be helpful to familiarize yourself with the NodeMapCallback 23 | # example, as nodemap callbacks follow the same general procedure as events. 24 | # 25 | # Device events can be thought of as camera-related events. This example 26 | # creates a user-defined class, DeviceEventHandler, which allows the user to 27 | # define any properties, parameters, and the event itself while DeviceEvent, 28 | # the parent class, allows the child class to appropriately interface with 29 | # the Spinnaker SDK. 30 | 31 | import PySpin 32 | 33 | 34 | class EventType: 35 | """ 36 | 'Enum' for choosing whether to register a event specifically for exposure end events 37 | or universally for all events. 38 | """ 39 | GENERIC = 0 40 | SPECIFIC = 1 41 | 42 | CHOSEN_EVENT = EventType.GENERIC # change me! 43 | NUM_IMAGES = 10 # number of images to acquire 44 | 45 | 46 | class DeviceEventHandler(PySpin.DeviceEvent): 47 | """ 48 | This class defines the properties, parameters, and the event itself. Take a 49 | moment to notice what parts of the class are mandatory, and what have been 50 | added for demonstration purposes. First, any class used to define device 51 | events must inherit from DeviceEvent. Second, the method signature of 52 | OnDeviceEvent() must also be consistent. Everything else - including the 53 | constructor, destructor, properties, and body of OnDeviceEvent() - are 54 | particular to the example. 55 | """ 56 | def __init__(self, eventname): 57 | """ 58 | This constructor registers an event name to be used on device events. 59 | 60 | :param eventname: Name of event to register. 61 | :type eventname: str 62 | :rtype: None 63 | """ 64 | super(DeviceEventHandler, self).__init__() 65 | self.event_name = eventname 66 | self.count = 0 67 | 68 | def OnDeviceEvent(self, eventname): 69 | """ 70 | Callback function when a device event occurs. 71 | Note eventname is a wrapped gcstring, not a Python string, but basic operations such as printing and comparing 72 | with Python strings are supported. 73 | 74 | :param eventname: gcstring representing the name of the occurred event. 75 | :type eventname: gcstring 76 | :rtype: None 77 | """ 78 | if eventname == self.event_name: 79 | self.count += 1 80 | 81 | # Print information on specified device event 82 | print "\tDevice event %s with ID %i number %i..." % (self.GetDeviceEventName(), 83 | self.GetDeviceEventId(), 84 | self.count) 85 | else: 86 | # Print no information on non-specified event 87 | print "\tDevice event occurred; not %s; ignoring..." % self.event_name 88 | 89 | 90 | def configure_device_events(nodemap, cam): 91 | """ 92 | This function configures the example to execute device events by enabling all 93 | types of device events, and then creating and registering a device event that 94 | only concerns itself with an end of exposure event. 95 | 96 | :param INodeMap nodemap: Device nodemap. 97 | :param CameraPtr cam: Pointer to camera. 98 | :returns: tuple (result, device_event_handler) 99 | WHERE 100 | result is True if successful, False otherwise 101 | device_event_handler is the event handler 102 | :rtype: (bool, DeviceEventHandler) 103 | """ 104 | print "\n*** CONFIGURING DEVICE EVENTS ***\n" 105 | 106 | try: 107 | result = True 108 | 109 | # Retrieve device event selector 110 | # 111 | # *** NOTES *** 112 | # Each type of device event must be enabled individually. This is done 113 | # by retrieving "EventSelector" (an enumeration node) and then enabling 114 | # the device event on "EventNotification" (another enumeration node). 115 | # 116 | # This example only deals with exposure end events. However, instead of 117 | # only enabling exposure end events with a simpler device event function, 118 | # all device events are enabled while the device event handler deals with 119 | # ensuring that only exposure end events are considered. A more standard 120 | # use-case might be to enable only the events of interest. 121 | node_event_selector = PySpin.CEnumerationPtr(nodemap.GetNode("EventSelector")) 122 | if not PySpin.IsAvailable(node_event_selector) or not PySpin.IsReadable(node_event_selector): 123 | print "Unable to retrieve event selector entries. Aborting..." 124 | return False 125 | 126 | entries = node_event_selector.GetEntries() 127 | print "Enabling event selector entries..." 128 | 129 | # Enable device events 130 | # 131 | # *** NOTES *** 132 | # In order to enable a device event, the event selector and event 133 | # notification nodes (both of type enumeration) must work in unison. 134 | # The desired event must first be selected on the event selector node 135 | # and then enabled on the event notification node. 136 | for entry in entries: 137 | 138 | # Select entry on selector node 139 | node_entry = PySpin.CEnumEntryPtr(entry) 140 | if not PySpin.IsAvailable(node_entry) or not PySpin.IsReadable(node_entry): 141 | 142 | # Skip if node fails 143 | result = False 144 | continue 145 | 146 | node_event_selector.SetIntValue(node_entry.GetValue()) 147 | 148 | # Retrieve event notification node (an enumeration node) 149 | node_event_notification = PySpin.CEnumerationPtr(nodemap.GetNode("EventNotification")) 150 | if not PySpin.IsAvailable(node_event_notification) or not PySpin.IsWritable(node_event_notification): 151 | 152 | # Skip if node fails 153 | result = False 154 | continue 155 | 156 | # Retrieve entry node to enable device event 157 | node_event_notification_on = PySpin.CEnumEntryPtr(node_event_notification.GetEntryByName("On")) 158 | if not PySpin.IsAvailable(node_event_notification_on) or not PySpin.IsReadable(node_event_notification_on): 159 | 160 | # Skip if node fails 161 | result = False 162 | continue 163 | 164 | node_event_notification.SetIntValue(node_event_notification_on.GetValue()) 165 | 166 | print "\t%s: enabled..." % node_entry.GetDisplayName() 167 | 168 | # Create device event 169 | # 170 | # *** NOTES *** 171 | # The class has been designed to take in the name of an event. If all 172 | # events are registered generically, all event types will trigger a 173 | # device event; on the other hand, if an event is registered 174 | # specifically, only that event will trigger an event. 175 | device_event_handler = DeviceEventHandler("EventExposureEnd") 176 | 177 | # Register device event 178 | # 179 | # *** NOTES *** 180 | # Device events are registered to cameras. If there are multiple 181 | # cameras, each camera must have any device events registered to it 182 | # separately. Note that multiple device events may be registered to a 183 | # single camera. 184 | # 185 | # *** LATER *** 186 | # Device events must be unregistered manually. This must be done prior 187 | # to releasing the system and while the device events are still in 188 | # scope. 189 | if CHOSEN_EVENT == EventType.GENERIC: 190 | 191 | # Device event handlers registered generally will be triggered by any device events. 192 | cam.RegisterEvent(device_event_handler) 193 | 194 | print "Device event handler registered generally..." 195 | 196 | elif CHOSEN_EVENT == EventType.SPECIFIC: 197 | 198 | # Device event handlers registered to a specified event will only 199 | # be triggered by the type of event is it registered to. 200 | cam.RegisterEvent(device_event_handler, "EventExposureEnd") 201 | 202 | print "Device event handler registered specifically to EventExposureEnd events..." 203 | 204 | except PySpin.SpinnakerException as ex: 205 | print "Error: %s" % ex 206 | result = False 207 | 208 | return result, device_event_handler 209 | 210 | 211 | def reset_device_events(cam, device_event_handler): 212 | """ 213 | This function resets the example by unregistering the device event. 214 | 215 | :param cam: Camera to unregister event handler from. 216 | :param device_event_handler: Event handler for this example. 217 | :type cam: CameraPtr 218 | :type device_event_handler: DeviceEventHandler 219 | :return: True if successful, False otherwise. 220 | :rtype: bool 221 | """ 222 | try: 223 | result = True 224 | 225 | # Unregister device event 226 | # 227 | # *** NOTES *** 228 | # It is important to unregister all device events from all cameras that 229 | # they are registered to. 230 | cam.UnregisterEvent(device_event_handler) 231 | 232 | print "Device event handler unregistered...\n" 233 | 234 | except PySpin.SpinnakerException as ex: 235 | print "Error: %s" % ex 236 | result = False 237 | 238 | return result 239 | 240 | 241 | def print_device_info(nodemap): 242 | """ 243 | This function prints the device information of the camera from the transport 244 | layer; please see NodeMapInfo example for more in-depth comments on printing 245 | device information from the nodemap. 246 | 247 | :param nodemap: Transport layer device nodemap. 248 | :type nodemap: INodeMap 249 | :return: True if successful, False otherwise. 250 | :rtype: bool 251 | """ 252 | print "\n*** DEVICE INFORMATION ***\n" 253 | 254 | try: 255 | result = True 256 | node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) 257 | 258 | if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): 259 | features = node_device_information.GetFeatures() 260 | for feature in features: 261 | node_feature = PySpin.CValuePtr(feature) 262 | print "%s: %s" % (node_feature.GetName(), 263 | node_feature.ToString() if PySpin.IsReadable(node_feature) else "Node not readable") 264 | 265 | else: 266 | print "Device control information not available." 267 | 268 | except PySpin.SpinnakerException as ex: 269 | print "Error: %s" % ex.message 270 | return False 271 | 272 | return result 273 | 274 | 275 | def acquire_images(cam, nodemap, nodemap_tldevice): 276 | """ 277 | This function acquires and saves 10 images from a device; please see 278 | Acquisition example for more in-depth comments on acquiring images. 279 | 280 | :param cam: Camera to acquire images from. 281 | :param nodemap: Device nodemap. 282 | :param nodemap_tldevice: Transport layer device nodemap. 283 | :type cam: CameraPtr 284 | :type nodemap: INodeMap 285 | :type nodemap_tldevice: INodeMap 286 | :return: True if successful, False otherwise. 287 | :rtype: bool 288 | """ 289 | print "\n*** IMAGE ACQUISITION ***\n" 290 | try: 291 | result = True 292 | 293 | # Set acquisition mode to continuous 294 | node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode("AcquisitionMode")) 295 | if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): 296 | print "Unable to set acquisition mode to continuous (enum retrieval). Aborting...\n" 297 | return False 298 | 299 | # Retrieve entry node from enumeration node 300 | node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName("Continuous") 301 | if not PySpin.IsAvailable(node_acquisition_mode_continuous) \ 302 | or not PySpin.IsReadable(node_acquisition_mode_continuous): 303 | print "Unable to set acquisition mode to continuous (entry retrieval). Aborting...\n" 304 | return False 305 | 306 | acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() 307 | 308 | node_acquisition_mode.SetIntValue(acquisition_mode_continuous) 309 | 310 | print "Acquisition mode set to continuous..." 311 | 312 | # Begin acquiring images 313 | cam.BeginAcquisition() 314 | 315 | print "Acquiring images..." 316 | 317 | # Retrieve device serial number for filename 318 | node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode("DeviceSerialNumber")) 319 | if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): 320 | device_serial_number = node_device_serial_number.GetValue() 321 | print "Device serial number retrieved as %s..." % device_serial_number 322 | 323 | # Retrieve, convert, and save images 324 | for i in range(NUM_IMAGES): 325 | try: 326 | # Retrieve next received image and ensure image completion 327 | image_result = cam.GetNextImage() 328 | 329 | if image_result.IsIncomplete(): 330 | print "Image incomplete with image status %s..." % image_result.GetImageStatus() 331 | 332 | else: 333 | 334 | # Print image information 335 | width = image_result.GetWidth() 336 | height = image_result.GetHeight() 337 | print "Grabbed Image %i, width = %i, height = %i" % (i, width, height) 338 | 339 | # Convert to mono8 340 | image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) 341 | 342 | if device_serial_number: 343 | filename = "DeviceEvents-%s-%i.jpg" % (device_serial_number, i) 344 | else: 345 | filename = "DeviceEvents-%i.jpg" % i 346 | 347 | # Save image 348 | image_converted.Save(filename) 349 | print "Image saved at %s" % filename 350 | 351 | # Release image 352 | image_result.Release() 353 | print "" 354 | 355 | except PySpin.SpinnakerException as ex: 356 | print "Error: %s" % ex 357 | result = False 358 | 359 | cam.EndAcquisition() 360 | 361 | except PySpin.SpinnakerException as ex: 362 | print "Error: %s" % ex 363 | result = False 364 | 365 | return result 366 | 367 | 368 | def run_single_camera(cam): 369 | """ 370 | This function acts as the body of the example; please see NodeMapInfo example 371 | for more in-depth comments on setting up cameras. 372 | 373 | :param cam: Camera to setup and run on. 374 | :type cam: CameraPtr 375 | :return: True if successful, False otherwise. 376 | :rtype: bool 377 | """ 378 | try: 379 | result = True 380 | 381 | # Retrieve TL device nodemap and print device information 382 | nodemap_tldevice = cam.GetTLDeviceNodeMap() 383 | 384 | result &= print_device_info(nodemap_tldevice) 385 | 386 | # Initialize camera 387 | cam.Init() 388 | 389 | # Retrieve GenICam nodemap 390 | nodemap = cam.GetNodeMap() 391 | 392 | # Configure device events 393 | err, device_event_handler = configure_device_events(nodemap, cam) 394 | if not err: 395 | return err 396 | 397 | # Acquire images 398 | result &= acquire_images(cam, nodemap, nodemap_tldevice) 399 | 400 | # Reset device events 401 | result &= reset_device_events(cam, device_event_handler) 402 | 403 | # Deinitialize camera 404 | cam.DeInit() 405 | 406 | except PySpin.SpinnakerException as ex: 407 | print "Error: %s" % ex.message 408 | result = False 409 | 410 | return result 411 | 412 | 413 | def main(): 414 | """ 415 | Example entry point; please see Enumeration example for more in-depth 416 | comments on preparing and cleaning up the system. 417 | 418 | :return: True if successful, False otherwise. 419 | :rtype: bool 420 | """ 421 | # Retrieve singleton reference to system object 422 | system = PySpin.System.GetInstance() 423 | 424 | # Retrieve list of cameras from the system 425 | cam_list = system.GetCameras() 426 | 427 | num_cameras = cam_list.GetSize() 428 | 429 | print "Number of cameras detected: %d" % num_cameras 430 | 431 | # Finish if there are no cameras 432 | if num_cameras == 0: 433 | 434 | # Clear camera list before releasing system 435 | cam_list.Clear() 436 | 437 | # Release system 438 | system.ReleaseInstance() 439 | 440 | print "Not enough cameras!" 441 | raw_input("Done! Press Enter to exit...") 442 | return False 443 | 444 | # Run example on each camera 445 | for i in range(num_cameras): 446 | cam = cam_list.GetByIndex(i) 447 | 448 | print "Running example for camera %d..." % i 449 | 450 | result = run_single_camera(cam) 451 | print "Camera %d example complete..." % i 452 | 453 | # Release reference to camera 454 | # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically 455 | # cleaned up when going out of scope. 456 | del cam 457 | 458 | # Clear camera list before releasing system 459 | cam_list.Clear() 460 | 461 | # Release instance 462 | system.ReleaseInstance() 463 | 464 | raw_input("Done! Press Enter to exit...") 465 | return result 466 | 467 | if __name__ == "__main__": 468 | main() 469 | -------------------------------------------------------------------------------- /Enumeration.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # Enumeration.py shows how to enumerate interfaces and cameras. 20 | # Knowing this is mandatory for doing anything with the Spinnaker SDK, and is 21 | # therefore the best place to start learning how to use the SDK. 22 | # 23 | # This example introduces the preparation, use, and cleanup of the system 24 | # object, interface and camera lists, interfaces, and cameras. It also touches 25 | # on retrieving both nodes from nodemaps and information from nodes. 26 | # 27 | # Once comfortable with enumeration, we suggest checking out the Acquisition and/or 28 | # NodeMapInfo examples. Acquisition demonstrates using a camera to acquire images, 29 | # and NodeMapInfo demonstrates retrieving information from various node types. 30 | import pyspin 31 | from pyspin import PySpin 32 | 33 | 34 | def query_interface(interface): 35 | """ 36 | Queries an interface for its cameras and prints out device information. 37 | 38 | :param interface: InterfacePtr 39 | :return: True if successful, False otherwise. 40 | :rtype: bool 41 | """ 42 | 43 | try: 44 | result = True 45 | 46 | # Retrieve TL nodemap from interface 47 | # 48 | # *** NOTES *** 49 | # Each interface has a nodemap that can be retrieved in order to 50 | # access information about the interface itself, any devices 51 | # connected, or addressing information if applicable. 52 | nodemap_interface = interface.GetTLNodeMap() 53 | 54 | # Print interface display name 55 | # 56 | # *** NOTES *** 57 | # Grabbing node information requires first retrieving the node and 58 | # then retrieving its information. There are two things to keep in 59 | # mind. First, a node is distinguished by type, which is related 60 | # to its value's data type. Second, nodes should be checked for 61 | # availability and readability/writability prior to making an 62 | # attempt to read from or write to the node. 63 | # 64 | # Note that for Python, the node retrieved then has to be 'cast' 65 | # to the proper type (CStringPtr in this case) before it can be used. 66 | node_interface_display_name = PySpin.CStringPtr(nodemap_interface.GetNode("InterfaceDisplayName")) 67 | 68 | if PySpin.IsAvailable(node_interface_display_name) and PySpin.IsReadable(node_interface_display_name): 69 | interface_display_name = node_interface_display_name.GetValue() 70 | 71 | print interface_display_name 72 | 73 | else: 74 | print "Interface display name not readable" 75 | 76 | # Update list of cameras on the interface 77 | # 78 | # *** NOTES *** 79 | # Updating the cameras on each interface is especially important if 80 | # there has been any device arrivals or removals since the last time 81 | # that UpdateCameras() was called. 82 | interface.UpdateCameras() 83 | 84 | # Retrieve list of cameras from the interface 85 | # 86 | # *** NOTES *** 87 | # Camera lists can be retrieved from an interface or the system object. 88 | # Camera lists retrieved from an interface, such as this one, only 89 | # return cameras attached on that specific interface whereas camera 90 | # lists retrieved from the system will return all cameras on all 91 | # interfaces. 92 | # 93 | # *** LATER *** 94 | # Camera lists must be cleared manually. This must be done prior to 95 | # releasing the system and while the camera list is still in scope. 96 | cam_list = interface.GetCameras() 97 | 98 | # Retrieve number of cameras 99 | num_cams = cam_list.GetSize() 100 | 101 | # Return if no cameras detected 102 | if num_cams == 0: 103 | print "\tNo devices detected.\n" 104 | return result 105 | 106 | # Print device vendor and model name for each camera on the interface 107 | for i in range(num_cams): 108 | 109 | # Select camera 110 | # 111 | # *** NOTES *** 112 | # Each camera is retrieved from a camera list with an index. If 113 | # the index is out of range, an exception is thrown. 114 | cam = cam_list[i] 115 | 116 | # Retrieve TL device nodemap; please see NodeMapInfo example for 117 | # additional comments on transport layer nodemaps 118 | nodemap_tldevice = cam.GetTLDeviceNodeMap() 119 | 120 | # Print device vendor name and device model name 121 | # 122 | # *** NOTES *** 123 | # Grabbing node information requires first retrieving the node and 124 | # then retrieving its information. There are two things to keep in 125 | # mind. First, a node is distinguished by type, which is related 126 | # to its value's data type. Second, nodes should be checked for 127 | # availability and readability/writability prior to making an 128 | # attempt to read from or write to the node. 129 | node_device_vendor_name = PySpin.CStringPtr(nodemap_tldevice.GetNode("DeviceVendorName")) 130 | 131 | if PySpin.IsAvailable(node_device_vendor_name) and PySpin.IsReadable(node_device_vendor_name): 132 | device_vendor_name = node_device_vendor_name.ToString() 133 | 134 | node_device_model_name = PySpin.CStringPtr(nodemap_tldevice.GetNode("DeviceModelName")) 135 | 136 | if PySpin.IsAvailable(node_device_model_name) and PySpin.IsReadable(node_device_model_name): 137 | device_model_name = node_device_model_name.ToString() 138 | 139 | print "\tDevice %i %s %s \n" % (i, device_vendor_name, device_model_name) 140 | 141 | # Clear camera list before losing scope 142 | # 143 | # *** NOTES *** 144 | # Camera lists (and interface lists) must be cleared manually while in 145 | # the same scope that the system is released. However, in cases like this 146 | # where scope is lost, camera lists (and interface lists) will be cleared 147 | # automatically. 148 | cam_list.Clear() 149 | 150 | except PySpin.SpinnakerException as ex: 151 | print "Error: %s" % ex 152 | result = False 153 | 154 | return result 155 | 156 | 157 | def main(): 158 | """ 159 | Example entry point. 160 | :return: True if successful, False otherwise. 161 | :rtype: bool 162 | """ 163 | result = True 164 | 165 | # Retrieve singleton reference to system object 166 | # 167 | # *** NOTES *** 168 | # Everything originates with the system object. It is important to notice 169 | # that it has a singleton implementation, so it is impossible to have 170 | # multiple system objects at the same time. Users can only get a smart 171 | # pointer (SystemPtr) to the system instance. 172 | # 173 | # *** LATER *** 174 | # The system object should be cleared prior to program completion. If not 175 | # released explicitly, it will be released automatically when all SystemPtr 176 | # objects that point to the system go out of scope. 177 | system = PySpin.System.GetInstance() 178 | 179 | # Retrieve list of interfaces from the system 180 | # 181 | # *** NOTES *** 182 | # Interface lists are retrieved from the system object. 183 | # 184 | # *** LATER *** 185 | # Interface lists must be cleared manually. This must be done prior to 186 | # releasing the system and while the interface list is still in scope. 187 | interface_list = system.GetInterfaces() 188 | 189 | # Get number of interfaces 190 | num_interfaces = interface_list.GetSize() 191 | 192 | print "Number of interfaces detected: %i" % num_interfaces 193 | 194 | # Retrieve list of cameras from the system 195 | # 196 | # *** NOTES *** 197 | # Camera lists can be retrieved from an interface or the system object. 198 | # Camera lists retrieved from the system, such as this one, return all 199 | # cameras available on the system. 200 | # 201 | # *** LATER *** 202 | # Camera lists must be cleared manually. This must be done prior to 203 | # releasing the system and while the camera list is still in scope. 204 | cam_list = system.GetCameras() 205 | 206 | num_cams = cam_list.GetSize() 207 | 208 | print "Number of cameras detected: %i" % num_cams 209 | 210 | # Finish if there are no cameras 211 | if num_cams == 0 or num_interfaces == 0: 212 | 213 | # Clear camera list before releasing system 214 | cam_list.Clear() 215 | 216 | # Clear interface list before releasing system 217 | interface_list.Clear() 218 | 219 | # Release system 220 | system.ReleaseInstance() 221 | 222 | print "Not enough cameras!" 223 | raw_input("Done! Press Enter to exit...") 224 | 225 | print "\n*** QUERYING INTERFACES ***\n" 226 | 227 | for i in range(num_interfaces): 228 | 229 | # Select interface 230 | # 231 | # *** LATER *** 232 | # Interfaces have to be manually deleted before the system gets released. 233 | # Unlike C++, the interface will not be destroyed when it goes out of the scope of this for loop; 234 | # instead, it gets garbage-collected at the end of main(). 235 | interface = interface_list[i] 236 | 237 | # Query interface 238 | result &= query_interface(interface) 239 | 240 | # Release interface 241 | del interface 242 | 243 | # Clear camera list before releasing system 244 | # 245 | # *** NOTES *** 246 | # Camera lists must be cleared manually prior to a system release call. 247 | cam_list.Clear() 248 | 249 | # Clear interface list before releasing system 250 | # 251 | # *** NOTES *** 252 | # Interface lists must be cleared manually prior to a system release call. 253 | interface_list.Clear() 254 | 255 | # Release system 256 | # 257 | # *** NOTES *** 258 | # The system should be released, but if it is not, it will do so itself. 259 | # It is often at the release of the system (whether manual or automatic) 260 | # that unreleased resources and still-registered events will throw an 261 | # exception. 262 | system.ReleaseInstance() 263 | 264 | raw_input("Done! Press Enter to exit...") 265 | 266 | if __name__ == "__main__": 267 | main() 268 | -------------------------------------------------------------------------------- /EnumerationEvents.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # EnumerationEvents.py explores arrival and removal events on interfaces and the system. 20 | # It relies on information provided in the Enumeration, Acquisition, and NodeMapInfo examples. 21 | # 22 | # It can also be helpful to familiarize yourself with the NodeMapCallback example, 23 | # as nodemap callbacks follow the same general procedure as events, but with a few less steps. 24 | # 25 | # This example creates two user-defined classes: InterfaceEventHandler and SystemEventHandler. 26 | # These child classes allow the user to define properties, parameters, and the event itself 27 | # while the parent classes - ArrivalEvent, RemovalEvent, and InterfaceEvent - 28 | # allow the child classes to interface with Spinnaker. 29 | 30 | import PySpin 31 | 32 | 33 | class InterfaceEventHandler(PySpin.InterfaceEvent): 34 | """ 35 | This class defines the properties and methods for device arrivals and removals 36 | on an interface. Take special note of the signatures of the OnDeviceArrival() 37 | and OnDeviceRemoval() methods. Also, enumeration events must inherit from 38 | InterfaceEvent whether they are to be registered to the system or an interface. 39 | """ 40 | def __init__(self, iface, iface_num): 41 | """ 42 | Constructor. Note that this sets the interface instance. 43 | 44 | :param iface: Interface instance. 45 | :param iface_num: Interface number. 46 | """ 47 | super(InterfaceEventHandler, self).__init__() 48 | self.interface = iface 49 | self.interface_num = iface_num 50 | 51 | def OnDeviceArrival(self, serial_number): 52 | """ 53 | This method defines the arrival event on an interface. It prints out 54 | the device serial number of the camera arriving and the interface 55 | number. The argument is the serial number of the camera that triggered 56 | the arrival event. 57 | 58 | :param serial_number: gcstring representing the device serial number of arriving camera 59 | :type serial_number: gcstring 60 | :return: None 61 | """ 62 | print "Interface event handler:" 63 | print "\tDevice %i has arrived on interface %i." % (serial_number, self.interface_num) 64 | 65 | def OnDeviceRemoval(self, serial_number): 66 | """ 67 | This method defines removal events on an interface. It prints out the 68 | device serial number of the camera being removed and the interface 69 | number. The argument is the serial number of the camera that triggered 70 | the removal event. 71 | 72 | :param serial_number: gcstring representing the device serial number of removed camera 73 | :type serial_number: gcstring 74 | :return: None 75 | """ 76 | print "Interface event handler:" 77 | print "\tDevice %i was removed from interface %i." % (serial_number, self.interface_num) 78 | 79 | 80 | class SystemEventHandler(PySpin.InterfaceEvent): 81 | """ 82 | In the C++ example, the SystemEventHandler inherits from both ArrivalEvent and 83 | RemovalEvent. This doesn't work for this wrapper, as it will only inherit the abstract 84 | method from the first base class listed, so for this example both System and Interface 85 | event handlers inherit from InterfaceEvent. 86 | All three event types - ArrivalEvent, RemovalEvent, and InterfaceEvent - can be 87 | registered to interfaces, the system, or both. 88 | """ 89 | def __init__(self, system): 90 | """ 91 | Constructor. This sets the system instance. 92 | 93 | :param system: Instance of the system. 94 | :type system: SystemPtr 95 | :rtype: None 96 | """ 97 | super(SystemEventHandler, self).__init__() 98 | self.system = system 99 | 100 | def OnDeviceArrival(self, serial_number): 101 | """ 102 | This method defines the arrival event on the system. It retrieves the 103 | number of cameras currently connected and prints it out. 104 | 105 | :param serial_number: gcstring representing the serial number of the arriving camera. 106 | :type serial_number: gcstring 107 | :return: None 108 | """ 109 | cam_list = self.system.GetCameras() 110 | count = cam_list.GetSize() 111 | print "System event handler:" 112 | print "\tThere %s %i %s on the system." % ("is" if count == 1 else "are", 113 | count, 114 | "device" if count == 1 else "devices") 115 | 116 | def OnDeviceRemoval(self, serial_number): 117 | """ 118 | This method defines the removal event on the system. It does the same 119 | as the system arrival event - it retrieves the number of cameras 120 | currently connected and prints it out. 121 | 122 | :param serial_number: gcstring representing the serial number of the removed camera. 123 | :type serial_number: gcstring 124 | :return: None 125 | """ 126 | cam_list = self.system.GetCameras() 127 | count = cam_list.GetSize() 128 | print "System event handler:" 129 | print "\tThere %s %i %s on the system." % ("is" if count == 1 else "are", 130 | count, 131 | "device" if count == 1 else "devices") 132 | 133 | 134 | def main(): 135 | """ 136 | Example entry point; please see Enumeration example for more in-depth 137 | comments on preparing and cleaning up the system. 138 | 139 | :rtype: None 140 | """ 141 | # Retrieve singleton reference to system object 142 | system = PySpin.System.GetInstance() 143 | 144 | # Retrieve list of cameras from the system 145 | cam_list = system.GetCameras() 146 | 147 | num_cams = cam_list.GetSize() 148 | 149 | print "Number of cameras detected: %i" % num_cams 150 | 151 | # Retrieve list of interfaces from the system 152 | interface_list = system.GetInterfaces() 153 | 154 | num_ifaces = interface_list.GetSize() 155 | 156 | print "Number of interfaces detected: %i" % num_ifaces 157 | 158 | print "*** CONFIGURING ENUMERATION EVENTS *** \n" 159 | 160 | # Create interface event for the system 161 | # 162 | # *** NOTES *** 163 | # The SystemEventHandler has been constructed to accept a system object in 164 | # order to print the number of cameras on the system. 165 | system_event_handler = SystemEventHandler(system) 166 | 167 | # Register interface event for the system 168 | # 169 | # *** NOTES *** 170 | # Arrival, removal, and interface events can all be registered to 171 | # interfaces or the system. Do not think that interface events can only be 172 | # registered to an interface. An interface event is merely a combination 173 | # of an arrival and a removal event. 174 | # 175 | # *** LATER *** 176 | # Arrival, removal, and interface events must all be unregistered manually. 177 | # This must be done prior to releasing the system and while they are still 178 | # in scope. 179 | system.RegisterInterfaceEvent(system_event_handler) 180 | 181 | # Create and register interface event to each interface 182 | # 183 | # *** NOTES *** 184 | # The process of event creation and registration on interfaces is similar 185 | # to the process of event creation and registration on the system. The 186 | # class for interfaces has been constructed to accept an interface and an 187 | # interface number (this is just to separate the interfaces). 188 | # 189 | # *** LATER *** 190 | # Arrival, removal, and interface events must all be unregistered manually. 191 | # This must be done prior to releasing the system and while they are still 192 | # in scope. 193 | interface_events = [] 194 | 195 | for i in range(num_ifaces): 196 | 197 | # Select interface 198 | iface = interface_list[i] 199 | 200 | # Create interface event 201 | iface_event_handler = InterfaceEventHandler(iface, i) 202 | interface_events.append(iface_event_handler) 203 | 204 | # Register interface event 205 | iface.RegisterEvent(interface_events[i]) 206 | 207 | print "Event handler registered to interface %i ..." % i 208 | 209 | # Delete references to interface 210 | del iface 211 | del iface_event_handler 212 | 213 | # Wait for user to plug in and/or remove camera devices 214 | raw_input("\nReady! Remove/Plug in cameras to test or press Enter to exit...\n") 215 | 216 | # Unregister interface event from each interface 217 | # 218 | # *** NOTES *** 219 | # It is important to unregister all arrival, removal, and interface events 220 | # from all interfaces that they may be registered to. 221 | for i in range(num_ifaces): 222 | interface_list[i].UnregisterEvent(interface_events[i]) 223 | 224 | # Delete all interface events, which each have a reference to an interface 225 | del interface_events 226 | print "Event handler unregistered from interfaces..." 227 | 228 | # Unregister system event from system object 229 | # 230 | # *** NOTES *** 231 | # It is important to unregister all arrival, removal, and interface events 232 | # registered to the system. 233 | system.UnregisterInterfaceEvent(system_event_handler) 234 | 235 | # Delete system event, which has a system reference 236 | del system_event_handler 237 | print "Event handler unregistered from system..." 238 | 239 | # Clear camera list before releasing system 240 | cam_list.Clear() 241 | 242 | # Clear interface list before releasing system 243 | interface_list.Clear() 244 | 245 | # Release system 246 | system.ReleaseInstance() 247 | 248 | raw_input("Done! Press Enter to exit...") 249 | 250 | if __name__ == "__main__": 251 | main() 252 | -------------------------------------------------------------------------------- /Enumeration_QuickSpin.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # Enumeration_QuickSpin.py shows how to enumerate interfaces 20 | # and cameras using the QuickSpin API. QuickSpin is a subset of the Spinnaker 21 | # library that allows for simpler node access and control. This is a great 22 | # example to start learning about QuickSpin. 23 | # 24 | # This example introduces the preparation, use, and cleanup of the system 25 | # object, interface and camera lists, interfaces, and cameras. It also 26 | # touches on retrieving information from pre-fetched nodes using QuickSpin. 27 | # Retrieving node information is the only portion of the example that 28 | # differs from Enumeration. 29 | # 30 | # A much wider range of topics is covered in the full Spinnaker examples than 31 | # in the QuickSpin ones. There are only enough QuickSpin examples to 32 | # demonstrate node access and to get started with the API; please see full 33 | # Spinnaker examples for further or specific knowledge on a topic. 34 | 35 | import PySpin 36 | 37 | 38 | def query_interface(interface): 39 | """ 40 | Queries an interface for its cameras and prints out device information. 41 | 42 | :param interface: InterfacePtr 43 | :return: True if successful, False otherwise. 44 | :rtype: bool 45 | """ 46 | 47 | try: 48 | result = True 49 | 50 | # Print interface display name 51 | # 52 | # *** NOTES *** 53 | # QuickSpin allows for the retrieval of interface information directly 54 | # from an interface. Because interface information is made available 55 | # on the transport layer, camera initialization is not required. 56 | node_interface_display_name = interface.TLInterface.InterfaceDisplayName 57 | if PySpin.IsAvailable(node_interface_display_name) and PySpin.IsReadable(node_interface_display_name): 58 | 59 | interface_display_name = node_interface_display_name.GetValue() 60 | 61 | print interface_display_name 62 | 63 | else: 64 | print "Interface display name not readable" 65 | 66 | # Update list of cameras on the interface 67 | # 68 | # *** NOTES *** 69 | # Updating the cameras on each interface is especially important if 70 | # there has been any device arrivals or removals since the last time 71 | # that UpdateCameras() was called. 72 | interface.UpdateCameras() 73 | 74 | # Retrieve list of cameras from the interface 75 | # 76 | # *** NOTES *** 77 | # Camera lists can be retrieved from an interface or the system object. 78 | # Camera lists retrieved from an interface, such as this one, only 79 | # return cameras attached on that specific interface whereas camera 80 | # lists retrieved from the system will return all cameras on all 81 | # interfaces. 82 | # 83 | # *** LATER *** 84 | # Camera lists must be cleared manually. This must be done prior to 85 | # releasing the system and while the camera list is still in scope. 86 | cam_list = interface.GetCameras() 87 | 88 | # Retrieve number of cameras 89 | num_cams = cam_list.GetSize() 90 | 91 | # Return if no cameras detected 92 | if num_cams == 0: 93 | print "\tNo devices detected.\n" 94 | return True 95 | 96 | # Print device vendor and model name for each camera on the interface 97 | for i in range(num_cams): 98 | 99 | # Select camera 100 | # 101 | # *** NOTES *** 102 | # Each camera is retrieved from a camera list with an index. If 103 | # the index is out of range, an exception is thrown. 104 | cam = cam_list[i] 105 | 106 | # Print device vendor name and device model name 107 | # 108 | # *** NOTES *** 109 | # In QuickSpin, accessing nodes does not require first retrieving a 110 | # nodemap. Instead, GenICam nodes are made available 111 | # directly through the camera, and transport layer nodes are made 112 | # available through the camera's TLDevice and TLStream properties. 113 | # 114 | # Most camera interaction happens through the GenICam nodemap, which 115 | # requires the device to be initialized. Simpler reads, like the 116 | # ones below, can often be accomplished at the transport layer, 117 | # which does not require initialization; please see 118 | # NodeMapInfo_QuickSpin for additional information on this topic. 119 | # 120 | # Readability/writability should be checked prior to interacting with 121 | # nodes. Readability and writability are ensured by checking the 122 | # access mode or by using the methods 123 | if cam.TLDevice.DeviceVendorName.GetAccessMode() == PySpin.RO: 124 | device_vendor_name = cam.TLDevice.DeviceVendorName.ToString() 125 | 126 | if cam.TLDevice.DeviceModelName.GetAccessMode() == PySpin.RO: 127 | device_model_name = cam.TLDevice.DeviceModelName.GetValue() 128 | 129 | print "\tDevice %i %s %s \n" % (i, device_vendor_name, device_model_name) 130 | 131 | # Clear camera list before losing scope 132 | # 133 | # *** NOTES *** 134 | # Camera lists (and interface lists) must be cleared manually while in 135 | # the same scope that the system is released. However, in cases like this 136 | # where scope is lost, camera lists (and interface lists) will be cleared 137 | cam_list.Clear() 138 | 139 | except PySpin.SpinnakerException as ex: 140 | print "Error: %s" % ex 141 | result = False 142 | 143 | return result 144 | 145 | 146 | def main(): 147 | """ 148 | Example entry point. 149 | :return: True if successful, False otherwise. 150 | :rtype: bool 151 | """ 152 | result = True 153 | 154 | # Retrieve singleton reference to system object 155 | # 156 | # *** NOTES *** 157 | # Everything originates with the system object. It is important to notice 158 | # that it has a singleton implementation, so it is impossible to have 159 | # multiple system objects at the same time. Users can only get a smart 160 | # pointer (SystemPtr) to the system instance. 161 | # 162 | # *** LATER *** 163 | # The system object should be cleared prior to program completion. If not 164 | # released explicitly, it will be released automatically when all SystemPtr 165 | # objects that point to the system go out of scope. 166 | system = PySpin.System.GetInstance() 167 | 168 | # Retrieve list of interfaces from the system 169 | # 170 | # *** NOTES *** 171 | # Interface lists are retrieved from the system object. 172 | # 173 | # *** LATER *** 174 | # Interface lists must be cleared manually. This must be done prior to 175 | # releasing the system and while the interface list is still in scope. 176 | interface_list = system.GetInterfaces() 177 | 178 | # Get number of interfaces 179 | num_interfaces = interface_list.GetSize() 180 | 181 | print "Number of interfaces detected: %i" % num_interfaces 182 | 183 | # Retrieve list of cameras from the system 184 | # 185 | # *** NOTES *** 186 | # Camera lists can be retrieved from an interface or the system object. 187 | # Camera lists retrieved from the system, such as this one, return all 188 | # cameras available on the system. 189 | # 190 | # *** LATER *** 191 | # Camera lists must be cleared manually. This must be done prior to 192 | # releasing the system and while the camera list is still in scope. 193 | cam_list = system.GetCameras() 194 | 195 | num_cams = cam_list.GetSize() 196 | 197 | print "Number of cameras detected: %i" % num_cams 198 | 199 | # Finish if there are no cameras 200 | if num_cams == 0 or num_interfaces == 0: 201 | 202 | # Clear camera list before releasing system 203 | cam_list.Clear() 204 | 205 | # Clear interface list before releasing system 206 | interface_list.Clear() 207 | 208 | # Release system 209 | system.ReleaseInstance() 210 | 211 | print "Not enough cameras!" 212 | raw_input("Done! Press Enter to exit...") 213 | 214 | print "\n*** QUERYING INTERFACES ***\n" 215 | 216 | for i in range(num_interfaces): 217 | 218 | # Select interface 219 | # 220 | # *** LATER *** 221 | # Interfaces have to be manually deleted before the system gets released. 222 | # Unlike C++, the interface will not be destroyed when it goes out of the scope of this for loop; 223 | # instead, it gets garbage-collected at the end of main(). 224 | interface = interface_list[i] 225 | 226 | # Query interface 227 | result &= query_interface(interface) 228 | 229 | # Release interface 230 | del interface 231 | 232 | # Clear camera list before releasing system 233 | # 234 | # *** NOTES *** 235 | # Camera lists must be cleared manually prior to a system release call. 236 | cam_list.Clear() 237 | 238 | # Clear interface list before releasing system 239 | # 240 | # *** NOTES *** 241 | # Interface lists must be cleared manually prior to a system release call. 242 | interface_list.Clear() 243 | 244 | # Release system 245 | # 246 | # *** NOTES *** 247 | # The system should be released, but if it is not, it will do so itself. 248 | # It is often at the release of the system (whether manual or automatic) 249 | # that unreleased resources and still registered events will throw an 250 | # exception. 251 | system.ReleaseInstance() 252 | 253 | raw_input("Done! Press Enter to exit...") 254 | 255 | if __name__ == "__main__": 256 | main() -------------------------------------------------------------------------------- /Exposure_QuickSpin.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # Exposure_QuickSpin.py shows how to customize image exposure time 20 | # using the QuickSpin API. QuickSpin is a subset of the Spinnaker library 21 | # that allows for simpler node access and control. 22 | # 23 | # This example prepares the camera, sets a new exposure time, and restores 24 | # the camera to its default state. Ensuring custom values fall within an 25 | # acceptable range is also touched on. Retrieving and setting information 26 | # is the only portion of the example that differs from Exposure. 27 | # 28 | # A much wider range of topics is covered in the full Spinnaker examples than 29 | # in the QuickSpin ones. There are only enough QuickSpin examples to 30 | # demonstrate node access and to get started with the API; please see full 31 | # Spinnaker examples for further or specific knowledge on a topic. 32 | 33 | import PySpin 34 | 35 | NUM_IMAGES = 5 # number of images to save 36 | 37 | 38 | def configure_exposure(cam): 39 | """ 40 | This function configures a custom exposure time. Automatic exposure is turned 41 | off in order to allow for the customization, and then the custom setting is 42 | applied. 43 | 44 | :param cam: Camera to configure exposure for. 45 | :type cam: CameraPtr 46 | :return: True if successful, False otherwise. 47 | :rtype: bool 48 | """ 49 | 50 | print "*** CONFIGURING EXPOSURE ***\n" 51 | 52 | try: 53 | result = True 54 | 55 | # Turn off automatic exposure mode 56 | # 57 | # *** NOTES *** 58 | # Automatic exposure prevents the manual configuration of exposure 59 | # times and needs to be turned off for this example. Enumerations 60 | # representing entry nodes have been added to QuickSpin. This allows 61 | # for the much easier setting of enumeration nodes to new values. 62 | # 63 | # The naming convention of QuickSpin enums is the name of the 64 | # enumeration node followed by an underscore and the symbolic of 65 | # the entry node. Selecting "Off" on the "ExposureAuto" node is 66 | # thus named "ExposureAuto_Off". 67 | # 68 | # *** LATER *** 69 | # Exposure time can be set automatically or manually as needed. This 70 | # example turns automatic exposure off to set it manually and back 71 | # on to return the camera to its default state. 72 | 73 | if cam.ExposureAuto.GetAccessMode() != PySpin.RW: 74 | print "Unable to disable automatic exposure. Aborting..." 75 | return False 76 | 77 | cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Off) 78 | print "Automatic exposure disabled..." 79 | 80 | # Set exposure time manually; exposure time recorded in microseconds 81 | # 82 | # *** NOTES *** 83 | # Notice that the node is checked for availability and writability 84 | # prior to the setting of the node. In QuickSpin, availability and 85 | # writability are ensured by checking the access mode. 86 | # 87 | # Further, it is ensured that the desired exposure time does not exceed 88 | # the maximum. Exposure time is counted in microseconds - this can be 89 | # found out either by retrieving the unit with the GetUnit() method or 90 | # by checking SpinView. 91 | 92 | if cam.ExposureTime.GetAccessMode() != PySpin.RW: 93 | print "Unable to set exposure time. Aborting..." 94 | return False 95 | 96 | # Ensure desired exposure time does not exceed the maximum 97 | exposure_time_to_set = 2000000.0 98 | exposure_time_to_set = min(cam.ExposureTime.GetMax(), exposure_time_to_set) 99 | cam.ExposureTime.SetValue(exposure_time_to_set) 100 | 101 | except PySpin.SpinnakerException as ex: 102 | print "Error: %s" % ex 103 | result = False 104 | 105 | return result 106 | 107 | 108 | def reset_exposure(cam): 109 | """ 110 | This function returns the camera to a normal state by re-enabling automatic exposure. 111 | 112 | :param cam: Camera to reset exposure on. 113 | :type cam: CameraPtr 114 | :return: True if successful, False otherwise. 115 | :rtype: bool 116 | """ 117 | try: 118 | result = True 119 | 120 | # Turn automatic exposure back on 121 | # 122 | # *** NOTES *** 123 | # Automatic exposure is turned on in order to return the camera to its 124 | # default state. 125 | 126 | if cam.ExposureAuto.GetAccessMode() != PySpin.RW: 127 | print "Unable to enable automatic exposure (node retrieval). Non-fatal error..." 128 | return False 129 | 130 | cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Continuous) 131 | 132 | print "Automatic exposure enabled..." 133 | 134 | except PySpin.SpinnakerException as ex: 135 | print "Error: %s" % ex 136 | result = False 137 | 138 | return result 139 | 140 | 141 | def print_device_info(cam): 142 | """ 143 | This function prints the device information of the camera from the transport 144 | layer; please see NodeMapInfo example for more in-depth comments on printing 145 | device information from the nodemap. 146 | 147 | :param cam: Camera to get device information from. 148 | :type cam: CameraPtr 149 | :return: True if successful, False otherwise. 150 | :rtype: bool 151 | """ 152 | 153 | print "*** DEVICE INFORMATION ***\n" 154 | 155 | try: 156 | result = True 157 | nodemap = cam.GetTLDeviceNodeMap() 158 | 159 | node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) 160 | 161 | if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): 162 | features = node_device_information.GetFeatures() 163 | for feature in features: 164 | node_feature = PySpin.CValuePtr(feature) 165 | print "%s: %s" % (node_feature.GetName(), 166 | node_feature.ToString() if PySpin.IsReadable(node_feature) else "Node not readable") 167 | 168 | else: 169 | print "Device control information not available." 170 | 171 | except PySpin.SpinnakerException as ex: 172 | print "Error: %s" % ex.message 173 | return False 174 | 175 | return result 176 | 177 | 178 | def acquire_images(cam): 179 | """ 180 | This function acquires and saves 10 images from a device; please see 181 | Acquisition example for more in-depth comments on the acquisition of images. 182 | 183 | :param cam: Camera to acquire images from. 184 | :type cam: CameraPtr 185 | :return: True if successful, False otherwise. 186 | :rtype: bool 187 | """ 188 | print "*** IMAGE ACQUISITION ***" 189 | 190 | try: 191 | result = True 192 | 193 | # Set acquisition mode to continuous 194 | if cam.AcquisitionMode.GetAccessMode() != PySpin.RW: 195 | print "Unable to set acquisition mode to continuous. Aborting..." 196 | return False 197 | 198 | cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous) 199 | print "Acquisition mode set to continuous..." 200 | 201 | # Begin acquiring images 202 | cam.BeginAcquisition() 203 | 204 | print "Acquiring images..." 205 | 206 | # Get device serial number for filename 207 | device_serial_number = "" 208 | if cam.TLDevice.DeviceSerialNumber is not None and cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: 209 | device_serial_number = cam.TLDevice.DeviceSerialNumber.GetValue() 210 | 211 | print "Device serial number retrieved as %s..." % device_serial_number 212 | 213 | # Retrieve, convert, and save images 214 | for i in range(NUM_IMAGES): 215 | 216 | try: 217 | # Retrieve next received image and ensure image completion 218 | image_result = cam.GetNextImage() 219 | 220 | if image_result.IsIncomplete(): 221 | print "Image incomplete with image status %d..." % image_result.GetImageStatus() 222 | 223 | else: 224 | # Print image information 225 | width = image_result.GetWidth() 226 | height = image_result.GetHeight() 227 | print "Grabbed Image %d, width = %d, height = %d" % (i, width, height) 228 | 229 | # Convert image to Mono8 230 | image_converted = image_result.Convert(PySpin.PixelFormat_Mono8) 231 | 232 | # Create a unique filename 233 | filename = "ExposureQS-%s-%d.jpg" % (device_serial_number, i) 234 | 235 | # Save image 236 | image_converted.Save(filename) 237 | 238 | print "Image saved at %s" % filename 239 | 240 | # Release image 241 | image_result.Release() 242 | 243 | except PySpin.SpinnakerException as ex: 244 | print "Error: %s" % ex 245 | result = False 246 | 247 | # End acquisition 248 | cam.EndAcquisition() 249 | 250 | except PySpin.SpinnakerException as ex: 251 | print "Error: %s" % ex 252 | result = False 253 | 254 | return result 255 | 256 | 257 | def run_single_camera(cam): 258 | """ 259 | This function acts as the body of the example; please see NodeMapInfo_QuickSpin example for more 260 | in-depth comments on setting up cameras. 261 | 262 | :param cam: Camera to run example on. 263 | :type cam: CameraPtr 264 | :return: True if successful, False otherwise. 265 | :rtype: bool 266 | """ 267 | try: 268 | # Initialize camera 269 | cam.Init() 270 | 271 | # Print device info 272 | result = print_device_info(cam) 273 | 274 | # Configure exposure 275 | if not configure_exposure(cam): 276 | return False 277 | 278 | # Acquire images 279 | result &= acquire_images(cam) 280 | 281 | # Reset exposure 282 | result &= reset_exposure(cam) 283 | 284 | # Deinitialize camera 285 | cam.DeInit() 286 | 287 | return result 288 | 289 | except PySpin.SpinnakerException as ex: 290 | print "Error: %s" % ex 291 | return False 292 | 293 | 294 | def main(): 295 | """ 296 | Example entry point; please see Enumeration_QuickSpin example for more 297 | in-depth comments on preparing and cleaning up the system. 298 | 299 | :return: True if successful, False otherwise. 300 | :rtype: bool 301 | """ 302 | # Retrieve singleton reference to system object 303 | system = PySpin.System.GetInstance() 304 | 305 | # Retrieve list of cameras from the system 306 | cam_list = system.GetCameras() 307 | 308 | num_cameras = cam_list.GetSize() 309 | 310 | print "Number of cameras detected: %d" % num_cameras 311 | 312 | # Finish if there are no cameras 313 | if num_cameras == 0: 314 | # Clear camera list before releasing system 315 | cam_list.Clear() 316 | 317 | # Release system 318 | system.ReleaseInstance() 319 | 320 | print "Not enough cameras!" 321 | raw_input("Done! Press Enter to exit...") 322 | return False 323 | 324 | # Release example on each camera 325 | for i in range(num_cameras): 326 | print "Running example for camera %d..." % i 327 | 328 | result = run_single_camera(cam_list.GetByIndex(i)) 329 | 330 | print "Camera %d example complete..." % i 331 | 332 | # Clear camera list before releasing system 333 | cam_list.Clear() 334 | 335 | # Release system 336 | system.ReleaseInstance() 337 | 338 | raw_input("Done! Press Enter to exit...") 339 | return result 340 | 341 | if __name__ == "__main__": 342 | main() 343 | -------------------------------------------------------------------------------- /ImageChannelStatistics.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # ImageChannelStatisitcs.py shows how to get the image data and channel statistics, and then saves / displays them. 20 | # This example relies on information provided in the Acquisition examples. 21 | # 22 | # This example demonstrates how to visualize the image histogram using Python, and display an image represented as 23 | # a numpy array. 24 | 25 | import PySpin 26 | import matplotlib.pyplot as plt 27 | 28 | NUM_IMAGES = 10 # number of images to grab 29 | 30 | 31 | def acquire_and_display_images(cam, nodemap, nodemap_tldevice): 32 | """ 33 | This function acquires and displays the channel statistics of N images from a device. 34 | 35 | :param cam: Camera to acquire images from. 36 | :param nodemap: Device nodemap. 37 | :param nodemap_tldevice: Transport layer device nodemap. 38 | :type cam: CameraPtr 39 | :type nodemap: INodeMap 40 | :type nodemap_tldevice: INodeMap 41 | :return: True if successful, False otherwise. 42 | :rtype: bool 43 | """ 44 | 45 | print "*** IMAGE ACQUISITION ***\n" 46 | try: 47 | result = True 48 | 49 | node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode("AcquisitionMode")) 50 | if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): 51 | print "Unable to set acquisition mode to continuous (enum retrieval). Aborting..." 52 | return False 53 | 54 | # Retrieve entry node from enumeration node 55 | node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName("Continuous") 56 | if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( 57 | node_acquisition_mode_continuous): 58 | print "Unable to set acquisition mode to continuous (entry retrieval). Aborting..." 59 | return False 60 | 61 | # Retrieve integer value from entry node 62 | acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() 63 | 64 | # Set integer value from entry node as new value of enumeration node 65 | node_acquisition_mode.SetIntValue(acquisition_mode_continuous) 66 | 67 | print "Acquisition mode set to continuous..." 68 | 69 | node_pixel_format = PySpin.CEnumerationPtr(nodemap.GetNode("PixelFormat")) 70 | if not PySpin.IsAvailable(node_pixel_format) or not PySpin.IsWritable(node_pixel_format): 71 | print "Unable to set Pixel Format. Aborting..." 72 | return False 73 | 74 | else: 75 | # Retrieve entry node from enumeration node 76 | node_pixel_format_mono8 = PySpin.CEnumEntryPtr(node_pixel_format.GetEntryByName("Mono8")) 77 | if not PySpin.IsAvailable(node_pixel_format_mono8) or not PySpin.IsReadable(node_pixel_format_mono8): 78 | print "Unable to set Pixel Format to MONO8. Aborting..." 79 | return False 80 | 81 | # Retrieve integer value from entry node 82 | pixel_format_mono8 = node_pixel_format_mono8.GetValue() 83 | 84 | # Set integer value from entry node as new value of enumeration node 85 | node_pixel_format.SetIntValue(pixel_format_mono8) 86 | 87 | print "Pixel Format set to MONO8 ..." 88 | 89 | cam.BeginAcquisition() 90 | 91 | print "Acquiring images..." 92 | 93 | device_serial_number = "" 94 | node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode("DeviceSerialNumber")) 95 | if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): 96 | device_serial_number = node_device_serial_number.GetValue() 97 | print "Device serial number retrieved as %s..." % device_serial_number 98 | 99 | plt.ion() 100 | for i in range(NUM_IMAGES): 101 | try: 102 | image_result = cam.GetNextImage() 103 | 104 | if image_result.IsIncomplete(): 105 | print "Image incomplete with image status %d ..." % image_result.GetImageStatus() 106 | else: 107 | fig = plt.figure(1) 108 | 109 | try: 110 | image_stats = image_result.CalculateChannelStatistics(PySpin.GREY) 111 | # Getting the image data as a numpy array 112 | image_data = image_result.GetNDArray() 113 | 114 | # Display Statistics 115 | print "SN%s image %d:" % (device_serial_number, i) 116 | print "\tNumber pixel values : %d" % image_stats.num_pixel_values 117 | print "\tRange: Min = %d, Max = %d" % (image_stats.range_min, 118 | image_stats.range_max) 119 | print "\tPixel Value: Min = %d, Max = %d, Mean = %.2f" % (image_stats.pixel_value_min, 120 | image_stats.pixel_value_max, 121 | image_stats.pixel_value_mean) 122 | 123 | # Using matplotlib, two subplots are created where the top subplot is the histogram and the 124 | # bottom subplot is the image. 125 | # 126 | # Refer to https://matplotlib.org/2.0.2/api/pyplot_api.html#module-matplotlib.pyplot 127 | 128 | # Plot the histogram in the first subplot in a 2 row by 1 column grid 129 | plt.subplot(211) 130 | plt.cla() 131 | plt.plot(image_stats.histogram, label='Grey') 132 | plt.title("SN%s Histogram (%d)" % (device_serial_number, i)) 133 | plt.legend() 134 | 135 | # Plot the image in the second subplot in a 2 row by 1 column grid 136 | plt.subplot(212) 137 | plt.cla() 138 | plt.imshow(image_data, cmap='gray') 139 | 140 | # Show the image 141 | plt.show() 142 | plt.pause(0.01) 143 | 144 | # Create a unique filename 145 | if device_serial_number: 146 | filename = "ImageChannelStatistics-%s-%d.png" % (device_serial_number, i) 147 | else: # if serial number is empty 148 | filename = "ImageChannelStatistics-%d.png" % i 149 | 150 | fig.savefig(filename) 151 | print "\tSave to %s" % filename 152 | print 153 | 154 | except PySpin.SpinnakerException: 155 | raise 156 | 157 | # Release image 158 | # 159 | # *** NOTES *** 160 | # Images retrieved directly from the camera (i.e. non-converted 161 | # images) need to be released in order to keep from filling the 162 | # buffer. 163 | image_result.Release() 164 | 165 | except PySpin.SpinnakerException: 166 | raise 167 | 168 | cam.EndAcquisition() 169 | print "End Acquisition" 170 | 171 | plt.close() 172 | 173 | except PySpin.SpinnakerException as ex: 174 | print "Error: %s" % ex 175 | return False 176 | 177 | return result 178 | 179 | 180 | def run_single_camera(cam): 181 | """ 182 | This function acts as the body of the example; please see NodeMapInfo example 183 | for more in-depth comments on setting up cameras. 184 | 185 | :param cam: Camera to run on. 186 | :type cam: CameraPtr 187 | :return: True if successful, False otherwise. 188 | :rtype: bool 189 | """ 190 | try: 191 | result = True 192 | 193 | nodemap_tldevice = cam.GetTLDeviceNodeMap() 194 | 195 | #Initialize camera 196 | cam.Init() 197 | 198 | # Retrieve GenICam nodemap 199 | nodemap = cam.GetNodeMap() 200 | 201 | # Acquire images 202 | result &= acquire_and_display_images(cam, nodemap, nodemap_tldevice) 203 | 204 | # Deinitialize camera 205 | cam.DeInit() 206 | 207 | except PySpin.SpinnakerException as ex: 208 | print "Error: %s" % ex 209 | result = False 210 | 211 | return result 212 | 213 | def main(): 214 | """ 215 | Example entry point; notice the volume of data that the logging event handler 216 | prints out on debug despite the fact that very little really happens in this 217 | example. Because of this, it may be better to have the logger set to lower 218 | level in order to provide a more concise, focused log. 219 | 220 | :rtype: None 221 | """ 222 | 223 | # Retrieve singleton reference to system object 224 | system = PySpin.System.GetInstance() 225 | 226 | # Retrieve list of cameras from the system 227 | cam_list = system.GetCameras() 228 | 229 | num_cameras = cam_list.GetSize() 230 | 231 | print "Number of cameras detected: %d" % num_cameras 232 | 233 | # Finish if there are no cameras 234 | if num_cameras == 0: 235 | 236 | # Clear camera list before releasing system 237 | cam_list.Clear() 238 | 239 | # Release system 240 | system.ReleaseInstance() 241 | 242 | print "Not enough cameras!" 243 | raw_input("Done! Press Enter to exit...") 244 | return False 245 | 246 | # Run example on each camera 247 | for i in range(num_cameras): 248 | cam = cam_list.GetByIndex(i) 249 | 250 | print "Running example for camera %d..." % i 251 | 252 | result = run_single_camera(cam) 253 | print "Camera %d example complete..." % i 254 | 255 | # Release reference to camera 256 | # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically 257 | # cleaned up when going out of scope. 258 | # The usage of del is preferred to assigning the variable to None. 259 | del cam 260 | 261 | # Clear camera list before releasing system 262 | cam_list.Clear() 263 | 264 | # Release instance 265 | system.ReleaseInstance() 266 | 267 | raw_input("Done! Press Enter to exit...") 268 | return result 269 | 270 | 271 | if __name__ == "__main__": 272 | main() 273 | 274 | -------------------------------------------------------------------------------- /ImageEvents.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # ImageEvents.py shows how to acquire images using the image event handler. 20 | # It relies on information provided in the Enumeration, Acquisition, 21 | # and NodeMapInfo examples. 22 | # 23 | # It can also be helpful to familiarize yourself with the NodeMapCallback 24 | # example, as nodemap callbacks follow the same general procedure as 25 | # events, but with a few less steps. 26 | # 27 | # This example creates a user-defined class, ImageEventHandler, that inherits 28 | # from the Spinnaker class, ImageEvent. ImageEventHandler allows the user to 29 | # define any properties, parameters, and the event itself while ImageEvent 30 | # allows the child class to appropriately interface with Spinnaker. 31 | 32 | 33 | import PySpin 34 | from time import sleep 35 | 36 | SLEEP_DURATION = 200 # amount of time for main thread to sleep for (in milliseconds) until _NUM_IMAGES have been saved 37 | 38 | 39 | class ImageEventHandler(PySpin.ImageEvent): 40 | """ 41 | This class defines the properties, parameters, and the event itself. Take a 42 | moment to notice what parts of the class are mandatory, and what have been 43 | added for demonstration purposes. First, any class used to define image events 44 | must inherit from ImageEvent. Second, the method signature of OnImageEvent() 45 | must also be consistent. Everything else - including the constructor, 46 | destructor, properties, body of OnImageEvent(), and other functions - 47 | is particular to the example. 48 | """ 49 | _NUM_IMAGES = 10 50 | 51 | def __init__(self, cam): 52 | """ 53 | Constructor. Retrieves serial number of given camera and sets image counter to 0. 54 | 55 | :param cam: Camera instance, used to get serial number for unique image filenames. 56 | :type cam: CameraPtr 57 | :rtype: None 58 | """ 59 | super(ImageEventHandler, self).__init__() 60 | 61 | nodemap = cam.GetTLDeviceNodeMap() 62 | 63 | # Retrieve device serial number 64 | node_device_serial_number = PySpin.CStringPtr(nodemap.GetNode("DeviceSerialNumber")) 65 | 66 | if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): 67 | self._device_serial_number = node_device_serial_number.GetValue() 68 | 69 | # Initialize image counter to 0 70 | self._image_count = 0 71 | 72 | # Release reference to camera 73 | del cam 74 | 75 | def OnImageEvent(self, image): 76 | """ 77 | This method defines an image event. In it, the image that triggered the 78 | event is converted and saved before incrementing the count. Please see 79 | Acquisition example for more in-depth comments on the acquisition 80 | of images. 81 | 82 | :param image: Image from event. 83 | :type image: ImagePtr 84 | :rtype: None 85 | """ 86 | # Save max of _NUM_IMAGES Images 87 | if self._image_count < self._NUM_IMAGES: 88 | print "Image event occurred..." 89 | 90 | # Check if image is incomplete 91 | if image.IsIncomplete(): 92 | print "Image incomplete with image status %i..." % image.GetImageStatus() 93 | 94 | else: 95 | # Print image info 96 | print "Grabbed image %i, width = %i, height = %i" % (self._image_count, 97 | image.GetWidth(), 98 | image.GetHeight()) 99 | 100 | # Convert to mono8 101 | image_converted = image.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) 102 | 103 | # Create unique filename and save image 104 | if self._device_serial_number: 105 | filename = "ImageEvents-%s-%i.jpg" % (self._device_serial_number, self._image_count) 106 | 107 | else: # if serial number is empty 108 | filename = "ImageEvents-%i.jpg" % self._image_count 109 | 110 | image_converted.Save(filename) 111 | 112 | print "Image saved at %s\n" % filename 113 | 114 | # Increment image counter 115 | self._image_count += 1 116 | 117 | def get_image_count(self): 118 | """ 119 | Getter for image count. 120 | 121 | :return: Number of images saved. 122 | :rtype: int 123 | """ 124 | return self._image_count 125 | 126 | def get_max_images(self): 127 | """ 128 | Getter for maximum images. 129 | 130 | :return: Total number of images to save. 131 | :rtype: int 132 | """ 133 | return self._NUM_IMAGES 134 | 135 | 136 | def configure_image_events(cam): 137 | """ 138 | This function configures the example to execute image events by preparing and 139 | registering an image event. 140 | 141 | :param cam: Camera instance to configure image event. 142 | :return: tuple(result, image_event_handler) 143 | WHERE 144 | result is True if successful, False otherwise 145 | image_event_handler is the event handler 146 | :rtype: (bool, ImageEventHandler) 147 | """ 148 | try: 149 | result = True 150 | 151 | # Create image event 152 | # 153 | # *** NOTES *** 154 | # The class has been constructed to accept a camera pointer in order 155 | # to allow the saving of images with the device serial number. 156 | image_event_handler = ImageEventHandler(cam) 157 | 158 | # Register image event handler 159 | # 160 | # *** NOTES *** 161 | # Image events are registered to cameras. If there are multiple 162 | # cameras, each camera must have the image events registered to it 163 | # separately. Also, multiple image events may be registered to a 164 | # single camera. 165 | # 166 | # *** LATER *** 167 | # Image events must be unregistered manually. This must be done prior 168 | # to releasing the system and while the image events are still in 169 | # scope. 170 | cam.RegisterEvent(image_event_handler) 171 | 172 | except PySpin.SpinnakerException as ex: 173 | print "Error: %s" % ex 174 | result = False 175 | 176 | return result, image_event_handler 177 | 178 | 179 | def wait_for_images(image_event_handler): 180 | """ 181 | This function waits for the appropriate amount of images. Notice that 182 | whereas most examples actively retrieve images, the acquisition of images is 183 | handled passively in this example. 184 | 185 | :param image_event_handler: Image event handler. 186 | :type image_event_handler: ImageEventHandler 187 | :return: True if successful, False otherwise. 188 | :rtype: bool 189 | """ 190 | try: 191 | result = True 192 | 193 | # Wait for images 194 | # 195 | # *** NOTES *** 196 | # In order to passively capture images using image events and 197 | # automatic polling, the main thread sleeps in increments of SLEEP_DURATION ms 198 | # until _MAX_IMAGES images have been acquired and saved. 199 | while image_event_handler.get_image_count() < image_event_handler.get_max_images(): 200 | print "\t//\n\t// Sleeping for %i ms. Grabbing images..." % SLEEP_DURATION 201 | sleep(SLEEP_DURATION / 1000.0) 202 | 203 | except PySpin.SpinnakerException as ex: 204 | print "Error: %s" % ex 205 | result = False 206 | 207 | return result 208 | 209 | 210 | def reset_image_events(cam, image_event_handler): 211 | """ 212 | This functions resets the example by unregistering the image event. 213 | 214 | :param cam: Camera instance. 215 | :param image_event_handler: Image event handler for cam. 216 | :type cam: CameraPtr 217 | :type image_event_handler: ImageEventHandler 218 | :return: True if successful, False otherwise. 219 | :rtype: bool 220 | """ 221 | try: 222 | result = True 223 | 224 | # Unregister image event handler 225 | # 226 | # *** NOTES *** 227 | # It is important to unregister all image events from all cameras they are registered to. 228 | # Unlike SystemEventHandler and InterfaceEventHandler in the EnumerationEvents example, 229 | # there is no need to explicitly delete the ImageEventHandler here as it does not store 230 | # an instance of the camera (it gets deleted in the constructor already). 231 | cam.UnregisterEvent(image_event_handler) 232 | 233 | print "Image events unregistered..." 234 | 235 | except PySpin.SpinnakerException as ex: 236 | print "Error: %s" % ex 237 | result = False 238 | 239 | return result 240 | 241 | 242 | def print_device_info(nodemap): 243 | """ 244 | This function prints the device information of the camera from the transport 245 | layer; please see NodeMapInfo example for more in-depth comments on printing 246 | device information from the nodemap. 247 | 248 | :param nodemap: Transport layer device nodemap from camera. 249 | :type nodemap: INodeMap 250 | :return: True if successful, False otherwise. 251 | :rtype: bool 252 | """ 253 | print "*** DEVICE INFORMATION ***" 254 | 255 | try: 256 | result = True 257 | node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) 258 | 259 | if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): 260 | features = node_device_information.GetFeatures() 261 | for feature in features: 262 | node_feature = PySpin.CValuePtr(feature) 263 | print "%s: %s" % (node_feature.GetName(), 264 | node_feature.ToString() if PySpin.IsReadable(node_feature) else "Node not readable") 265 | 266 | else: 267 | print "Device control information not available." 268 | 269 | except PySpin.SpinnakerException as ex: 270 | print "Error: %s" % ex.message 271 | result = False 272 | 273 | return result 274 | 275 | 276 | def acquire_images(cam, nodemap, image_event_handler): 277 | """ 278 | This function passively waits for images by calling wait_for_images(). Notice that 279 | this function is much shorter than the acquire_images() function of other examples. 280 | This is because most of the code has been moved to the image event's OnImageEvent() 281 | method. 282 | 283 | :param cam: Camera instance to grab images from. 284 | :param nodemap: Device nodemap. 285 | :param image_event_handler: Image event handler. 286 | :type cam: CameraPtr 287 | :type nodemap: INodeMap 288 | :type image_event_handler: ImageEventHandler 289 | :return: True if successful, False otherwise. 290 | :rtype: bool 291 | """ 292 | print "*** IMAGE ACQUISITION ***\n" 293 | try: 294 | result = True 295 | 296 | # Set acquisition mode to continuous 297 | node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode("AcquisitionMode")) 298 | if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): 299 | print "Unable to set acquisition mode to continuous (enum retrieval). Aborting..." 300 | return False 301 | 302 | node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName("Continuous") 303 | if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable(node_acquisition_mode_continuous): 304 | print "Unable to set acquisition mode to continuous (entry retrieval). Aborting..." 305 | return False 306 | 307 | acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() 308 | node_acquisition_mode.SetIntValue(acquisition_mode_continuous) 309 | 310 | print "Acquisition mode set to continuous..." 311 | 312 | # Begin acquiring images 313 | cam.BeginAcquisition() 314 | 315 | print "Acquiring images..." 316 | 317 | # Retrieve images using image event handler 318 | wait_for_images(image_event_handler) 319 | 320 | cam.EndAcquisition() 321 | 322 | except PySpin.SpinnakerException as ex: 323 | print "Error: %s" % ex 324 | result = False 325 | 326 | return result 327 | 328 | 329 | def run_single_camera(cam): 330 | """ 331 | This function acts as the body of the example; please see NodeMapInfo example 332 | for more in-depth comments on setting up cameras. 333 | 334 | :param cam: Camera to acquire images from. 335 | :type cam: CameraPtr 336 | :return: True if successful, False otherwise. 337 | :rtype: bool 338 | """ 339 | try: 340 | result = True 341 | 342 | # Retrieve TL device nodemap and print device information 343 | nodemap_tldevice = cam.GetTLDeviceNodeMap() 344 | 345 | result &= print_device_info(nodemap_tldevice) 346 | 347 | # Initialize camera 348 | cam.Init() 349 | 350 | # Retrieve GenICam nodemap 351 | nodemap = cam.GetNodeMap() 352 | 353 | # Configure image events 354 | err, image_event_handler = configure_image_events(cam) 355 | if not err: 356 | return err 357 | 358 | # Acquire images using the image event handler 359 | result &= acquire_images(cam, nodemap, image_event_handler) 360 | 361 | # Reset image events 362 | result &= reset_image_events(cam, image_event_handler) 363 | 364 | # Deinitialize camera 365 | cam.DeInit() 366 | 367 | except PySpin.SpinnakerException as ex: 368 | print "Error: %s" % ex 369 | result = False 370 | 371 | return result 372 | 373 | 374 | def main(): 375 | """ 376 | Example entry point; please see Enumeration example for additional 377 | comments on the steps in this function. 378 | 379 | :return: True if successful, False otherwise. 380 | :rtype: bool 381 | """ 382 | result = True 383 | 384 | # Retrieve singleton reference to system object 385 | system = PySpin.System.GetInstance() 386 | 387 | # Retrieve list of cameras from the system 388 | cam_list = system.GetCameras() 389 | 390 | num_cams = cam_list.GetSize() 391 | 392 | print "Number of cameras detected: %i" % num_cams 393 | 394 | # Finish if there are no cameras 395 | if num_cams == 0: 396 | # Clear camera list before releasing system 397 | cam_list.Clear() 398 | 399 | # Release system 400 | system.ReleaseInstance() 401 | 402 | print "Not enough cameras!" 403 | raw_input("Done! Press Enter to exit...") 404 | 405 | # Run example on each camera 406 | for i in range(num_cams): 407 | print "Running example for camera %i..." % i 408 | 409 | result &= run_single_camera(cam_list.GetByIndex(i)) 410 | 411 | print "Camera %i example complete..." % i 412 | 413 | # Clear camera list before releasing system 414 | cam_list.Clear() 415 | 416 | # Release system 417 | system.ReleaseInstance() 418 | raw_input("Done! Press Enter to exit...") 419 | 420 | return result 421 | 422 | if __name__ == "__main__": 423 | main() 424 | -------------------------------------------------------------------------------- /ImageFormatControl.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # ImageFormatControl.py shows how to apply custom image settings to 20 | # the camera. It relies on information provided in the Enumeration, 21 | # Acquisition, and NodeMapInfo examples. 22 | # 23 | # This example demonstrates setting minimums to offsets, X and Y, and maximums 24 | # to width and height. It also shows the setting of a new pixel format, which 25 | # is an enumeration type node. 26 | # 27 | # Following this, we suggest familiarizing yourself with the Exposure example 28 | # if you haven't already. Exposure is another example on camera customization 29 | # that is shorter and simpler than many of the others. Once comfortable with 30 | # Exposure and ImageFormatControl, we suggest checking out any of the longer, 31 | # more complicated examples related to camera configuration: ChunkData, 32 | # LookupTable, Sequencer, or Trigger. 33 | 34 | import PySpin 35 | 36 | NUM_IMAGES = 10 # number of images to grab 37 | 38 | 39 | def configure_custom_image_settings(nodemap): 40 | """ 41 | Configures a number of settings on the camera including offsets X and Y, width, 42 | height, and pixel format. These settings must be applied before BeginAcquisition() 43 | is called; otherwise, they will be read only. Also, it is important to note that 44 | settings are applied immediately. This means if you plan to reduce the width and 45 | move the x offset accordingly, you need to apply such changes in the appropriate order. 46 | 47 | :param nodemap: GenICam nodemap. 48 | :type nodemap: INodeMap 49 | :return: True if successful, False otherwise. 50 | :rtype: bool 51 | """ 52 | print "\n*** CONFIGURING CUSTOM IMAGE SETTINGS *** \n" 53 | 54 | try: 55 | result = True 56 | 57 | # Apply mono 8 pixel format 58 | # 59 | # *** NOTES *** 60 | # Enumeration nodes are slightly more complicated to set than other 61 | # nodes. This is because setting an enumeration node requires working 62 | # with two nodes instead of the usual one. 63 | # 64 | # As such, there are a number of steps to setting an enumeration node: 65 | # retrieve the enumeration node from the nodemap, retrieve the desired 66 | # entry node from the enumeration node, retrieve the integer value from 67 | # the entry node, and set the new value of the enumeration node with 68 | # the integer value from the entry node. 69 | # 70 | # Retrieve the enumeration node from the nodemap 71 | node_pixel_format = PySpin.CEnumerationPtr(nodemap.GetNode("PixelFormat")) 72 | if PySpin.IsAvailable(node_pixel_format) and PySpin.IsWritable(node_pixel_format): 73 | 74 | # Retrieve the desired entry node from the enumeration node 75 | node_pixel_format_mono8 = PySpin.CEnumEntryPtr(node_pixel_format.GetEntryByName("Mono8")) 76 | if PySpin.IsAvailable(node_pixel_format_mono8) and PySpin.IsReadable(node_pixel_format_mono8): 77 | 78 | # Retrieve the integer value from the entry node 79 | pixel_format_mono8 = node_pixel_format_mono8.GetValue() 80 | 81 | # Set integer as new value for enumeration node 82 | node_pixel_format.SetIntValue(pixel_format_mono8) 83 | 84 | print "Pixel format set to %s..." % node_pixel_format.GetCurrentEntry().GetSymbolic() 85 | 86 | else: 87 | print "Pixel format mono 8 not available..." 88 | 89 | else: 90 | print "Pixel format not available..." 91 | 92 | # Apply minimum to offset X 93 | # 94 | # *** NOTES *** 95 | # Numeric nodes have both a minimum and maximum. A minimum is retrieved 96 | # with the method GetMin(). Sometimes it can be important to check 97 | # minimums to ensure that your desired value is within range. 98 | node_offset_x = PySpin.CIntegerPtr(nodemap.GetNode("OffsetX")) 99 | if PySpin.IsAvailable(node_offset_x) and PySpin.IsWritable(node_offset_x): 100 | 101 | node_offset_x.SetValue(node_offset_x.GetMin()) 102 | print "Offset X set to %i..." % node_offset_x.GetMin() 103 | 104 | else: 105 | print "Offset X not available..." 106 | 107 | # Apply minimum to offset Y 108 | # 109 | # *** NOTES *** 110 | # It is often desirable to check the increment as well. The increment 111 | # is a number of which a desired value must be a multiple of. Certain 112 | # nodes, such as those corresponding to offsets X and Y, have an 113 | # increment of 1, which basically means that any value within range 114 | # is appropriate. The increment is retrieved with the method GetInc(). 115 | node_offset_y = PySpin.CIntegerPtr(nodemap.GetNode("OffsetY")) 116 | if PySpin.IsAvailable(node_offset_y) and PySpin.IsWritable(node_offset_y): 117 | 118 | node_offset_y.SetValue(node_offset_y.GetMin()) 119 | print "Offset Y set to %i..." % node_offset_y.GetMin() 120 | 121 | else: 122 | print "Offset Y not available..." 123 | 124 | # Set maximum width 125 | # 126 | # *** NOTES *** 127 | # Other nodes, such as those corresponding to image width and height, 128 | # might have an increment other than 1. In these cases, it can be 129 | # important to check that the desired value is a multiple of the 130 | # increment. However, as these values are being set to the maximum, 131 | # there is no reason to check against the increment. 132 | node_width = PySpin.CIntegerPtr(nodemap.GetNode("Width")) 133 | if PySpin.IsAvailable(node_width) and PySpin.IsWritable(node_width): 134 | 135 | width_to_set = node_width.GetMax() 136 | node_width.SetValue(width_to_set) 137 | print "Width set to %i..." % node_width.GetValue() 138 | 139 | else: 140 | print "Width not available..." 141 | 142 | # Set maximum height 143 | # 144 | # *** NOTES *** 145 | # A maximum is retrieved with the method GetMax(). A node's minimum and 146 | # maximum should always be a multiple of its increment. 147 | node_height = PySpin.CIntegerPtr(nodemap.GetNode("Height")) 148 | if PySpin.IsAvailable(node_height) and PySpin.IsWritable(node_height): 149 | 150 | height_to_set = node_height.GetMax() 151 | node_height.SetValue(height_to_set) 152 | print "Height set to %i..." % node_height.GetValue() 153 | 154 | else: 155 | print "Height not available..." 156 | 157 | except PySpin.SpinnakerException as ex: 158 | print "Error: %s" % ex 159 | return False 160 | 161 | return result 162 | 163 | 164 | def print_device_info(nodemap): 165 | """ 166 | This function prints the device information of the camera from the transport 167 | layer; please see NodeMapInfo example for more in-depth comments on printing 168 | device information from the nodemap. 169 | 170 | :param nodemap: Transport layer device nodemap. 171 | :type nodemap: INodeMap 172 | :returns: True if successful, False otherwise. 173 | :rtype: bool 174 | """ 175 | 176 | print "*** DEVICE INFORMATION ***\n" 177 | 178 | try: 179 | result = True 180 | node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) 181 | 182 | if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): 183 | features = node_device_information.GetFeatures() 184 | for feature in features: 185 | node_feature = PySpin.CValuePtr(feature) 186 | print "%s: %s" % (node_feature.GetName(), 187 | node_feature.ToString() if PySpin.IsReadable(node_feature) else "Node not readable") 188 | 189 | else: 190 | print "Device control information not available." 191 | 192 | except PySpin.SpinnakerException as ex: 193 | print "Error: %s" % ex 194 | return False 195 | 196 | return result 197 | 198 | 199 | def acquire_images(cam, nodemap, nodemap_tldevice): 200 | """ 201 | This function acquires and saves 10 images from a device. 202 | 203 | :param cam: Camera to acquire images from. 204 | :param nodemap: Device nodemap. 205 | :param nodemap_tldevice: Transport layer device nodemap. 206 | :type cam: CameraPtr 207 | :type nodemap: INodeMap 208 | :type nodemap_tldevice: INodeMap 209 | :return: True if successful, False otherwise. 210 | :rtype: bool 211 | """ 212 | 213 | print "*** IMAGE ACQUISITION ***\n" 214 | try: 215 | result = True 216 | 217 | # Set acquisition mode to continuous 218 | # 219 | # *** NOTES *** 220 | # Because the example acquires and saves 10 images, setting acquisition 221 | # mode to continuous lets the example finish. If set to single frame 222 | # or multiframe (at a lower number of images), the example would just 223 | # hang. This would happen because the example has been written to 224 | # acquire 10 images while the camera would have been programmed to 225 | # retrieve less than that. 226 | # 227 | # Setting the value of an enumeration node is slightly more complicated 228 | # than other node types. Two nodes must be retrieved: first, the 229 | # enumeration node is retrieved from the nodemap; and second, the entry 230 | # node is retrieved from the enumeration node. The integer value of the 231 | # entry node is then set as the new value of the enumeration node. 232 | # 233 | # Notice that both the enumeration and the entry nodes are checked for 234 | # availability and readability/writability. Enumeration nodes are 235 | # generally readable and writable whereas their entry nodes are only 236 | # ever readable. 237 | # 238 | # Retrieve enumeration node from nodemap 239 | 240 | # In order to access the node entries, they have to be casted to a pointer type (CEnumerationPtr here) 241 | node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode("AcquisitionMode")) 242 | if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): 243 | print "Unable to set acquisition mode to continuous (enum retrieval). Aborting..." 244 | return False 245 | 246 | # Retrieve entry node from enumeration node 247 | node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName("Continuous") 248 | if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( 249 | node_acquisition_mode_continuous): 250 | print "Unable to set acquisition mode to continuous (entry retrieval). Aborting..." 251 | return False 252 | 253 | # Retrieve integer value from entry node 254 | acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() 255 | 256 | # Set integer value from entry node as new value of enumeration node 257 | node_acquisition_mode.SetIntValue(acquisition_mode_continuous) 258 | 259 | print "Acquisition mode set to continuous..." 260 | 261 | # Begin acquiring images 262 | # 263 | # *** NOTES *** 264 | # What happens when the camera begins acquiring images depends on the 265 | # acquisition mode. Single frame captures only a single image, multi 266 | # frame catures a set number of images, and continuous captures a 267 | # continuous stream of images. Because the example calls for the 268 | # retrieval of 10 images, continuous mode has been set. 269 | # 270 | # *** LATER *** 271 | # Image acquisition must be ended when no more images are needed. 272 | cam.BeginAcquisition() 273 | 274 | print "Acquiring images..." 275 | 276 | # Retrieve device serial number for filename 277 | # 278 | # *** NOTES *** 279 | # The device serial number is retrieved in order to keep cameras from 280 | # overwriting one another. Grabbing image IDs could also accomplish 281 | # this. 282 | device_serial_number = "" 283 | node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode("DeviceSerialNumber")) 284 | if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): 285 | device_serial_number = node_device_serial_number.GetValue() 286 | print "Device serial number retrieved as %s..." % device_serial_number 287 | 288 | # Retrieve, convert, and save images 289 | for i in range(NUM_IMAGES): 290 | try: 291 | 292 | # Retrieve next received image 293 | # 294 | # *** NOTES *** 295 | # Capturing an image houses images on the camera buffer. Trying 296 | # to capture an image that does not exist will hang the camera. 297 | # 298 | # *** LATER *** 299 | # Once an image from the buffer is saved and/or no longer 300 | # needed, the image must be released in order to keep the 301 | # buffer from filling up. 302 | image_result = cam.GetNextImage() 303 | 304 | # Ensure image completion 305 | # 306 | # *** NOTES *** 307 | # Images can easily be checked for completion. This should be 308 | # done whenever a complete image is expected or required. 309 | # Further, check image status for a little more insight into 310 | # why an image is incomplete. 311 | if image_result.IsIncomplete(): 312 | print "Image incomplete with image status %d ..." % image_result.GetImageStatus() 313 | 314 | else: 315 | 316 | # Print image information; height and width recorded in pixels 317 | # 318 | # *** NOTES *** 319 | # Images have quite a bit of available metadata including 320 | # things such as CRC, image status, and offset values, to 321 | # name a few. 322 | width = image_result.GetWidth() 323 | height = image_result.GetHeight() 324 | print "Grabbed Image %d, width = %d, height = %d" % (i, width, height) 325 | 326 | # Convert image to mono 8 327 | # 328 | # *** NOTES *** 329 | # Images can be converted between pixel formats by using 330 | # the appropriate enumeration value. Unlike the original 331 | # image, the converted one does not need to be released as 332 | # it does not affect the camera buffer. 333 | # 334 | # When converting images, color processing algorithm is an 335 | # optional parameter. 336 | image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) 337 | 338 | # Create a unique filename 339 | if device_serial_number: 340 | filename = "ImageFormatControl-%s-%d.jpg" % (device_serial_number, i) 341 | else: # if serial number is empty 342 | filename = "ImageFormatControl-%d.jpg" % i 343 | 344 | # Save image 345 | # 346 | # *** NOTES *** 347 | # The standard practice of the examples is to use device 348 | # serial numbers to keep images of one device from 349 | # overwriting those of another. 350 | image_converted.Save(filename) 351 | print "Image saved at %s" % filename 352 | 353 | # Release image 354 | # 355 | # *** NOTES *** 356 | # Images retrieved directly from the camera (i.e. non-converted 357 | # images) need to be released in order to keep from filling the 358 | # buffer. 359 | image_result.Release() 360 | print "" 361 | 362 | except PySpin.SpinnakerException as ex: 363 | print "Error: %s" % ex 364 | return False 365 | 366 | # End acquisition 367 | # 368 | # *** NOTES *** 369 | # Ending acquisition appropriately helps ensure that devices clean up 370 | # properly and do not need to be power-cycled to maintain integrity. 371 | cam.EndAcquisition() 372 | 373 | except PySpin.SpinnakerException as ex: 374 | print "Error: %s" % ex 375 | return False 376 | 377 | return result 378 | 379 | 380 | def run_single_camera(cam): 381 | """ 382 | This function acts as the body of the example; please see NodeMapInfo example 383 | for more in-depth comments on setting up cameras. 384 | 385 | :param cam: Camera to run on. 386 | :type cam: CameraPtr 387 | :return: True if successful, False otherwise. 388 | :rtype: bool 389 | """ 390 | try: 391 | result = True 392 | 393 | # Retrieve TL device nodemap and print device information 394 | nodemap_tldevice = cam.GetTLDeviceNodeMap() 395 | 396 | result &= print_device_info(nodemap_tldevice) 397 | 398 | # Initialize camera 399 | cam.Init() 400 | 401 | # Retrieve GenICam nodemap 402 | nodemap = cam.GetNodeMap() 403 | 404 | # Configure custom image settings 405 | if not configure_custom_image_settings(nodemap): 406 | return False 407 | 408 | # Acquire images 409 | result &= acquire_images(cam, nodemap, nodemap_tldevice) 410 | 411 | # Deinitialize camera 412 | cam.DeInit() 413 | 414 | except PySpin.SpinnakerException as ex: 415 | print "Error: %s" % ex 416 | result = False 417 | 418 | return result 419 | 420 | 421 | def main(): 422 | """ 423 | Example entry point; please see Enumeration example for more in-depth 424 | comments on preparing and cleaning up the system. 425 | 426 | :return: True if successful, False otherwise. 427 | :rtype: bool 428 | """ 429 | # Retrieve singleton reference to system object 430 | system = PySpin.System.GetInstance() 431 | 432 | # Retrieve list of cameras from the system 433 | cam_list = system.GetCameras() 434 | 435 | num_cameras = cam_list.GetSize() 436 | 437 | print "Number of cameras detected: %d" % num_cameras 438 | 439 | # Finish if there are no cameras 440 | if num_cameras == 0: 441 | 442 | # Clear camera list before releasing system 443 | cam_list.Clear() 444 | 445 | # Release system 446 | system.ReleaseInstance() 447 | 448 | print "Not enough cameras!" 449 | raw_input("Done! Press Enter to exit...") 450 | return False 451 | 452 | # Run example on each camera 453 | for i in range(num_cameras): 454 | cam = cam_list.GetByIndex(i) 455 | 456 | print "Running example for camera %d..." % i 457 | 458 | result = run_single_camera(cam) 459 | print "Camera %d example complete..." % i 460 | 461 | # Release reference to camera 462 | # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically 463 | # cleaned up when going out of scope. 464 | # The usage of del is preferred to assigning the variable to None. 465 | del cam 466 | 467 | # Clear camera list before releasing system 468 | cam_list.Clear() 469 | 470 | # Release instance 471 | system.ReleaseInstance() 472 | 473 | raw_input("Done! Press Enter to exit...") 474 | return result 475 | 476 | if __name__ == "__main__": 477 | main() 478 | -------------------------------------------------------------------------------- /ImageFormatControl_QuickSpin.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # ImageFormatControl_QuickSpin.py shows how to apply custom image 20 | # settings to the camera using the QuickSpin API. QuickSpin is a subset of 21 | # the Spinnaker library that allows for simpler node access and control. 22 | # 23 | # This example demonstrates customizing offsets X and Y, width and height, 24 | # and the pixel format. Ensuring custom values fall within an acceptable 25 | # range is also touched on. Retrieving and setting node values using 26 | # QuickSpin is the only portion of the example that differs from 27 | # ImageFormatControl. 28 | # 29 | # A much wider range of topics is covered in the full Spinnaker examples than 30 | # in the QuickSpin ones. There are only enough QuickSpin examples to 31 | # demonstrate node access and to get started with the API; please see full 32 | # Spinnaker examples for further or specific knowledge on a topic. 33 | 34 | import PySpin 35 | 36 | NUM_IMAGES = 10 # number of images to grab 37 | 38 | 39 | def configure_custom_image_settings(cam): 40 | """ 41 | Configures a number of settings on the camera including offsets X and Y, 42 | width, height, and pixel format. These settings must be applied before 43 | BeginAcquisition() is called; otherwise, those nodes would be read only. 44 | Also, it is important to note that settings are applied immediately. 45 | This means if you plan to reduce the width and move the x offset accordingly, 46 | you need to apply such changes in the appropriate order. 47 | 48 | :param cam: Camera to configure settings on. 49 | :type cam: CameraPtr 50 | :return: True if successful, False otherwise. 51 | :rtype: bool 52 | """ 53 | print "\n*** CONFIGURING CUSTOM IMAGE SETTINGS ***\n" 54 | 55 | try: 56 | result = True 57 | 58 | # Apply mono 8 pixel format 59 | # 60 | # *** NOTES *** 61 | # In QuickSpin, enumeration nodes are as easy to set as other node 62 | # types. This is because enum values representing each entry node 63 | # are added to the API. 64 | if cam.PixelFormat.GetAccessMode() == PySpin.RW: 65 | cam.PixelFormat.SetValue(PySpin.PixelFormat_Mono8) 66 | print "Pixel format set to %s..." % cam.PixelFormat.GetCurrentEntry().GetSymbolic() 67 | 68 | else: 69 | print "Pixel format not available..." 70 | result = False 71 | 72 | # Apply minimum to offset X 73 | # 74 | # *** NOTES *** 75 | # Numeric nodes have both a minimum and maximum. A minimum is retrieved 76 | # with the method GetMin(). Sometimes it can be important to check 77 | # minimums to ensure that your desired value is within range. 78 | if cam.OffsetX.GetAccessMode() == PySpin.RW: 79 | cam.OffsetX.SetValue(cam.OffsetX.GetMin()) 80 | print "Offset X set to %d..." % cam.OffsetX.GetValue() 81 | 82 | else: 83 | print "Offset X not available..." 84 | result = False 85 | 86 | # Apply minimum to offset Y 87 | # 88 | # *** NOTES *** 89 | # It is often desirable to check the increment as well. The increment 90 | # is a number of which a desired value must be a multiple. Certain 91 | # nodes, such as those corresponding to offsets X and Y, have an 92 | # increment of 1, which basically means that any value within range 93 | # is appropriate. The increment is retrieved with the method GetInc(). 94 | if cam.OffsetY.GetAccessMode() == PySpin.RW: 95 | cam.OffsetY.SetValue(cam.OffsetY.GetMin()) 96 | print "Offset Y set to %d..." % cam.OffsetY.GetValue() 97 | 98 | else: 99 | print "Offset Y not available..." 100 | result = False 101 | 102 | # Set maximum width 103 | # 104 | # *** NOTES *** 105 | # Other nodes, such as those corresponding to image width and height, 106 | # might have an increment other than 1. In these cases, it can be 107 | # important to check that the desired value is a multiple of the 108 | # increment. 109 | # 110 | # This is often the case for width and height nodes. However, because 111 | # these nodes are being set to their maximums, there is no real reason 112 | # to check against the increment. 113 | if cam.Width.GetAccessMode() == PySpin.RW and cam.Width.GetInc() != 0 and cam.Width.GetMax != 0: 114 | cam.Width.SetValue(cam.Width.GetMax()) 115 | print "Width set to %i..." % cam.Width.GetValue() 116 | 117 | else: 118 | print "Width not available..." 119 | result = False 120 | 121 | # Set maximum height 122 | # 123 | # *** NOTES *** 124 | # A maximum is retrieved with the method GetMax(). A node's minimum and 125 | # maximum should always be a multiple of its increment. 126 | if cam.Height.GetAccessMode() == PySpin.RW and cam.Height.GetInc() != 0 and cam.Height.GetMax != 0: 127 | cam.Height.SetValue(cam.Height.GetMax()) 128 | print "Height set to %i..." % cam.Height.GetValue() 129 | 130 | else: 131 | print "Height not available..." 132 | result = False 133 | 134 | except PySpin.SpinnakerException as ex: 135 | print "Error: %s" % ex 136 | return False 137 | 138 | return result 139 | 140 | 141 | def print_device_info(cam): 142 | """ 143 | This function prints the device information of the camera from the transport 144 | layer; please see NodeMapInfo example for more in-depth comments on printing 145 | device information from the nodemap. 146 | 147 | :param cam: Camera to get device information from. 148 | :type cam: CameraPtr 149 | :return: True if successful, False otherwise. 150 | :rtype: bool 151 | """ 152 | 153 | print "\n*** DEVICE INFORMATION ***\n" 154 | 155 | try: 156 | result = True 157 | nodemap = cam.GetTLDeviceNodeMap() 158 | 159 | node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) 160 | 161 | if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): 162 | features = node_device_information.GetFeatures() 163 | for feature in features: 164 | node_feature = PySpin.CValuePtr(feature) 165 | print "%s: %s" % (node_feature.GetName(), 166 | node_feature.ToString() if PySpin.IsReadable(node_feature) else "Node not readable") 167 | 168 | else: 169 | print "Device control information not available." 170 | 171 | except PySpin.SpinnakerException as ex: 172 | print "Error: %s" % ex.message 173 | return False 174 | 175 | return result 176 | 177 | 178 | def acquire_images(cam): 179 | """ 180 | This function acquires and saves 10 images from a device; please see 181 | Acquisition example for more in-depth comments on the acquisition of images. 182 | 183 | :param cam: Camera to acquire images from. 184 | :type cam: CameraPtr 185 | :return: True if successful, False otherwise. 186 | :rtype: bool 187 | """ 188 | print "\n*** IMAGE ACQUISITION ***\n" 189 | 190 | try: 191 | result = True 192 | 193 | # Set acquisition mode to continuous 194 | if cam.AcquisitionMode.GetAccessMode() != PySpin.RW: 195 | print "Unable to set acquisition mode to continuous. Aborting..." 196 | return False 197 | 198 | cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous) 199 | print "Acquisition mode set to continuous..." 200 | 201 | # Begin acquiring images 202 | cam.BeginAcquisition() 203 | 204 | print "Acquiring images..." 205 | 206 | # Get device serial number for filename 207 | device_serial_number = "" 208 | if cam.TLDevice.DeviceSerialNumber is not None and cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: 209 | device_serial_number = cam.TLDevice.DeviceSerialNumber.GetValue() 210 | 211 | print "Device serial number retrieved as %s..." % device_serial_number 212 | 213 | # Retrieve, convert, and save images 214 | for i in range(NUM_IMAGES): 215 | 216 | try: 217 | # Retrieve next received image and ensure image completion 218 | image_result = cam.GetNextImage() 219 | 220 | if image_result.IsIncomplete(): 221 | print "Image incomplete with image status %d..." % image_result.GetImageStatus() 222 | 223 | else: 224 | # Print image information 225 | width = image_result.GetWidth() 226 | height = image_result.GetHeight() 227 | print "Grabbed Image %d, width = %d, height = %d" % (i, width, height) 228 | 229 | # Convert image to Mono8 230 | image_converted = image_result.Convert(PySpin.PixelFormat_Mono8) 231 | 232 | # Create a unique filename 233 | if device_serial_number: 234 | filename = "ImageFormatControlQS-%s-%d.jpg" % (device_serial_number, i) 235 | else: 236 | filename = "ImageFormatControlQS-%d.jpg" % i 237 | 238 | # Save image 239 | image_converted.Save(filename) 240 | 241 | print "Image saved at %s" % filename 242 | 243 | # Release image 244 | image_result.Release() 245 | 246 | except PySpin.SpinnakerException as ex: 247 | print "Error: %s" % ex 248 | result = False 249 | 250 | # End acquisition 251 | cam.EndAcquisition() 252 | 253 | except PySpin.SpinnakerException as ex: 254 | print "Error: %s" % ex 255 | result = False 256 | 257 | return result 258 | 259 | 260 | def run_single_camera(cam): 261 | """ 262 | This function acts as the body of the example; please see NodeMapInfo_QuickSpin example for more 263 | in-depth comments on setting up cameras. 264 | 265 | :param cam: Camera to run example on. 266 | :type cam: CameraPtr 267 | :return: True if successful, False otherwise. 268 | :rtype: bool 269 | """ 270 | try: 271 | # Initialize camera 272 | cam.Init() 273 | 274 | # Print device info 275 | result = print_device_info(cam) 276 | 277 | # Configure exposure 278 | if not configure_custom_image_settings(cam): 279 | return False 280 | 281 | # Acquire images 282 | result &= acquire_images(cam) 283 | 284 | # Deinitialize camera 285 | cam.DeInit() 286 | 287 | return result 288 | 289 | except PySpin.SpinnakerException as ex: 290 | print "Error: %s" % ex 291 | return False 292 | 293 | 294 | def main(): 295 | """ 296 | Example entry point; please see Enumeration_QuickSpin example for more 297 | in-depth comments on preparing and cleaning up the system. 298 | 299 | :return: True if successful, False otherwise. 300 | :rtype: bool 301 | """ 302 | # Retrieve singleton reference to system object 303 | system = PySpin.System.GetInstance() 304 | 305 | # Retrieve list of cameras from the system 306 | cam_list = system.GetCameras() 307 | 308 | num_cameras = cam_list.GetSize() 309 | 310 | print "Number of cameras detected: %d" % num_cameras 311 | 312 | # Finish if there are no cameras 313 | if num_cameras == 0: 314 | # Clear camera list before releasing system 315 | cam_list.Clear() 316 | 317 | # Release system 318 | system.ReleaseInstance() 319 | 320 | print "Not enough cameras!" 321 | raw_input("Done! Press Enter to exit...") 322 | return False 323 | 324 | # Release example on each camera 325 | for i in range(num_cameras): 326 | print "Running example for camera %d..." % i 327 | 328 | result = run_single_camera(cam_list.GetByIndex(i)) 329 | 330 | print "Camera %d example complete..." % i 331 | 332 | # Clear camera list before releasing system 333 | cam_list.Clear() 334 | 335 | # Release system 336 | system.ReleaseInstance() 337 | 338 | raw_input("Done! Press Enter to exit...") 339 | return result 340 | 341 | if __name__ == "__main__": 342 | main() 343 | -------------------------------------------------------------------------------- /Logging.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # Logging.py shows how to create a handler to access logging events. 20 | # It relies on information provided in the Enumeration, Acquisition, and 21 | # NodeMapInfo examples. 22 | # 23 | # It can also be helpful to familiarize yourself with the NodeMapCallback 24 | # example, as nodemap callbacks follow the same general procedure as 25 | # events, but with a few less steps. 26 | # 27 | # This example creates a user-defined class, LoggingEventHandler, that inherits 28 | # from the Spinnaker class, LoggingEvent. The child class allows the user to 29 | # define any properties, parameters, and the event itself while LoggingEvent 30 | # allows the child class to appropriately interface with the Spinnaker SDK. 31 | 32 | import PySpin 33 | 34 | 35 | # Define callback priority threshold; please see documentation for additional 36 | # information on logging level philosophy. 37 | LOGGING_LEVEL = PySpin.LOG_LEVEL_DEBUG # change to any LOG_LEVEL_* constant 38 | 39 | 40 | class LoggingEventHandler(PySpin.LoggingEvent): 41 | """ 42 | Although logging events are just as flexible and extensible as other events, 43 | they are generally only used for logging purposes, which is why a number of 44 | helpful functions that provide logging information have been added. Generally, 45 | if the purpose is not logging, one of the other event types is probably more 46 | appropriate. 47 | """ 48 | 49 | def __init__(self): 50 | super(LoggingEventHandler, self).__init__() 51 | 52 | def OnLogEvent(self, logging_event_data): 53 | """ 54 | This function displays readily available logging information. 55 | 56 | :param logging_event_data: Logging data. 57 | :type logging_event_data: LoggingEventData 58 | :rtype: None 59 | """ 60 | print "--------Log Event Received----------" 61 | print "Category: %s" % logging_event_data.GetCategoryName() 62 | print "Priority Value: %s" % logging_event_data.GetPriority() 63 | print "Priority Name: %s" % logging_event_data.GetPriorityName() 64 | print "Timestamp: %s" % logging_event_data.GetTimestamp() 65 | print "NDC: %s" % logging_event_data.GetNDC() 66 | print "Thread: %s" % logging_event_data.GetThreadName() 67 | print "Message: %s" % logging_event_data.GetLogMessage() 68 | print "------------------------------------\n" 69 | 70 | 71 | def main(): 72 | """ 73 | Example entry point; notice the volume of data that the logging event handler 74 | prints out on debug despite the fact that very little really happens in this 75 | example. Because of this, it may be better to have the logger set to lower 76 | level in order to provide a more concise, focused log. 77 | 78 | :rtype: None 79 | """ 80 | 81 | # Retrieve singleton reference to system object 82 | system = PySpin.System.GetInstance() 83 | 84 | # Create and register the logging event handler 85 | # 86 | # *** NOTES *** 87 | # Logging events are registered to the system. Take note that a logging 88 | # event handler is very verbose when the logging level is set to debug. 89 | # 90 | # *** LATER *** 91 | # Logging events must be unregistered manually. This must be done prior to 92 | # releasing the system and while the device events are still in scope. 93 | logging_event_handler = LoggingEventHandler() 94 | system.RegisterLoggingEvent(logging_event_handler) 95 | 96 | # Set callback priority level 97 | # 98 | # *** NOTES *** 99 | # Please see documentation for up-to-date information on the logging 100 | # philosophies of the Spinnaker SDK. 101 | system.SetLoggingEventPriorityLevel(LOGGING_LEVEL) 102 | 103 | # Retrieve list of cameras from the system 104 | cam_list = system.GetCameras() 105 | 106 | num_cams = cam_list.GetSize() 107 | 108 | print "Number of cameras detected: %i" % num_cams 109 | 110 | # Clear camera list before releasing system 111 | cam_list.Clear() 112 | 113 | # Unregister logging event handler 114 | # 115 | # *** NOTES *** 116 | # It is important to unregister all logging events from the system. 117 | system.UnregisterLoggingEvent(logging_event_handler) 118 | 119 | # Release system 120 | system.ReleaseInstance() 121 | 122 | raw_input("Done! Press Enter to exit...") 123 | 124 | 125 | if __name__ == "__main__": 126 | main() 127 | -------------------------------------------------------------------------------- /NodeMapCallback.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # NodeMapCallback.py shows how to use nodemap callbacks. It relies 20 | # on information provided in the Enumeration, Acquisition, and NodeMapInfo 21 | # examples. As callbacks are very similar to events, it may be a good idea to 22 | # explore this example prior to tackling the events examples. 23 | # 24 | # This example focuses on creating, registering, using, and unregistering 25 | # callbacks. A callback requires a callback class with a callback function signature, 26 | # which allows it to be registered to and access a node. Events follow this same pattern. 27 | # 28 | # Once comfortable with NodeMapCallback, we suggest checking out any of the 29 | # events examples: DeviceEvents, EnumerationEvents, ImageEvents, or Logging. 30 | 31 | import PySpin 32 | 33 | 34 | class HeightNodeCallback(PySpin.NodeCallback): 35 | """ 36 | This is the first of two callback classes. This callback will be registered to the height node. 37 | Node callbacks must inherit from NodeCallback, and must implement CallbackFunction with the same function signature. 38 | 39 | NOTE: Instances of callback classes must not go out of scope until they are deregistered, otherwise segfaults 40 | will occur. 41 | """ 42 | def __init__(self): 43 | super(HeightNodeCallback, self).__init__() 44 | 45 | def CallbackFunction(self, node): 46 | """ 47 | This function gets called when the height node changes and triggers a callback. 48 | 49 | :param node: Height node. 50 | :type node: INode 51 | :rtype: None 52 | """ 53 | node_height = PySpin.CIntegerPtr(node) 54 | print "Height callback message:\n\tLook! Height changed to %f...\n" % node_height.GetValue() 55 | 56 | 57 | class GainNodeCallback(PySpin.NodeCallback): 58 | """ 59 | This is the second callback class, registered to the gain node. 60 | """ 61 | def __init__(self): 62 | super(GainNodeCallback, self).__init__() 63 | 64 | def CallbackFunction(self, node): 65 | """ 66 | This function gets called when the gain node changes and triggers a callback. 67 | 68 | :param node: Gain node. 69 | :type node: INode 70 | :rtype: None 71 | """ 72 | node_gain = PySpin.CFloatPtr(node) 73 | print "Gain callback message:\n\tLook! Gain changed to %f...\n" % node_gain.GetValue() 74 | 75 | 76 | def configure_callbacks(nodemap): 77 | """ 78 | This function sets up the example by disabling automatic gain, creating the callbacks, and registering them to 79 | their specific nodes. 80 | 81 | :param nodemap: Device nodemap. 82 | :type nodemap: INodeMap 83 | :returns: tuple (result, callback_height, callback_gain) 84 | WHERE 85 | result is True if successful, False otherwise 86 | callback_height is the HeightNodeCallback instance registered to the height node 87 | callback_gain is the GainNodeCallback instance registered to the gain node 88 | :rtype: (bool, HeightNodeCallback, GainNodeCallback) 89 | """ 90 | print "\n*** CONFIGURING CALLBACKS ***\n" 91 | try: 92 | result = True 93 | 94 | # Turn off automatic gain 95 | # 96 | # *** NOTES *** 97 | # Automatic gain prevents the manual configuration of gain and needs to 98 | # be turned off for this example. 99 | # 100 | # *** LATER *** 101 | # Automatic exposure is turned off at the end of the example in order 102 | # to restore the camera to its default state. 103 | node_gain_auto = PySpin.CEnumerationPtr(nodemap.GetNode("GainAuto")) 104 | if not PySpin.IsAvailable(node_gain_auto) or not PySpin.IsWritable(node_gain_auto): 105 | print "Unable to disable automatic gain (node retrieval). Aborting..." 106 | return False 107 | 108 | node_gain_auto_off = PySpin.CEnumEntryPtr(node_gain_auto.GetEntryByName("Off")) 109 | if not PySpin.IsAvailable(node_gain_auto_off) or not PySpin.IsReadable(node_gain_auto_off): 110 | print "Unable to disable automatic gain (enum entry retrieval). Aborting..." 111 | return False 112 | 113 | node_gain_auto.SetIntValue(node_gain_auto_off.GetValue()) 114 | print "Automatic gain disabled..." 115 | 116 | # Register callback to height node 117 | # 118 | # *** NOTES *** 119 | # Callbacks need to be registered to nodes, which should be writable 120 | # if the callback is to ever be triggered. Also ensure that the callback 121 | # instance does not go out of scope, as it will get garbage-collected 122 | # and a segfault will result once the callback actually occurs. 123 | # 124 | # *** LATER *** 125 | # Each callback needs to be unregistered individually before releasing 126 | # the system or an exception will be thrown. 127 | node_height = PySpin.CIntegerPtr(nodemap.GetNode("Height")) 128 | if not PySpin.IsAvailable(node_height) or not PySpin.IsWritable(node_height): 129 | print "Unable to retrieve height. Aborting...\n" 130 | return False 131 | 132 | print "Height ready..." 133 | 134 | callback_height = HeightNodeCallback() 135 | PySpin.RegisterNodeCallback(node_height.GetNode(), callback_height) 136 | 137 | print "Height callback registered..." 138 | 139 | # Register callback to gain node 140 | # 141 | # *** NOTES *** 142 | # Depending on the specific goal of the function, it can be important 143 | # to notice the node type that a callback is registered to. Notice in 144 | # the callback functions above that the callback registered to height 145 | # casts its node as an integer whereas the callback registered to gain 146 | # casts as a float. 147 | # 148 | # *** LATER *** 149 | # Each callback needs to be unregistered individually before releasing 150 | # the system or an exception will be thrown. 151 | node_gain = PySpin.CFloatPtr(nodemap.GetNode("Gain")) 152 | if not PySpin.IsAvailable(node_gain) or not PySpin.IsWritable(node_gain): 153 | print "Unable to retrieve gain. Aborting...\n" 154 | return False 155 | 156 | print "Gain ready..." 157 | 158 | callback_gain = GainNodeCallback() 159 | PySpin.RegisterNodeCallback(node_gain.GetNode(), callback_gain) 160 | print "Gain callback registered...\n" 161 | 162 | except PySpin.SpinnakerException as ex: 163 | print "Error: %s" % ex 164 | result = False 165 | 166 | return result, callback_height, callback_gain 167 | 168 | 169 | def change_height_and_gain(nodemap): 170 | """ 171 | This function demonstrates the triggering of the nodemap callbacks. First it 172 | changes height, which executes the callback registered to the height node, and 173 | then it changes gain, which executes the callback registered to the gain node. 174 | 175 | :param nodemap: Device nodemap. 176 | :type nodemap: INodeMap 177 | :return: True if successful, False otherwise. 178 | :rtype: bool 179 | """ 180 | print "\n***CHANGE HEIGHT & GAIN ***\n" 181 | 182 | try: 183 | result = True 184 | 185 | # Change height to trigger height callback 186 | # 187 | # *** NOTES *** 188 | # Notice that changing the height only triggers the callback function 189 | # registered to the height node. 190 | node_height = PySpin.CIntegerPtr(nodemap.GetNode("Height")) 191 | if not PySpin.IsAvailable(node_height) or not PySpin.IsWritable(node_height) \ 192 | or node_height.GetInc() == 0 or node_height.GetMax() == 0: 193 | 194 | print "Unable to retrieve height. Aborting..." 195 | return False 196 | 197 | height_to_set = node_height.GetMax() 198 | 199 | print "Regular function message:\n\tHeight about to be changed to %i...\n" % height_to_set 200 | 201 | node_height.SetValue(height_to_set) 202 | 203 | # Change gain to trigger gain callback 204 | # 205 | # *** NOTES *** 206 | # The same is true of changing the gain node; changing a node will 207 | # only ever trigger the callback function (or functions) currently 208 | # registered to it. 209 | node_gain = PySpin.CFloatPtr(nodemap.GetNode("Gain")) 210 | if not PySpin.IsAvailable(node_gain) or not PySpin.IsWritable(node_gain) or node_gain.GetMax() == 0: 211 | print "Unable to retrieve gain..." 212 | return False 213 | 214 | gain_to_set = node_gain.GetMax() / 2.0 215 | 216 | print "Regular function message:\n\tGain about to be changed to %f...\n" % gain_to_set 217 | node_gain.SetValue(gain_to_set) 218 | 219 | except PySpin.SpinnakerException as ex: 220 | print "Error: %s" % ex 221 | result = False 222 | 223 | return result 224 | 225 | 226 | def reset_callbacks(nodemap, callback_height, callback_gain): 227 | """ 228 | This function cleans up the example by deregistering the callbacks and 229 | turning automatic gain back on. 230 | 231 | :param nodemap: Device nodemap. 232 | :param callback_height: Height node callback instance to deregister. 233 | :param callback_gain: Gain node callback instance to deregister. 234 | :type nodemap: INodeMap 235 | :type callback_height: HeightNodeCallback 236 | :type callback_gain: GainNodeCallback 237 | :return: True if successful, False otherwise. 238 | :rtype: bool 239 | """ 240 | try: 241 | result = True 242 | 243 | # Deregister callbacks 244 | # 245 | # *** NOTES *** 246 | # It is important to deregister each callback function from each node 247 | # that it is registered to. 248 | PySpin.DeregisterNodeCallback(callback_height) 249 | PySpin.DeregisterNodeCallback(callback_gain) 250 | 251 | print "Callbacks deregistered..." 252 | 253 | # Turn automatic gain back on 254 | # 255 | # *** NOTES *** 256 | # Automatic gain is turned back on in order to restore the camera to 257 | # its default state. 258 | node_gain_auto = PySpin.CEnumerationPtr(nodemap.GetNode("GainAuto")) 259 | if not PySpin.IsAvailable(node_gain_auto) or not PySpin.IsWritable(node_gain_auto): 260 | print "Unable to enable automatic gain (node retrieval). Aborting..." 261 | return False 262 | 263 | node_gain_auto_continuous = PySpin.CEnumEntryPtr(node_gain_auto.GetEntryByName("Continuous")) 264 | if not PySpin.IsAvailable(node_gain_auto_continuous) or not PySpin.IsReadable(node_gain_auto_continuous): 265 | print "Unable to enable automatic gain (enum entry retrieval). Aborting..." 266 | return False 267 | 268 | node_gain_auto.SetIntValue(node_gain_auto_continuous.GetValue()) 269 | print "Automatic gain disabled..." 270 | 271 | except PySpin.SpinnakerException as ex: 272 | print "Error: %s" % ex 273 | result = False 274 | 275 | return result 276 | 277 | 278 | def print_device_info(nodemap): 279 | """ 280 | This function prints the device information of the camera from the transport 281 | layer; please see NodeMapInfo example for more in-depth comments on printing 282 | device information from the nodemap. 283 | 284 | :param nodemap: Transport layer device nodemap. 285 | :type nodemap: INodeMap 286 | :returns: True if successful, False otherwise. 287 | :rtype: bool 288 | """ 289 | 290 | print "*** DEVICE INFORMATION ***\n" 291 | 292 | try: 293 | result = True 294 | node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) 295 | 296 | if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): 297 | features = node_device_information.GetFeatures() 298 | for feature in features: 299 | node_feature = PySpin.CValuePtr(feature) 300 | print "%s: %s" % (node_feature.GetName(), 301 | node_feature.ToString() if PySpin.IsReadable(node_feature) else "Node not readable") 302 | 303 | else: 304 | print "Device control information not available." 305 | 306 | except PySpin.SpinnakerException as ex: 307 | print "Error: %s" % ex 308 | return False 309 | 310 | return result 311 | 312 | 313 | def run_single_camera(cam): 314 | """ 315 | This function acts as the body of the example; please see NodeMapInfo example 316 | for more in-depth comments on setting up cameras. 317 | 318 | :param cam: Camera to setup and run on. 319 | :type cam: CameraPtr 320 | :return: True if successful, False otherwise. 321 | :rtype: bool 322 | """ 323 | try: 324 | result = True 325 | 326 | # Retrieve TL device nodemap and print device information 327 | nodemap_tldevice = cam.GetTLDeviceNodeMap() 328 | 329 | result &= print_device_info(nodemap_tldevice) 330 | 331 | # Initialize camera 332 | cam.Init() 333 | 334 | # Retrieve GenICam nodemap 335 | nodemap = cam.GetNodeMap() 336 | 337 | # Configure callbacks 338 | err, callback_height, callback_gain = configure_callbacks(nodemap) 339 | if not err: 340 | return err 341 | 342 | # Change height and gain to trigger callbacks 343 | result &= change_height_and_gain(nodemap) 344 | 345 | # Reset callbacks 346 | result &= reset_callbacks(nodemap, callback_height, callback_gain) 347 | 348 | # Deinitialize camera 349 | cam.DeInit() 350 | 351 | except PySpin.SpinnakerException as ex: 352 | print "Error: %s" % ex 353 | return False 354 | 355 | return result 356 | 357 | 358 | def main(): 359 | """ 360 | Example entry point; please see Enumeration example for more in-depth 361 | comments on preparing and cleaning up the system. 362 | 363 | :return: True if successful, False otherwise. 364 | :rtype: bool 365 | """ 366 | result = True 367 | 368 | # Retrieve singleton reference to system object 369 | system = PySpin.System.GetInstance() 370 | 371 | # Retrieve list of cameras from the system 372 | cam_list = system.GetCameras() 373 | 374 | num_cameras = cam_list.GetSize() 375 | 376 | print "Number of cameras detected: %d" % num_cameras 377 | 378 | # Finish if there are no cameras 379 | if num_cameras == 0: 380 | 381 | # Clear camera list before releasing system 382 | cam_list.Clear() 383 | 384 | # Release system 385 | system.ReleaseInstance() 386 | 387 | print "Not enough cameras!" 388 | raw_input("Done! Press Enter to exit...") 389 | return False 390 | 391 | # Run example on each camera 392 | for i in range(num_cameras): 393 | cam = cam_list.GetByIndex(i) 394 | 395 | print "Running example for camera %d..." % i 396 | 397 | result &= run_single_camera(cam) 398 | print "Camera %d example complete..." % i 399 | 400 | # Release reference to camera 401 | # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically 402 | # cleaned up when going out of scope. 403 | # The usage of del is preferred to assigning the variable to None. 404 | del cam 405 | 406 | # Clear camera list before releasing system 407 | 408 | cam_list.Clear() 409 | 410 | # Release instance 411 | system.ReleaseInstance() 412 | 413 | raw_input("Done! Press Enter to exit...") 414 | return result 415 | 416 | if __name__ == "__main__": 417 | main() 418 | -------------------------------------------------------------------------------- /NodeMapInfo_QuickSpin.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # NodeMapInfo_QuickSpin.py shows how to interact with nodes 20 | # using the QuickSpin API. QuickSpin is a subset of the Spinnaker library 21 | # that allows for simpler node access and control. 22 | # 23 | # This example demonstrates the retrieval of information from both the 24 | # transport layer and the camera. Because the focus of this example is node 25 | # access, which is where QuickSpin and regular Spinnaker differ, this 26 | # example differs from NodeMapInfo quite a bit. 27 | # 28 | # A much wider range of topics is covered in the full Spinnaker examples than 29 | # in the QuickSpin ones. There are only enough QuickSpin examples to 30 | # demonstrate node access and to get started with the API; please see full 31 | # Spinnaker examples for further or specific knowledge on a topic. 32 | 33 | import PySpin 34 | 35 | 36 | def print_transport_layer_device_info(cam): 37 | """ 38 | Prints device information from the transport layer. 39 | 40 | *** NOTES *** 41 | In QuickSpin, accessing device information on the transport layer is 42 | accomplished via a camera's TLDevice property. The TLDevice property 43 | houses nodes related to general device information such as the three 44 | demonstrated below, device access status, XML and GUI paths and 45 | locations, and GEV information to name a few. The TLDevice property 46 | allows access to nodes that would generally be retrieved through the 47 | TL device nodemap in full Spinnaker. 48 | 49 | Notice that each node is checked for availability and readability 50 | prior to value retrieval. Checking for availability and readability 51 | (or writability when applicable) whenever a node is accessed is 52 | important in terms of error handling. If a node retrieval error 53 | occurs but remains unhandled, an exception is thrown. 54 | 55 | :param cam: Camera to get information from. 56 | :type cam: CameraPtr 57 | :return: True if successful, False otherwise. 58 | :rtype: bool 59 | """ 60 | try: 61 | result = True 62 | 63 | # Print device serial number 64 | if cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: 65 | print "Device serial number: %s" % cam.TLDevice.DeviceSerialNumber.ToString() 66 | 67 | else: 68 | print "Device serial number: unavailable" 69 | result = False 70 | 71 | # Print device vendor name 72 | # 73 | # *** NOTE *** 74 | # To check node readability/writability, you can either 75 | # compare its access mode with RO, RW, etc. or you can use 76 | # the IsReadable/IsWritable functions on the node. 77 | if PySpin.IsReadable(cam.TLDevice.DeviceVendorName): 78 | print "Device vendor name: %s" % cam.TLDevice.DeviceVendorName.ToString() 79 | else: 80 | print "Device vendor name: unavailable" 81 | result = False 82 | 83 | # Print device display name 84 | if PySpin.IsReadable(cam.TLDevice.DeviceDisplayName): 85 | print "Device display name: %s" % cam.TLDevice.DeviceDisplayName.ToString() 86 | else: 87 | print "Device display name: unavailable" 88 | result = False 89 | 90 | except PySpin.SpinnakerException as ex: 91 | print "Error: %s" % ex 92 | return False 93 | 94 | return result 95 | 96 | 97 | def print_transport_layer_stream_info(cam): 98 | """ 99 | Prints stream information from transport layer. 100 | 101 | *** NOTES *** 102 | In QuickSpin, accessing stream information on the transport layer is 103 | accomplished via a camera's TLStream property. The TLStream property 104 | houses nodes related to streaming such as the two demonstrated below, 105 | buffer information, and GEV packet information to name a few. The 106 | TLStream property allows access to nodes that would generally be 107 | retrieved through the TL stream nodemap in full Spinnaker. 108 | 109 | :param cam: Camera to get information from. 110 | :type cam: CameraPtr 111 | :return: True if successful, False otherwise. 112 | :rtype: bool 113 | """ 114 | try: 115 | result = True 116 | 117 | # Print stream ID 118 | if cam.TLStream.StreamID.GetAccessMode() == PySpin.RO: 119 | print "Stream ID: %s" % cam.TLStream.StreamID.ToString() 120 | else: 121 | print "Stream ID: unavailable" 122 | result = False 123 | 124 | # Print stream type 125 | if PySpin.IsReadable(cam.TLStream.StreamType): 126 | print "Stream type: %s" % cam.TLStream.StreamType.ToString() 127 | else: 128 | print "Stream type: unavailable" 129 | result = False 130 | 131 | except PySpin.SpinnakerException as ex: 132 | print "Error: %s" % ex 133 | return False 134 | 135 | return result 136 | 137 | 138 | def print_transport_layer_interface_info(interface): 139 | """ 140 | Prints stream information from the transport layer. 141 | 142 | *** NOTES *** 143 | In QuickSpin, accessing interface information is accomplished via an 144 | interface's TLInterface property. The TLInterface property houses 145 | nodes that hold information about the interface such as the three 146 | demonstrated below, other general interface information, and 147 | GEV addressing information. The TLInterface property allows access to 148 | nodes that would generally be retrieved through the interface nodemap 149 | in full Spinnaker. 150 | 151 | Interface nodes should also always be checked for availability and 152 | readability (or writability when applicable). If a node retrieval 153 | error occurs but remains unhandled, an exception is thrown. 154 | 155 | :param interface: Interface to get information from. 156 | :type interface: InterfacePtr 157 | :return: True if successful, False otherwise. 158 | :rtype: bool 159 | """ 160 | try: 161 | result = True 162 | 163 | # Print interface display name 164 | if interface.TLInterface.InterfaceDisplayName.GetAccessMode() == PySpin.RO: 165 | print "Interface display name: %s" % interface.TLInterface.InterfaceDisplayName.ToString() 166 | else: 167 | print "Interface display name: unavailable" 168 | result = False 169 | 170 | # Print interface ID 171 | if interface.TLInterface.InterfaceID.GetAccessMode() == PySpin.RO: 172 | print "Interface ID: %s" % interface.TLInterface.InterfaceID.ToString() 173 | else: 174 | print "Interface ID: unavailable" 175 | result = False 176 | 177 | # Print interface type 178 | if PySpin.IsReadable(interface.TLInterface.InterfaceType.GetAccessMode()): 179 | print "Interface type: %s" % interface.TLInterface.InterfaceType.ToString() 180 | else: 181 | print "Interface type: unavailable" 182 | result = False 183 | 184 | except PySpin.SpinnakerException as ex: 185 | print "Error: %s" % ex 186 | return False 187 | 188 | return result 189 | 190 | 191 | def print_genicam_device_info(cam): 192 | """ 193 | Prints device information from the camera. 194 | 195 | *** NOTES *** 196 | Most camera interaction happens through GenICam nodes. The 197 | advantages of these nodes is that there is a lot more of them, they 198 | allow for a much deeper level of interaction with a camera, and no 199 | intermediate property (i.e. TLDevice or TLStream) is required. The 200 | disadvantage is that they require initialization. 201 | 202 | :param cam: Camera to get information from. 203 | :type cam: CameraPtr 204 | :return: True if successful, False otherwise. 205 | :rtype: bool 206 | """ 207 | try: 208 | result = True 209 | 210 | # Print exposure time 211 | if cam.ExposureTime.GetAccessMode() == PySpin.RO or cam.ExposureTime.GetAccessMode() == PySpin.RW: 212 | print "Exposure time: %s" % cam.ExposureTime.ToString() 213 | else: 214 | print "Exposure time: unavailable" 215 | result = False 216 | 217 | # Print black level 218 | if PySpin.IsReadable(cam.BlackLevel): 219 | print "Black level: %s" % cam.BlackLevel.ToString() 220 | else: 221 | print "Black level: unavailable" 222 | result = False 223 | 224 | # Print height 225 | if PySpin.IsReadable(cam.Height): 226 | print "Height: %s" % cam.Height.ToString() 227 | else: 228 | print "Height: unavailable" 229 | result = False 230 | 231 | except PySpin.SpinnakerException as ex: 232 | print "Error: %s" % ex 233 | return False 234 | 235 | return result 236 | 237 | 238 | def main(): 239 | """ 240 | Example entry point; this function prints transport layer information from 241 | each interface and transport and GenICam information from each camera. 242 | 243 | :return: True if successful, False otherwise. 244 | :rtype: bool 245 | """ 246 | result = True 247 | 248 | # Retrieve singleton reference to system object 249 | sys = PySpin.System.GetInstance() 250 | 251 | # Retrieve list of cameras from the system 252 | cam_list = sys.GetCameras() 253 | 254 | num_cams = len(cam_list) 255 | 256 | print "Number of cameras detected: %i \n" % num_cams 257 | 258 | # Retrieve list of interfaces from the system 259 | iface_list = sys.GetInterfaces() 260 | 261 | num_ifaces = iface_list.GetSize() 262 | 263 | print "Number of interfaces detected: %i \n" % num_ifaces 264 | 265 | # Print information on each interface 266 | # 267 | # *** NOTES *** 268 | # All USB 3 Vision and GigE Vision interfaces should enumerate for 269 | # Spinnaker. 270 | print "\n*** PRINTING INTERFACE INFORMATION ***\n" 271 | 272 | for i in range(num_ifaces): 273 | result &= print_transport_layer_interface_info(iface_list[i]) 274 | 275 | # Print general device information on each camera from transport layer 276 | # 277 | # *** NOTES *** 278 | # Transport layer nodes do not require initialization in order to interact 279 | # with them. 280 | print "\n*** PRINTING TRANSPORT LAYER DEVICE INFORMATION ***\n" 281 | 282 | for i in range(num_cams): 283 | result &= print_transport_layer_device_info(cam_list[i]) 284 | 285 | # Print streaming information on each camera from transport layer 286 | # 287 | # *** NOTES *** 288 | # Again, initialization is not required to print information from the 289 | # transport layer; this is equally true of streaming information. 290 | print "\n*** PRINTING TRANSPORT LAYER STREAMING INFORMATION ***\n" 291 | 292 | for i in range(num_cams): 293 | result &= print_transport_layer_stream_info(cam_list[i]) 294 | 295 | # Print device information on each camera from GenICam nodemap 296 | # 297 | # *** NOTES *** 298 | # GenICam nodes require initialization in order to interact with 299 | # them; as such, this loop initializes the camera, prints some information 300 | # from the GenICam nodemap, and then deinitializes it. If the camera were 301 | # not initialized, node availability would fail. 302 | print "\n*** PRINTING GENICAM INFORMATION ***\n" 303 | 304 | # NOTE: The CameraList can be iterated over without using an index to grab each camera. 305 | for cam in cam_list: 306 | # Initialize camera 307 | cam.Init() 308 | 309 | # Print info 310 | result &= print_genicam_device_info(cam) 311 | 312 | # Deinitialize camera 313 | cam.DeInit() 314 | 315 | # Delete any references to camera 316 | del cam 317 | 318 | # Clear camera list before releasing system 319 | cam_list.Clear() 320 | 321 | # Clear interface list before releasing system 322 | iface_list.Clear() 323 | 324 | # Release system 325 | sys.ReleaseInstance() 326 | 327 | raw_input("Done! Press Enter to exit...") 328 | return result 329 | 330 | if __name__ == "__main__": 331 | main() 332 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PTGREY-cameras-with-python 2 | A few files explain how to use 'ptgrey' cameras with python. I felt the need to make this because there is not even an introductory code (to take a picture using ptgrey cameras) is available on internet. 3 | -------------------------------------------------------------------------------- /SaveToAvi.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # SaveToAvi.py shows how to create an AVI video from a vector of 20 | # images. It relies on information provided in the Enumeration, Acquisition, 21 | # and NodeMapInfo examples. 22 | # 23 | # This example introduces the AVIRecorder class, which is used to quickly and 24 | # easily create various types of AVI videos. It demonstrates the creation of 25 | # three types: uncompressed, MJPG, and H264. 26 | 27 | import PySpin 28 | 29 | 30 | class AviType: 31 | """'Enum' to select AVI video type to be created and saved""" 32 | UNCOMPRESSED = 0 33 | MJPG = 1 34 | H264 = 2 35 | 36 | chosenAviType = AviType.UNCOMPRESSED # change me! 37 | NUM_IMAGES = 10 # number of images to use in AVI file 38 | 39 | 40 | def save_list_to_avi(nodemap, nodemap_tldevice, images): 41 | """ 42 | This function prepares, saves, and cleans up an AVI video from a vector of images. 43 | 44 | :param nodemap: Device nodemap. 45 | :param nodemap_tldevice: Transport layer device nodemap. 46 | :param images: List of images to save to an AVI video. 47 | :type nodemap: INodeMap 48 | :type nodemap_tldevice: INodeMap 49 | :type images: list of ImagePtr 50 | :return: True if successful, False otherwise. 51 | :rtype: bool 52 | """ 53 | print "*** CREATING VIDEO ***" 54 | 55 | try: 56 | result = True 57 | 58 | # Retrieve device serial number for filename 59 | device_serial_number = "" 60 | node_serial = PySpin.CStringPtr(nodemap_tldevice.GetNode("DeviceSerialNumber")) 61 | 62 | if PySpin.IsAvailable(node_serial) and PySpin.IsReadable(node_serial): 63 | device_serial_number = node_serial.GetValue() 64 | print "Device serial number retrieved as %s..." % device_serial_number 65 | 66 | # Get the current frame rate; acquisition frame rate recorded in hertz 67 | # 68 | # *** NOTES *** 69 | # The video frame rate can be set to anything; however, in order to 70 | # have videos play in real-time, the acquisition frame rate can be 71 | # retrieved from the camera. 72 | 73 | node_acquisition_framerate = PySpin.CFloatPtr(nodemap.GetNode("AcquisitionFrameRate")) 74 | 75 | if not PySpin.IsAvailable(node_acquisition_framerate) and not PySpin.IsReadable(node_acquisition_framerate): 76 | print "Unable to retrieve frame rate. Aborting..." 77 | return False 78 | 79 | framerate_to_set = node_acquisition_framerate.GetValue() 80 | 81 | print "Frame rate to be set to %d..." % framerate_to_set 82 | 83 | # Select option and open AVI filetype with unique filename 84 | # 85 | # *** NOTES *** 86 | # Depending on the filetype, a number of settings need to be set in 87 | # an object called an option. An uncompressed option only needs to 88 | # have the video frame rate set whereas videos with MJPG or H264 89 | # compressions should have more values set. 90 | # 91 | # Once the desired option object is configured, open the AVI file 92 | # with the option in order to create the image file. 93 | # 94 | # Note that the filename does not need to be appended to the 95 | # name of the file. This is because the AVI recorder object takes care 96 | # of the file extension automatically. 97 | # 98 | # *** LATER *** 99 | # Once all images have been added, it is important to close the file - 100 | # this is similar to many other standard file streams. 101 | 102 | avi_recorder = PySpin.AVIRecorder() 103 | 104 | if chosenAviType == AviType.UNCOMPRESSED: 105 | avi_filename = "SaveToAvi-Uncompressed-%s" % device_serial_number 106 | 107 | option = PySpin.AVIOption() 108 | option.frameRate = framerate_to_set 109 | 110 | elif chosenAviType == AviType.MJPG: 111 | avi_filename = "SaveToAvi-MJPG-%s" % device_serial_number 112 | 113 | option = PySpin.MJPGOption() 114 | option.frameRate = framerate_to_set 115 | option.quality = 75 116 | 117 | elif chosenAviType == AviType.H264: 118 | avi_filename = "SaveToAvi-H264-%s" % device_serial_number 119 | 120 | option = PySpin.H264Option() 121 | option.frameRate = framerate_to_set 122 | option.bitrate = 1000000 123 | option.height = images[0].GetHeight() 124 | option.width = images[0].GetWidth() 125 | 126 | else: 127 | print "Error: Unknown AviType. Aborting..." 128 | return False 129 | 130 | avi_recorder.AVIOpen(avi_filename, option) 131 | 132 | # Construct and save AVI video 133 | # 134 | # *** NOTES *** 135 | # Although the video file has been opened, images must be individually 136 | # appended in order to construct the video. 137 | print "Appending %d images to AVI file: %s.avi..." % (len(images), avi_filename) 138 | 139 | for i in range(len(images)): 140 | avi_recorder.AVIAppend(images[i]) 141 | print "Appended image %d..." % i 142 | 143 | # Close AVI file 144 | # 145 | # *** NOTES *** 146 | # Once all images have been appended, it is important to close the 147 | # AVI file. Notice that once an AVI file has been closed, no more 148 | # images can be added. 149 | 150 | avi_recorder.AVIClose() 151 | print "Video saved at %s.avi" % avi_filename 152 | 153 | except PySpin.SpinnakerException as ex: 154 | print "Error: %s" % ex 155 | return False 156 | 157 | return result 158 | 159 | 160 | def print_device_info(nodemap): 161 | """ 162 | This function prints the device information of the camera from the transport 163 | layer; please see NodeMapInfo example for more in-depth comments on printing 164 | device information from the nodemap. 165 | 166 | :param nodemap: Transport layer device nodemap. 167 | :type nodemap: INodeMap 168 | :return: True if successful, False otherwise. 169 | :rtype: bool 170 | """ 171 | print "\n*** DEVICE INFORMATION ***\n" 172 | 173 | try: 174 | result = True 175 | node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) 176 | 177 | if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): 178 | features = node_device_information.GetFeatures() 179 | for feature in features: 180 | node_feature = PySpin.CValuePtr(feature) 181 | print "%s: %s" % (node_feature.GetName(), 182 | node_feature.ToString() if PySpin.IsReadable(node_feature) else "Node not readable") 183 | 184 | else: 185 | print "Device control information not available." 186 | 187 | except PySpin.SpinnakerException as ex: 188 | print "Error: %s" % ex 189 | return False 190 | 191 | return result 192 | 193 | 194 | def acquire_images(cam, nodemap): 195 | """ 196 | This function acquires 10 images from a device, stores them in a list, and returns the list. 197 | please see the Acquisition example for more in-depth comments on acquiring images. 198 | 199 | :param cam: Camera to acquire images from. 200 | :param nodemap: Device nodemap. 201 | :type cam: CameraPtr 202 | :type nodemap: INodeMap 203 | :return: True if successful, False otherwise. 204 | :rtype: bool 205 | """ 206 | print "*** IMAGE ACQUISITION ***\n" 207 | try: 208 | result = True 209 | 210 | # Set acquisition mode to continuous 211 | node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode("AcquisitionMode")) 212 | if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): 213 | print "Unable to set acquisition mode to continuous (enum retrieval). Aborting..." 214 | return False 215 | 216 | # Retrieve entry node from enumeration node 217 | node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName("Continuous") 218 | if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable(node_acquisition_mode_continuous): 219 | print "Unable to set acquisition mode to continuous (entry retrieval). Aborting..." 220 | return False 221 | 222 | acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() 223 | 224 | node_acquisition_mode.SetIntValue(acquisition_mode_continuous) 225 | 226 | print "Acquisition mode set to continuous..." 227 | 228 | # Begin acquiring images 229 | cam.BeginAcquisition() 230 | 231 | print "Acquiring images..." 232 | 233 | # Retrieve, convert, and save images 234 | images = list() 235 | 236 | for i in range(NUM_IMAGES): 237 | try: 238 | # Retrieve next received image 239 | image_result = cam.GetNextImage() 240 | 241 | # Ensure image completion 242 | if image_result.IsIncomplete(): 243 | print "Image incomplete with image status %d..." % image_result.GetImageStatus() 244 | 245 | else: 246 | # Print image information; height and width recorded in pixels 247 | width = image_result.GetWidth() 248 | height = image_result.GetHeight() 249 | print "Grabbed Image %d, width = %d, height = %d" % (i, width, height) 250 | 251 | # Convert image to mono 8 and append to list 252 | images.append(image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR)) 253 | 254 | # Release image 255 | image_result.Release() 256 | print "" 257 | 258 | except PySpin.SpinnakerException as ex: 259 | print "Error: %s" % ex 260 | result = False 261 | 262 | # End acquisition 263 | cam.EndAcquisition() 264 | 265 | except PySpin.SpinnakerException as ex: 266 | print "Error: %s" % ex 267 | result = False 268 | 269 | return result, images 270 | 271 | 272 | def run_single_camera(cam): 273 | """ 274 | This function acts as the body of the example; please see NodeMapInfo example 275 | for more in-depth comments on setting up cameras. 276 | 277 | :param cam: Camera to run example on. 278 | :type cam: CameraPtr 279 | :return: True if successful, False otherwise. 280 | :rtype: bool 281 | """ 282 | 283 | try: 284 | result = True 285 | 286 | # Retrieve TL device nodemap and print device information 287 | nodemap_tldevice = cam.GetTLDeviceNodeMap() 288 | 289 | result &= print_device_info(nodemap_tldevice) 290 | 291 | # Initialize camera 292 | cam.Init() 293 | 294 | # Retrieve GenICam nodemap 295 | nodemap = cam.GetNodeMap() 296 | 297 | # Acquire list of images 298 | err, images = acquire_images(cam, nodemap) 299 | if err < 0: 300 | return err 301 | 302 | result &= save_list_to_avi(nodemap, nodemap_tldevice, images) 303 | 304 | # Deinitialize camera 305 | cam.DeInit() 306 | 307 | except PySpin.SpinnakerException as ex: 308 | print "Error: %s" % ex 309 | result = False 310 | 311 | return result 312 | 313 | 314 | def main(): 315 | """ 316 | Example entry point; please see Enumeration example for more in-depth 317 | comments on preparing and cleaning up the system. 318 | 319 | :return: True if successful, False otherwise. 320 | :rtype: bool 321 | """ 322 | 323 | # Retrieve singleton reference to system object 324 | system = PySpin.System.GetInstance() 325 | 326 | # Retrieve list of cameras from the system 327 | cam_list = system.GetCameras() 328 | 329 | num_cameras = cam_list.GetSize() 330 | 331 | print "Number of cameras detected:", num_cameras 332 | # Finish if there are no cameras 333 | if num_cameras == 0: 334 | # Clear camera list before releasing system 335 | cam_list.Clear() 336 | 337 | # Release system 338 | system.ReleaseInstance() 339 | 340 | print "Not enough cameras!" 341 | raw_input("Done! Press Enter to exit...") 342 | return False 343 | 344 | # Run example on each camera 345 | for i in range(num_cameras): 346 | cam = cam_list.GetByIndex(i) 347 | 348 | print "Running example for camera %d..." % i 349 | 350 | result = run_single_camera(cam) 351 | print "Camera %d example complete..." % i 352 | 353 | # Release reference to camera 354 | del cam 355 | 356 | # Clear camera list before releasing system 357 | cam_list.Clear() 358 | 359 | # Release instance 360 | system.ReleaseInstance() 361 | 362 | raw_input("Done! Press Enter to exit...") 363 | return result 364 | 365 | if __name__ == "__main__": 366 | main() 367 | -------------------------------------------------------------------------------- /SpinUpdate.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # SpinUpdate.py is a sample firmware updater application that takes in 20 | # command line arguments. The example also demonstrates usage of callback 21 | # functions to keep track of current update progress. 22 | # 23 | # Run with arguments in format (no quotes): "-R -P -UU " 24 | 25 | import PySpin 26 | import sys 27 | 28 | 29 | last_action = "" 30 | 31 | 32 | def progress_callback(action, address, global_percent, curr_percent): 33 | """ 34 | Example progress callback function. 35 | NOTE: This function must take exactly 4 arguments, 36 | otherwise the update process will hang/crash! 37 | 38 | :param action: Current action being done in firmware update. 39 | :param address: Address in camera being written to. 40 | :param global_percent: Global completion percentage of update. 41 | :param curr_percent: Completion percentage of current action. 42 | :type action: str 43 | :type address: int 44 | :type global_percent: int 45 | :type curr_percent: int 46 | :rtype: int 47 | """ 48 | global last_action 49 | if action != last_action: 50 | # Prints action only if changed from previous one 51 | print "Action: %s" % action 52 | last_action = action 53 | 54 | return 1 55 | 56 | 57 | def message_callback(message): 58 | """ 59 | Example message callback function. 60 | NOTE: This function must take exactly 1 argument, 61 | otherwise the update process will hang/crash! 62 | 63 | :param message: Message from updator. 64 | :type message: str 65 | :rtype: None 66 | """ 67 | print "Message: %s" % message 68 | 69 | 70 | def main(): 71 | # Register callbacks 72 | PySpin.SetProgressCallback(progress_callback) 73 | PySpin.SetMessageCallback(message_callback) 74 | 75 | # Example usage for firmware update: 76 | # Use either UpdateFirmware() or UpdateFirmwareConsole(): 77 | # 78 | # cmd = "-R3932019 C:\\firmware\\bfly2_u3_python1300.zim" # Add -P to argument list for callbacks 79 | # return UpdateFirmware(cmd); 80 | 81 | return PySpin.UpdateFirmwareConsole(sys.argv) # uses command line args 82 | 83 | if __name__ == '__main__': 84 | main() 85 | -------------------------------------------------------------------------------- /Trigger.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # Trigger.py shows how to trigger the camera. It relies on information 20 | # provided in the Enumeration, Acquisition, and NodeMapInfo examples. 21 | # 22 | # It can also be helpful to familiarize yourself with the ImageFormatControl 23 | # and Exposure examples. As they are somewhat shorter and simpler, either 24 | # provides a strong introduction to camera customization. 25 | # 26 | # This example shows the process of configuring, using, and cleaning up a 27 | # camera for use with both a software and a hardware trigger. 28 | 29 | import PySpin 30 | 31 | NUM_IMAGES = 10 # number of images to grab 32 | 33 | 34 | class TriggerType: 35 | SOFTWARE = 1 36 | HARDWARE = 2 37 | 38 | 39 | CHOSEN_TRIGGER = TriggerType.SOFTWARE 40 | 41 | 42 | def configure_trigger(cam): 43 | """ 44 | This function configures the camera to use a trigger. First, trigger mode is 45 | set to off in order to select the trigger source. Once the trigger source 46 | has been selected, trigger mode is then enabled, which has the camera 47 | capture only a single image upon the execution of the chosen trigger. 48 | 49 | :param cam: Camera to configure trigger for. 50 | :type cam: CameraPtr 51 | :return: True if successful, False otherwise. 52 | :rtype: bool 53 | """ 54 | result = True 55 | 56 | print "*** CONFIGURING TRIGGER ***\n" 57 | 58 | if CHOSEN_TRIGGER == TriggerType.SOFTWARE: 59 | print "Software trigger chosen ..." 60 | elif CHOSEN_TRIGGER == TriggerType.HARDWARE: 61 | print "Hardware trigger chose ..." 62 | 63 | try: 64 | # Ensure trigger mode off 65 | # The trigger must be disabled in order to configure whether the source 66 | # is software or hardware. 67 | nodemap = cam.GetNodeMap() 68 | node_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode("TriggerMode")) 69 | if not PySpin.IsAvailable(node_trigger_mode) or not PySpin.IsReadable(node_trigger_mode): 70 | print "Unable to disable trigger mode (node retrieval). Aborting..." 71 | return False 72 | 73 | node_trigger_mode_off = node_trigger_mode.GetEntryByName("Off") 74 | if not PySpin.IsAvailable(node_trigger_mode_off) or not PySpin.IsReadable(node_trigger_mode_off): 75 | print "Unable to disable trigger mode (enum entry retrieval). Aborting..." 76 | return False 77 | 78 | node_trigger_mode.SetIntValue(node_trigger_mode_off.GetValue()) 79 | 80 | print "Trigger mode disabled..." 81 | 82 | # Select trigger source 83 | # The trigger source must be set to hardware or software while trigger 84 | # mode is off. 85 | node_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode("TriggerSource")) 86 | if not PySpin.IsAvailable(node_trigger_source) or not PySpin.IsWritable(node_trigger_source): 87 | print "Unable to get trigger source (node retrieval). Aborting..." 88 | return False 89 | 90 | if CHOSEN_TRIGGER == TriggerType.SOFTWARE: 91 | node_trigger_source_software = node_trigger_source.GetEntryByName("Software") 92 | if not PySpin.IsAvailable(node_trigger_source_software) or not PySpin.IsReadable( 93 | node_trigger_source_software): 94 | print "Unable to set trigger source (enum entry retrieval). Aborting..." 95 | return False 96 | node_trigger_source.SetIntValue(node_trigger_source_software.GetValue()) 97 | 98 | elif CHOSEN_TRIGGER == TriggerType.HARDWARE: 99 | node_trigger_source_hardware = node_trigger_source.GetEntryByName("Line0") 100 | if not PySpin.IsAvailable(node_trigger_source_hardware) or not PySpin.IsReadable( 101 | node_trigger_source_hardware): 102 | print "Unable to set trigger source (enum entry retrieval). Aborting..." 103 | return False 104 | node_trigger_source.SetIntValue(node_trigger_source_hardware.GetValue()) 105 | 106 | # Turn trigger mode on 107 | # Once the appropriate trigger source has been set, turn trigger mode 108 | # on in order to retrieve images using the trigger. 109 | node_trigger_mode_on = node_trigger_mode.GetEntryByName("On") 110 | if not PySpin.IsAvailable(node_trigger_mode_on) or not PySpin.IsReadable(node_trigger_mode_on): 111 | print "Unable to enable trigger mode (enum entry retrieval). Aborting..." 112 | return False 113 | 114 | node_trigger_mode.SetIntValue(node_trigger_mode_on.GetValue()) 115 | print "Trigger mode turned back on..." 116 | 117 | except PySpin.SpinnakerException as ex: 118 | print "Error: %s" % ex 119 | return False 120 | 121 | return result 122 | 123 | 124 | def grab_next_image_by_trigger(nodemap, cam): 125 | """ 126 | This function acquires an image by executing the trigger node. 127 | 128 | :param cam: Camera to acquire images from. 129 | :param nodemap: Device nodemap. 130 | :type cam: CameraPtr 131 | :type nodemap: INodeMap 132 | :return: True if successful, False otherwise. 133 | :rtype: bool 134 | """ 135 | try: 136 | result = True 137 | # Use trigger to capture image 138 | # The software trigger only feigns being executed by the Enter key; 139 | # what might not be immediately apparent is that there is not a 140 | # continuous stream of images being captured; in other examples that 141 | # acquire images, the camera captures a continuous stream of images. 142 | # When an image is retrieved, it is plucked from the stream. 143 | 144 | if CHOSEN_TRIGGER == TriggerType.SOFTWARE: 145 | # Get user input 146 | raw_input("Press the Enter key to initiate software trigger.") 147 | 148 | # Execute software trigger 149 | node_softwaretrigger_cmd = PySpin.CCommandPtr(nodemap.GetNode("TriggerSoftware")) 150 | if not PySpin.IsAvailable(node_softwaretrigger_cmd) or not PySpin.IsWritable(node_softwaretrigger_cmd): 151 | print "Unable to execute trigger. Aborting..." 152 | return False 153 | 154 | node_softwaretrigger_cmd.Execute() 155 | 156 | # TODO: Blackfly and Flea3 GEV cameras need 2 second delay after software trigger 157 | 158 | elif CHOSEN_TRIGGER == TriggerType.HARDWARE: 159 | print "Use the hardware to trigger image acquisition." 160 | 161 | except PySpin.SpinnakerException as ex: 162 | print "Error: %s" % ex 163 | return False 164 | 165 | return result 166 | 167 | 168 | def acquire_images(cam, nodemap, nodemap_tldevice): 169 | """ 170 | This function acquires and saves 10 images from a device. 171 | Please see Acquisition example for more in-depth comments on acquiring images. 172 | 173 | :param cam: Camera to acquire images from. 174 | :param nodemap: Device nodemap. 175 | :param nodemap_tldevice: Transport layer device nodemap. 176 | :type cam: CameraPtr 177 | :type nodemap: INodeMap 178 | :type nodemap_tldevice: INodeMap 179 | :return: True if successful, False otherwise. 180 | :rtype: bool 181 | """ 182 | 183 | print "*** IMAGE ACQUISITION ***\n" 184 | try: 185 | result = True 186 | 187 | # Set acquisition mode to continuous 188 | # In order to access the node entries, they have to be casted to a pointer type (CEnumerationPtr here) 189 | node_acquisition_mode = PySpin.CEnumerationPtr(nodemap.GetNode("AcquisitionMode")) 190 | if not PySpin.IsAvailable(node_acquisition_mode) or not PySpin.IsWritable(node_acquisition_mode): 191 | print "Unable to set acquisition mode to continuous (enum retrieval). Aborting..." 192 | return False 193 | 194 | # Retrieve entry node from enumeration node 195 | node_acquisition_mode_continuous = node_acquisition_mode.GetEntryByName("Continuous") 196 | if not PySpin.IsAvailable(node_acquisition_mode_continuous) or not PySpin.IsReadable( 197 | node_acquisition_mode_continuous): 198 | print "Unable to set acquisition mode to continuous (entry retrieval). Aborting..." 199 | return False 200 | 201 | # Retrieve integer value from entry node 202 | acquisition_mode_continuous = node_acquisition_mode_continuous.GetValue() 203 | 204 | # Set integer value from entry node as new value of enumeration node 205 | node_acquisition_mode.SetIntValue(acquisition_mode_continuous) 206 | 207 | print "Acquisition mode set to continuous..." 208 | 209 | # Begin acquiring images 210 | cam.BeginAcquisition() 211 | 212 | print "Acquiring images..." 213 | 214 | # Retrieve device serial number for filename 215 | # 216 | # *** NOTES *** 217 | # The device serial number is retrieved in order to keep cameras from 218 | # overwriting one another. Grabbing image IDs could also accomplish 219 | # this. 220 | device_serial_number = "" 221 | node_device_serial_number = PySpin.CStringPtr(nodemap_tldevice.GetNode("DeviceSerialNumber")) 222 | if PySpin.IsAvailable(node_device_serial_number) and PySpin.IsReadable(node_device_serial_number): 223 | device_serial_number = node_device_serial_number.GetValue() 224 | print "Device serial number retrieved as %s..." % device_serial_number 225 | 226 | # Retrieve, convert, and save images 227 | for i in range(NUM_IMAGES): 228 | try: 229 | 230 | # Retrieve the next image from the trigger 231 | result &= grab_next_image_by_trigger(nodemap, cam) 232 | 233 | # Retrieve next received image 234 | image_result = cam.GetNextImage() 235 | 236 | # Ensure image completion 237 | if image_result.IsIncomplete(): 238 | print "Image incomplete with image status %d ..." % image_result.GetImageStatus() 239 | 240 | else: 241 | 242 | # Print image information; height and width recorded in pixels 243 | # 244 | # *** NOTES *** 245 | # Images have quite a bit of available metadata including 246 | # things such as CRC, image status, and offset values, to 247 | # name a few. 248 | width = image_result.GetWidth() 249 | height = image_result.GetHeight() 250 | print "Grabbed Image %d, width = %d, height = %d" % (i, width, height) 251 | 252 | # Convert image to mono 8 253 | # 254 | # *** NOTES *** 255 | # Images can be converted between pixel formats by using 256 | # the appropriate enumeration value. Unlike the original 257 | # image, the converted one does not need to be released as 258 | # it does not affect the camera buffer. 259 | # 260 | # When converting images, color processing algorithm is an 261 | # optional parameter. 262 | image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) 263 | 264 | # Create a unique filename 265 | if device_serial_number: 266 | filename = "Trigger-%s-%d.jpg" % (device_serial_number, i) 267 | else: # if serial number is empty 268 | filename = "Trigger-%d.jpg" % i 269 | 270 | # Save image 271 | # 272 | # *** NOTES *** 273 | # The standard practice of the examples is to use device 274 | # serial numbers to keep images of one device from 275 | # overwriting those of another. 276 | image_converted.Save(filename) 277 | print "Image saved at %s" % filename 278 | 279 | # Release image 280 | # 281 | # *** NOTES *** 282 | # Images retrieved directly from the camera (i.e. non-converted 283 | # images) need to be released in order to keep from filling the 284 | # buffer. 285 | image_result.Release() 286 | print "" 287 | 288 | except PySpin.SpinnakerException as ex: 289 | print "Error: %s" % ex 290 | return False 291 | 292 | # End acquisition 293 | # 294 | # *** NOTES *** 295 | # Ending acquisition appropriately helps ensure that devices clean up 296 | # properly and do not need to be power-cycled to maintain integrity. 297 | cam.EndAcquisition() 298 | 299 | except PySpin.SpinnakerException as ex: 300 | print "Error: %s" % ex 301 | return False 302 | 303 | return result 304 | 305 | 306 | def reset_trigger(nodemap): 307 | """ 308 | This function returns the camera to a normal state by turning off trigger mode. 309 | 310 | :param nodemap: Transport layer device nodemap. 311 | :type nodemap: INodeMap 312 | :returns: True if successful, False otherwise. 313 | :rtype: bool 314 | """ 315 | try: 316 | result = True 317 | node_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode("TriggerMode")) 318 | if not PySpin.IsAvailable(node_trigger_mode) or not PySpin.IsReadable(node_trigger_mode): 319 | print "Unable to disable trigger mode (node retrieval). Aborting..." 320 | return False 321 | 322 | node_trigger_mode_off = node_trigger_mode.GetEntryByName("Off") 323 | if not PySpin.IsAvailable(node_trigger_mode_off) or not PySpin.IsReadable(node_trigger_mode_off): 324 | print "Unable to disable trigger mode (enum entry retrieval). Aborting..." 325 | return False 326 | 327 | node_trigger_mode.SetIntValue(node_trigger_mode_off.GetValue()) 328 | 329 | print "Trigger mode disabled..." 330 | 331 | except PySpin.SpinnakerException as ex: 332 | print "Error: %s" % ex 333 | result = False 334 | 335 | return result 336 | 337 | 338 | def print_device_info(nodemap): 339 | """ 340 | This function prints the device information of the camera from the transport 341 | layer; please see NodeMapInfo example for more in-depth comments on printing 342 | device information from the nodemap. 343 | 344 | :param nodemap: Transport layer device nodemap. 345 | :type nodemap: INodeMap 346 | :returns: True if successful, False otherwise. 347 | :rtype: bool 348 | """ 349 | 350 | print "*** DEVICE INFORMATION ***\n" 351 | 352 | try: 353 | result = True 354 | node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) 355 | 356 | if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): 357 | features = node_device_information.GetFeatures() 358 | for feature in features: 359 | node_feature = PySpin.CValuePtr(feature) 360 | print "%s: %s" % (node_feature.GetName(), 361 | node_feature.ToString() if PySpin.IsReadable(node_feature) else "Node not readable") 362 | 363 | else: 364 | print "Device control information not available." 365 | 366 | except PySpin.SpinnakerException as ex: 367 | print "Error: %s" % ex 368 | return False 369 | 370 | return result 371 | 372 | 373 | def run_single_camera(cam): 374 | """ 375 | This function acts as the body of the example; please see NodeMapInfo example 376 | for more in-depth comments on setting up cameras. 377 | 378 | :param cam: Camera to run on. 379 | :type cam: CameraPtr 380 | :return: True if successful, False otherwise. 381 | :rtype: bool 382 | """ 383 | try: 384 | result = True 385 | err = False 386 | 387 | # Retrieve TL device nodemap and print device information 388 | nodemap_tldevice = cam.GetTLDeviceNodeMap() 389 | 390 | result &= print_device_info(nodemap_tldevice) 391 | 392 | # Initialize camera 393 | cam.Init() 394 | 395 | # Retrieve GenICam nodemap 396 | nodemap = cam.GetNodeMap() 397 | 398 | # Configure trigger 399 | if configure_trigger(cam) is False: 400 | return False 401 | 402 | # Acquire images 403 | result &= acquire_images(cam, nodemap, nodemap_tldevice) 404 | 405 | # Reset trigger 406 | result &= reset_trigger(nodemap) 407 | 408 | # Deinitialize camera 409 | cam.DeInit() 410 | 411 | except PySpin.SpinnakerException as ex: 412 | print "Error: %s" % ex 413 | result = False 414 | 415 | return result 416 | 417 | 418 | def main(): 419 | """ 420 | Example entry point; please see Enumeration example for more in-depth 421 | comments on preparing and cleaning up the system. 422 | 423 | :return: True if successful, False otherwise. 424 | :rtype: bool 425 | """ 426 | # Retrieve singleton reference to system object 427 | system = PySpin.System.GetInstance() 428 | 429 | # Retrieve list of cameras from the system 430 | cam_list = system.GetCameras() 431 | 432 | num_cameras = cam_list.GetSize() 433 | 434 | print "Number of cameras detected: %d" % num_cameras 435 | 436 | # Finish if there are no cameras 437 | if num_cameras == 0: 438 | # Clear camera list before releasing system 439 | cam_list.Clear() 440 | 441 | # Release system 442 | system.ReleaseInstance() 443 | 444 | print "Not enough cameras!" 445 | raw_input("Done! Press Enter to exit...") 446 | return False 447 | 448 | # Run example on each camera 449 | for i in range(num_cameras): 450 | cam = cam_list.GetByIndex(i) 451 | 452 | print "Running example for camera %d..." % i 453 | 454 | result = run_single_camera(cam) 455 | print "Camera %d example complete... \n" % i 456 | 457 | # Release reference to camera 458 | # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically 459 | # cleaned up when going out of scope. 460 | # The usage of del is preferred to assigning the variable to None. 461 | del cam 462 | 463 | # Clear camera list before releasing system 464 | cam_list.Clear() 465 | 466 | # Release instance 467 | system.ReleaseInstance() 468 | 469 | raw_input("Done! Press Enter to exit...") 470 | return result 471 | 472 | 473 | if __name__ == "__main__": 474 | main() 475 | -------------------------------------------------------------------------------- /Trigger_QuickSpin.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # ============================================================================= 3 | # Copyright © 2017 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved. 4 | # 5 | # This software is the confidential and proprietary information of FLIR 6 | # Integrated Imaging Solutions, Inc. ("Confidential Information"). You 7 | # shall not disclose such Confidential Information and shall use it only in 8 | # accordance with the terms of the license agreement you entered into 9 | # with FLIR Integrated Imaging Solutions, Inc. (FLIR). 10 | # 11 | # FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE 12 | # SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 13 | # IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | # PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES 15 | # SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 16 | # THIS SOFTWARE OR ITS DERIVATIVES. 17 | # ============================================================================= 18 | # 19 | # Trigger_QuickSpin.py shows how to capture images with the 20 | # trigger using the QuickSpin API. QuickSpin is a subset of the Spinnaker 21 | # library that allows for simpler node access and control. 22 | # 23 | # This example demonstrates how to prepare, execute, and clean up the camera 24 | # in regards to using both software and hardware triggers. Retrieving and 25 | # setting node values using QuickSpin is the only portion of the example 26 | # that differs from Trigger. 27 | # 28 | # A much wider range of topics is covered in the full Spinnaker examples than 29 | # in the QuickSpin ones. There are only enough QuickSpin examples to 30 | # demonstrate node access and to get started with the API; please see full 31 | # Spinnaker examples for further or specific knowledge on a topic. 32 | 33 | import PySpin 34 | 35 | NUM_IMAGES = 10 # number of images to grab 36 | 37 | 38 | class TriggerType: 39 | SOFTWARE = 1 40 | HARDWARE = 2 41 | 42 | CHOSEN_TRIGGER = TriggerType.SOFTWARE 43 | 44 | 45 | def configure_trigger(cam): 46 | """ 47 | This function configures the camera to use a trigger. First, trigger mode is 48 | ensured to be off in order to select the trigger source. Trigger mode is 49 | then enabled, which has the camera capture only a single image upon the 50 | execution of the chosen trigger. 51 | 52 | :param cam: Camera to configure trigger for. 53 | :type cam: CameraPtr 54 | :return: True if successful, False otherwise. 55 | :rtype: bool 56 | """ 57 | 58 | print "*** CONFIGURING TRIGGER ***\n" 59 | 60 | if CHOSEN_TRIGGER == TriggerType.SOFTWARE: 61 | print "Software trigger chosen..." 62 | elif CHOSEN_TRIGGER == TriggerType.HARDWARE: 63 | print "Hardware trigger chosen..." 64 | 65 | try: 66 | result = True 67 | 68 | # Ensure trigger mode off 69 | # The trigger must be disabled in order to configure whether the source 70 | # is software or hardware. 71 | if cam.TriggerMode.GetAccessMode() != PySpin.RW: 72 | print "Unable to disable trigger mode (node retrieval). Aborting..." 73 | return False 74 | 75 | cam.TriggerMode.SetValue(PySpin.TriggerMode_Off) 76 | 77 | print "Trigger mode disabled..." 78 | 79 | # Select trigger source 80 | # The trigger source must be set to hardware or software while trigger 81 | # mode is off. 82 | if cam.TriggerSource.GetAccessMode() != PySpin.RW: 83 | print "Unable to get trigger source (node retrieval). Aborting..." 84 | return False 85 | 86 | if CHOSEN_TRIGGER == TriggerType.SOFTWARE: 87 | cam.TriggerSource.SetValue(PySpin.TriggerSource_Software) 88 | elif CHOSEN_TRIGGER == TriggerType.HARDWARE: 89 | cam.TriggerSource.SetValue(PySpin.TriggerSource_Line0) 90 | 91 | # Turn trigger mode on 92 | # Once the appropriate trigger source has been set, turn trigger mode 93 | # on in order to retrieve images using the trigger. 94 | cam.TriggerMode.SetValue(PySpin.TriggerMode_On) 95 | print "Trigger mode turned back on..." 96 | 97 | except PySpin.SpinnakerException as ex: 98 | print "Error: %s" % ex 99 | return False 100 | 101 | return result 102 | 103 | 104 | def grab_next_image_by_trigger(cam): 105 | """ 106 | This function acquires an image by executing the trigger node. 107 | 108 | :param cam: Camera to acquire images from. 109 | :type cam: CameraPtr 110 | :return: True if successful, False otherwise. 111 | :rtype: bool 112 | """ 113 | try: 114 | result = True 115 | # Use trigger to capture image 116 | # The software trigger only feigns being executed by the Enter key; 117 | # what might not be immediately apparent is that there is not a 118 | # continuous stream of images being captured; in other examples that 119 | # acquire images, the camera captures a continuous stream of images. 120 | # When an image is retrieved, it is plucked from the stream. 121 | 122 | if CHOSEN_TRIGGER == TriggerType.SOFTWARE: 123 | # Get user input 124 | raw_input("Press the Enter key to initiate software trigger.") 125 | 126 | # Execute software trigger 127 | if cam.TriggerSoftware.GetAccessMode() != PySpin.WO: 128 | print "Unable to execute trigger. Aborting..." 129 | return False 130 | 131 | cam.TriggerSoftware.Execute() 132 | 133 | # TODO: Blackfly and Flea3 GEV cameras need 2 second delay after software trigger 134 | 135 | elif CHOSEN_TRIGGER == TriggerType.HARDWARE: 136 | print "Use the hardware to trigger image acquisition." 137 | 138 | except PySpin.SpinnakerException as ex: 139 | print "Error: %s" % ex 140 | return False 141 | 142 | return result 143 | 144 | 145 | def acquire_images(cam): 146 | """ 147 | This function acquires and saves 10 images from a device. 148 | Please see Acquisition example for more in-depth comments on acquiring images. 149 | 150 | :param cam: Camera to acquire images from. 151 | :type cam: CameraPtr 152 | :return: True if successful, False otherwise. 153 | :rtype: bool 154 | """ 155 | 156 | print "*** IMAGE ACQUISITION ***\n" 157 | try: 158 | result = True 159 | 160 | # Set acquisition mode to continuous 161 | if cam.AcquisitionMode.GetAccessMode() != PySpin.RW: 162 | print "Unable to set acquisition mode to continuous. Aborting..." 163 | return False 164 | 165 | cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous) 166 | print "Acquisition mode set to continuous..." 167 | 168 | # Begin acquiring images 169 | cam.BeginAcquisition() 170 | 171 | print "Acquiring images..." 172 | 173 | # Get device serial number for filename 174 | device_serial_number = "" 175 | if cam.TLDevice.DeviceSerialNumber.GetAccessMode() == PySpin.RO: 176 | device_serial_number = cam.TLDevice.DeviceSerialNumber.GetValue() 177 | 178 | print "Device serial number retrieved as %s..." % device_serial_number 179 | 180 | # Retrieve, convert, and save images 181 | for i in range(NUM_IMAGES): 182 | try: 183 | 184 | # Retrieve the next image from the trigger 185 | result &= grab_next_image_by_trigger(cam) 186 | 187 | # Retrieve next received image 188 | image_result = cam.GetNextImage() 189 | 190 | # Ensure image completion 191 | if image_result.IsIncomplete(): 192 | print "Image incomplete with image status %d ..." % image_result.GetImageStatus() 193 | 194 | else: 195 | 196 | # Print image information 197 | width = image_result.GetWidth() 198 | height = image_result.GetHeight() 199 | print "Grabbed Image %d, width = %d, height = %d" % (i, width, height) 200 | 201 | # Convert image to mono 8 202 | image_converted = image_result.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR) 203 | 204 | # Create a unique filename 205 | if device_serial_number: 206 | filename = "Trigger-%s-%d.jpg" % (device_serial_number, i) 207 | else: # if serial number is empty 208 | filename = "Trigger-%d.jpg" % i 209 | 210 | # Save image 211 | image_converted.Save(filename) 212 | 213 | print "Image saved at %s" % filename 214 | 215 | # Release image 216 | image_result.Release() 217 | print "" 218 | 219 | except PySpin.SpinnakerException as ex: 220 | print "Error: %s" % ex 221 | return False 222 | 223 | # End acquisition 224 | cam.EndAcquisition() 225 | 226 | except PySpin.SpinnakerException as ex: 227 | print "Error: %s" % ex 228 | return False 229 | 230 | return result 231 | 232 | 233 | def reset_trigger(cam): 234 | """ 235 | This function returns the camera to a normal state by turning off trigger mode. 236 | 237 | :param cam: Camera to acquire images from. 238 | :type cam: CameraPtr 239 | :returns: True if successful, False otherwise. 240 | :rtype: bool 241 | """ 242 | try: 243 | result = True 244 | # Ensure trigger mode off 245 | # The trigger must be disabled in order to configure whether the source 246 | # is software or hardware. 247 | if cam.TriggerMode.GetAccessMode() != PySpin.RW: 248 | print "Unable to disable trigger mode (node retrieval). Aborting..." 249 | return False 250 | 251 | cam.TriggerMode.SetValue(PySpin.TriggerMode_Off) 252 | 253 | print "Trigger mode disabled..." 254 | 255 | except PySpin.SpinnakerException as ex: 256 | print "Error: %s" % ex 257 | result = False 258 | 259 | return result 260 | 261 | 262 | def print_device_info(nodemap): 263 | """ 264 | This function prints the device information of the camera from the transport 265 | layer; please see NodeMapInfo example for more in-depth comments on printing 266 | device information from the nodemap. 267 | 268 | :param nodemap: Transport layer device nodemap. 269 | :type nodemap: INodeMap 270 | :returns: True if successful, False otherwise. 271 | :rtype: bool 272 | """ 273 | 274 | print "*** DEVICE INFORMATION ***\n" 275 | 276 | try: 277 | result = True 278 | node_device_information = PySpin.CCategoryPtr(nodemap.GetNode("DeviceInformation")) 279 | 280 | if PySpin.IsAvailable(node_device_information) and PySpin.IsReadable(node_device_information): 281 | features = node_device_information.GetFeatures() 282 | for feature in features: 283 | node_feature = PySpin.CValuePtr(feature) 284 | print "%s: %s" % (node_feature.GetName(), 285 | node_feature.ToString() if PySpin.IsReadable(node_feature) else "Node not readable") 286 | 287 | else: 288 | print "Device control information not available." 289 | 290 | except PySpin.SpinnakerException as ex: 291 | print "Error: %s" % ex 292 | return False 293 | 294 | return result 295 | 296 | 297 | def run_single_camera(cam): 298 | """ 299 | This function acts as the body of the example; please see NodeMapInfo example 300 | for more in-depth comments on setting up cameras. 301 | 302 | :param cam: Camera to run on. 303 | :type cam: CameraPtr 304 | :return: True if successful, False otherwise. 305 | :rtype: bool 306 | """ 307 | try: 308 | result = True 309 | err = False 310 | 311 | # Retrieve TL device nodemap and print device information 312 | nodemap_tldevice = cam.GetTLDeviceNodeMap() 313 | 314 | result &= print_device_info(nodemap_tldevice) 315 | 316 | # Initialize camera 317 | cam.Init() 318 | 319 | # Retrieve GenICam nodemap 320 | nodemap = cam.GetNodeMap() 321 | 322 | # Configure trigger 323 | if configure_trigger(cam) is False: 324 | return False 325 | 326 | # Acquire images 327 | result &= acquire_images(cam) 328 | 329 | # Reset trigger 330 | result &= reset_trigger(cam) 331 | 332 | # Deinitialize camera 333 | cam.DeInit() 334 | 335 | except PySpin.SpinnakerException as ex: 336 | print "Error: %s" % ex 337 | result = False 338 | 339 | return result 340 | 341 | 342 | def main(): 343 | """ 344 | Example entry point; please see Enumeration example for more in-depth 345 | comments on preparing and cleaning up the system. 346 | 347 | :return: True if successful, False otherwise. 348 | :rtype: bool 349 | """ 350 | # Retrieve singleton reference to system object 351 | system = PySpin.System.GetInstance() 352 | 353 | # Retrieve list of cameras from the system 354 | cam_list = system.GetCameras() 355 | 356 | num_cameras = cam_list.GetSize() 357 | 358 | print "Number of cameras detected: %d" % num_cameras 359 | 360 | # Finish if there are no cameras 361 | if num_cameras == 0: 362 | # Clear camera list before releasing system 363 | cam_list.Clear() 364 | 365 | # Release system 366 | system.ReleaseInstance() 367 | 368 | print "Not enough cameras!" 369 | raw_input("Done! Press Enter to exit...") 370 | return False 371 | 372 | # Run example on each camera 373 | for i in range(num_cameras): 374 | cam = cam_list.GetByIndex(i) 375 | 376 | print "Running example for camera %d..." % i 377 | 378 | result = run_single_camera(cam) 379 | print "Camera %d example complete... \n" % i 380 | 381 | # Release reference to camera 382 | # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically 383 | # cleaned up when going out of scope. 384 | # The usage of del is preferred to assigning the variable to None. 385 | del cam 386 | 387 | # Clear camera list before releasing system 388 | cam_list.Clear() 389 | 390 | # Release instance 391 | system.ReleaseInstance() 392 | 393 | raw_input("Done! Press Enter to exit...") 394 | return result 395 | 396 | 397 | if __name__ == "__main__": 398 | main() 399 | -------------------------------------------------------------------------------- /take_a_photo.py: -------------------------------------------------------------------------------- 1 | import pyspin 2 | from pyspin import PySpin 3 | 4 | # Get system 5 | system = PySpin.System.GetInstance() 6 | 7 | # Get camera list 8 | cam_list = system.GetCameras() 9 | 10 | # Figure out which is primary and secondary (usually webcam is primary and Flea3 is secondary) 11 | cam = cam_list.GetByIndex(0) 12 | 13 | # Initialize camera 14 | cam.Init() 15 | 16 | # Set acquisition mode 17 | cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_SingleFrame) 18 | 19 | # Start acquisition 20 | cam.BeginAcquisition() 21 | 22 | # Acquire images 23 | image_primary = cam.GetNextImage() 24 | width = image_primary.GetWidth() 25 | height = image_primary.GetHeight() 26 | print "width: " + str(width) + ", height: " + str(height) 27 | 28 | # Pixel array (NumPy array) 29 | image_array = image_primary.GetData() 30 | 31 | # Save images 32 | image_primary.Save('prime.jpg') 33 | 34 | # Stop acquisition 35 | cam.EndAcquisition() 36 | 37 | # De-initialize 38 | cam.DeInit() 39 | 40 | # Clear references to images and cameras 41 | del image_primary 42 | del cam 43 | del cam_list 44 | --------------------------------------------------------------------------------