81 lines
		
	
	
		
			No EOL
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
		
			No EOL
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/env python
 | |
| import PySimpleGUI as sg
 | |
| import cv2 as cv
 | |
| # from PIL import Image
 | |
| # import io
 | |
| 
 | |
| """
 | |
|     Demo program to open and play a file using OpenCV
 | |
|     It's main purpose is to show you:
 | |
|     1. How to get a frame at a time from a video file using OpenCV
 | |
|     2. How to display an image in a PySimpleGUI Window
 | |
|     
 | |
|     For added fun, you can reposition the video using the slider.
 | |
|     
 | |
|     Copyright 2022 PySimpleGUI
 | |
| """
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     # ---===--- Get the filename --- #
 | |
|     filename = sg.popup_get_file('Filename to play')
 | |
|     if filename is None:
 | |
|         return
 | |
|     vidFile = cv.VideoCapture(filename)
 | |
|     # ---===--- Get some Stats --- #
 | |
|     num_frames = vidFile.get(cv.CAP_PROP_FRAME_COUNT)
 | |
|     fps = vidFile.get(cv.CAP_PROP_FPS)
 | |
| 
 | |
|     sg.theme('Black')
 | |
| 
 | |
|     # ---===--- define the window layout --- #
 | |
|     layout = [[sg.Text('OpenCV Demo', size=(15, 1), font='Helvetica 20')],
 | |
|               [sg.Image(key='-IMAGE-')],
 | |
|               [sg.Slider(range=(0, num_frames), size=(60, 10), orientation='h', key='-SLIDER-')],
 | |
|               [sg.Push(), sg.Button('Exit', font='Helvetica 14')]]
 | |
| 
 | |
|     # create the window and show it without the plot
 | |
|     window = sg.Window('Demo Application - OpenCV Integration', layout, no_titlebar=False, location=(0, 0))
 | |
| 
 | |
|     # locate the elements we'll be updating. Does the search only 1 time
 | |
|     image_elem = window['-IMAGE-']
 | |
|     slider_elem = window['-SLIDER-']
 | |
|     timeout = 1000//fps                 # time in ms to use for window reads
 | |
|     
 | |
|     # ---===--- LOOP through video file by frame --- #
 | |
|     cur_frame = 0
 | |
|     while vidFile.isOpened():
 | |
|         event, values = window.read(timeout=timeout)
 | |
|         if event in ('Exit', None):
 | |
|             break
 | |
|         ret, frame = vidFile.read()
 | |
|         if not ret:  # if out of data stop looping
 | |
|             break
 | |
|         # if someone moved the slider manually, the jump to that frame
 | |
|         if int(values['-SLIDER-']) != cur_frame-1:
 | |
|             cur_frame = int(values['-SLIDER-'])
 | |
|             vidFile.set(cv.CAP_PROP_POS_FRAMES, cur_frame)
 | |
|         slider_elem.update(cur_frame)
 | |
|         cur_frame += 1
 | |
| 
 | |
|         imgbytes = cv.imencode('.ppm', frame)[1].tobytes()  # can also use png.  ppm found to be more efficient
 | |
|         image_elem.update(data=imgbytes)
 | |
| 
 | |
| main()
 | |
| 
 | |
|             #############
 | |
|             #    | |    #
 | |
|             #    | |    #
 | |
|             #    |_|    #
 | |
|             #  __   __  #
 | |
|             #  \ \ / /  #
 | |
|             #   \ V /   #
 | |
|             #    \_/    #
 | |
| """         #############
 | |
|         # This was another way updates were being done, but seems slower than the above
 | |
|         img = Image.fromarray(frame)    # create PIL image from frame
 | |
|         bio = io.BytesIO()              # a binary memory resident stream
 | |
|         img.save(bio, format= 'PNG')    # save image as png to it
 | |
|         imgbytes = bio.getvalue()       # this can be used by OpenCV hopefully
 | |
|         image_elem.update(data=imgbytes)
 | |
| """ |