0

OpenCV 4.7, Matplotlib 3.7.1, Spinnaker-Python 3.0.0.118, Python 3.10, Win 10 x64

I'm acquiring images from a FLIR thermal camera via their Spinnaker API.

I am displaying the images using OpenCV & concurrently displaying a histogram of the images using Matplotlib. The relevant code snippet, (that sits in a function which also contains camera set up & error handling)

cam.BeginAcquisition()
print('Acquiring images...')
print('Press enter to close the program..')

fig = plt.figure(1)
fig.canvas.mpl_connect('close_event', handle_close)
acq_count = 0 # number of saved images
        
# Retrieve and display images
while(continue_recording):
    try:
                
        image_result = cam.GetNextImage(1000)

        #  Ensure image completion
        if image_result.IsIncomplete():
            print('Image incomplete with image status %d ...' % image_result.GetImageStatus())

        else:                    

            # Getting the image data as a numpy array
            image_data = image_result.GetNDArray()
                      
            image_data = cv2.rotate(image_data, cv2.ROTATE_90_COUNTERCLOCKWISE)
            image_data = cv2.flip(image_data, 1)
            image_copy = image_data
                
            count, bins = np.histogram(image_data.flatten())
                        
            cv2.imshow("FLIR", image_data)
                    
            plt.stairs(count, bins)
            plt.pause(0.001)
            plt.clf()
            
            # if 's' pressed then save image data           
            if cv2.waitKey(100) & 0xFF == ord('s'):
                        
                f_name = "test_" + str(acq_count) + '.png'
                cv2.imwrite(f_name, image_data)
                acq_count += 1
                        
            # If user presses enter, close the program
            if keyboard.is_pressed('ENTER'):
                        
                print('Program is closing...')
                cv2.destroyAllWindows()
                plt.close('all')             
                input('Done! Press Enter to exit...')
                continue_recording=False                        

            image_result.Release() # clears camera buffer

        except PySpin.SpinnakerException as ex:
            print('Error: %s' % ex)
            return False

cam.EndAcquisition()

When s is pressed though a blocking popup appears asking me where I want to save figure 1 and then proceeds to save the histogram but not the image!

EDIT :: I should also mention that it all works fine as long as there is no Matplotlib figure.

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
DrBwts
  • 3,470
  • 6
  • 38
  • 62
  • 1
    Which window has focus when you press the key? My guess is that it's the matplotlib one, not the OpenCV one. – Dan Mašek Apr 13 '23 at 15:36
  • @DanMašek yeah you might be onto something there as the histogram is plotted after the output to the `cv2` window. Wierd though as I'm writing out the contents of `image_data` which is a `numpy` array & not the contents of any of the open windows. Will check when I'm back at work next week. – DrBwts Apr 13 '23 at 18:47
  • 2
    Right, my point is, the window with focus is the one that will get the keypress event. If it's the matplotlib window, then its own message loop with handle the `s`, which happens to trigger the matplotlib "save plot" feature. OpenCV's `waitKey` (which runs the message loop for the OpenCV window) never gets the keypress, so the `imwrite` never happens in that case. – Dan Mašek Apr 13 '23 at 18:54
  • @DanMašek thanks, I disabled `matplotlib`'s callback with `plt.rcParams['keymap.save'].remove('s')` & then used `keyboard`'s event handler instead of OpenCV's keyboard handler & now it works. Do you want to write up an answer/solution? if not I'll do it later – DrBwts Apr 17 '23 at 08:05
  • Go for it, you figured out the details anyway ;) – Dan Mašek Apr 18 '23 at 22:59

1 Answers1

0

As per the discussion in the commets to the OP.

As OpenCV & Matplotlib both have a window open when the keyboard is scanned and an s is pressed Matplotlib's save callback automatically kicks in.

To disable this,

plt.rcParams['keymap.save'].remove('s')

I also got rid of the OpenCV keyboard manager & just used the keyboard libraries keyboard manager.

DrBwts
  • 3,470
  • 6
  • 38
  • 62