From 68a0c79d1a0d32e2bab798bdccee8bdf57fef7b9 Mon Sep 17 00:00:00 2001 From: PySimpleGUI Date: Sun, 8 Dec 2019 12:50:16 -0500 Subject: [PATCH] Better camera control for droid --- .../PyDroid3/Demo_OpenCV_4_Line_Program.py | 3 +- .../PyDroid3/Demo_OpenCV_Webcam_ASCII.py | 62 ++++++++++++------- .../PyDroid3/Demo_OpenCV_Webcam_Minimal.py | 35 +++++++++++ 3 files changed, 77 insertions(+), 23 deletions(-) create mode 100644 DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_Minimal.py diff --git a/DemoPrograms/PyDroid3/Demo_OpenCV_4_Line_Program.py b/DemoPrograms/PyDroid3/Demo_OpenCV_4_Line_Program.py index b7cd3904..9efba4c6 100644 --- a/DemoPrograms/PyDroid3/Demo_OpenCV_4_Line_Program.py +++ b/DemoPrograms/PyDroid3/Demo_OpenCV_4_Line_Program.py @@ -1,5 +1,6 @@ import tkinter import cv2, PySimpleGUI as sg -window, cap = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(filename='', key='image')], ], location=(0, 0)), cv2.VideoCapture(0) +USE_CAMERA = 0 # change to 1 for front facing camera +window, cap = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(filename='', key='image')], ], location=(0, 0), grab_anywhere=True), cv2.VideoCapture(USE_CAMERA) while window(timeout=20)[0] is not None: window['image'](data=cv2.imencode('.png', cap.read()[1])[1].tobytes()) diff --git a/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_ASCII.py b/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_ASCII.py index ad8ffbf5..6de65e26 100644 --- a/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_ASCII.py +++ b/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_ASCII.py @@ -3,8 +3,12 @@ import cv2 from PIL import Image import numpy as np import PySimpleGUI as sg + font_size = 4 -USING_QT = False +CAMERA_FRONT = 1 +CAMERA_REAR = 0 + +USE_CAMERA = CAMERA_REAR """ Interesting program that shows your webcam's image as ASCII text. Runs in realtime, producing a stream of @@ -29,34 +33,48 @@ On Linux / Mac use pip3 instead of pip chars = np.asarray(list(' .,:;irsXA253hMHGS#9B&@')) SC, GCF, WCF = .1, 1, 7/4 -sg.change_look_and_feel('Black') # make it look cool +sg.change_look_and_feel('Dark Black 1') # make it look cool -# define the window layout +# ---------------- A Quick Little Window - to get camera to use ---------------- +win_get_cam = sg.Window('Which Camera?',[[sg.T('Which camera?')],[sg.Combo(['Front', 'Rear'], default_value='Rear', font='any 20')], [sg.Ok()]], location=(0,0)) +event, values = win_get_cam.read() +win_get_cam.close() +if event != 'Ok': exit() +USE_CAMERA = [CAMERA_FRONT, CAMERA_REAR][values[0]=='Rear'] + +# ------------ Turn on camera and read a frame to find the number of lines of text needed --------- +cap = cv2.VideoCapture(USE_CAMERA) # Setup camera using your camera choice + +ret, frame = cap.read() + +img = Image.fromarray(frame) # create PIL image from frame +GCF = 1.0 # Variable user will be able to change +WCF = 1.75 # Variable user will be able to change +# ----------- magic that coverts the image to ascii ----------- +S = (round(img.size[0] * SC * WCF), round(img.size[1] * SC)) +img = np.sum(np.asarray(img.resize(S)), axis=2) +img -= img.min() +img = (1.0 - img / img.max()) ** GCF * (chars.size - 1) + +# Find number of lines of text that will be drawn so can create the right size of window +NUM_LINES = len(chars[img.astype(int)]) +LINE_LENGTH = len("".join(chars[img.astype(int)][0])) +print(f'line len = {LINE_LENGTH}') +# ------------- define the window layout ------------- # number of lines of text elements. Depends on cameras image size and the variable SC (scaller) -NUM_LINES = 65 -if USING_QT: - layout = [[sg.Text(i, size_px=(800, 12), - font=('Courier', font_size), - key='-OUT-' + str(i))] for i in range(NUM_LINES)] -else: - layout = [[sg.Text(i, size=(120, 1), font=('Courier', font_size), - pad=(0, 0), key='-OUT-'+str(i))] for i in range(NUM_LINES)] + +layout = [[sg.Text(i, size=(LINE_LENGTH, 1), font=('Courier', font_size), pad=(0, 0), key='-OUT-'+str(i))] for i in range(NUM_LINES)] layout += [[sg.Button('Exit', size=(5, 1)), -sg.Text('GCF', size=(4, 1)), -sg.Spin([round(i, 2) for i in np.arange(0.1, 20.0, 0.1)], -initial_value=1, key='-SPIN-GCF-', size=(5, 1)), -sg.Text('WCF', size=(4, 1)), -sg.Slider((1, 4), resolution=.05, default_value=1.75, -orientation='h', key='-SLIDER-WCF-', size=(15, 15))]] + sg.Text('GCF', size=(4, 1)), + sg.Spin([round(i, 2) for i in np.arange(0.1, 20.0, 0.1)], initial_value=1, key='-SPIN-GCF-', size=(5, 1), font='any 20')], + [sg.Text('WCF', size=(4, 1)), + sg.Slider((1, 4), resolution=.05, default_value=1.75, orientation='h', key='-SLIDER-WCF-', size=(15, 30))]] -# create the window and show it without the plot -window = sg.Window('Demo Application - OpenCV Integration', layout, -location=(0,0), font='Any 10') +# ------------- create the window ------------- +window = sg.Window('Demo Application - OpenCV Integration', layout, location=(0,0)) # ---===--- Event LOOP Read and display frames, operate the GUI --- # -# Setup the OpenCV capture device (webcam) -cap = cv2.VideoCapture(0) while True: event, values = window.read(timeout=0) diff --git a/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_Minimal.py b/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_Minimal.py new file mode 100644 index 00000000..2e92af22 --- /dev/null +++ b/DemoPrograms/PyDroid3/Demo_OpenCV_Webcam_Minimal.py @@ -0,0 +1,35 @@ +import tkinter +import PySimpleGUI as sg +import cv2 + +""" + Demo of using OpenCV to show your webcam in a GUI window. + This demo will run on tkinter, Qt, and Web(Remi). The web version flickers at the moment though + To exit, right click and choose exit. If on Qt, you'll have to kill the program as there are no right click menus + in PySimpleGUIQt (yet). +""" + +CAMERA_FRONT = 1 +CAMERA_REAR = 0 +sg.change_look_and_feel('Dark Black 1') + +# define the window layout +layout = [[sg.Image(filename='', key='-IMAGE-', tooltip='Right click for exit menu')], + [sg.Exit()],] + +# create the window and show it without the plot +window = sg.Window('Demo Application - OpenCV Integration', layout, location=(0,0), + no_titlebar=True, grab_anywhere=True, + right_click_menu=['&Right', ['E&xit']], ) # if trying Qt, you will need to remove this right click menu + +# ---===--- Event LOOP Read and display frames, operate the GUI --- # +cap = cv2.VideoCapture(CAMERA_REAR) # Setup the OpenCV capture device (webcam) +while True: + event, values = window.read(timeout=20) + if event in ('Exit', None): + break + ret, frame = cap.read() # Read image from capture device (camera) + imgbytes=cv2.imencode('.png', frame)[1].tobytes() # Convert the image to PNG Bytes + window['-IMAGE-'].update(data=imgbytes) # Change the Image Element to show the new image + +window.close()