cv2.VideoCapture freeze framing when using a countdown timer with pressed key 's' for rock paper scissors project - computer-vision

I have defined two different functions, one for getting the prediction of the user using the Teachable Machine from Google and then a countdown function which is initiated by the 'S' key within the loop.
My issue is that when I click the 'S' key my Video Capture freeze frames and begins the countdown, when all I want it to be doing is allowing the user to ready themselves for creating one of three gestures.
The code is below:
def get_user_choice(self):
user_choice = ''
while True:
ret, frame = cap.read()
resized_frame = cv2.resize(frame, (224, 224), interpolation = cv2.INTER_AREA)
image_np = np.array(resized_frame)
normalized_image = (image_np.astype(np.float32) / 127.0) - 1 # Normalize the image
data[0] = normalized_image
prediction = model.predict(data, verbose=0)
cv2.imshow('frame', frame)
k = cv2.waitKey(1)
if k == ord('s'):
countdown()
user_index = np.argmax(prediction[0])
user_choice = user_options[user_index]
print('You chose:', user_choice)
return user_choice
def countdown():
print('Get your answer ready!')
prev = time.time() + 1
TIMER = int(4)
while TIMER >= 1:
cur = time.time()
if cur - prev >= 1:
prev = cur
TIMER = TIMER -1
print(TIMER)
It works almost perfectly apart from the countdown function which has created a freeze frame issue.
I've tried to mess around with the countdown function, and put the videocapture into the countdown function. Nothing seems to have worked for me so far, and thus is causing frustration.

Related

How to quit pygame with text input?

I am trying to make a screensaver using pygame. I want it to take input from my keyboard, and quit if the correct input is given. This is what i have right now:
import pygame
from pygame.locals import *
pygame.init()
WIDTH = 1366
HEIGHT = 768
windowSurface = pygame.display.set_mode((WIDTH, HEIGHT), pygame.FULLSCREEN)
img = pygame.image.load("bilde.jpeg")
running = True
name = ""
while running:
events = pygame.event.get()
for evt in pygame.event.get():
if evt.type == pygame.KEYDOWN:
if evt.unicode.isalpha():
name += evt.unicode
elif evt.key == K_BACKSPACE:
name = name[:-1]
elif evt.key == K_RETURN:
name = ""
elif evt.key == K_ESCAPE:
running = False
if name == "abc":
running = False
in this case i want it to quit if abc is pressed, but nothing happens. (I have added the "K_ESCAPE" event so that i am able to quit while testing. Thanks!
You must not call pygame.event.get() more than once per frame, otherwise you'll miss some events because this function empties the event queue. Just remove the line events = pygame.event.get() and it should work correctly.

Tkinter button doesn't respond (has no mouse over effect)

I'm writing a game that has info that is communicated from client to server and from server to client. One specific (non-playing) client is the monitor, which only displays the game board and players. This works fine, the only thing that doesn't work is the quit button on the GUI. A minor thing, but I would like it to work. :) Plus I think that there might be something pretty wrong with the code, even though it works.
I tried all kind of different commands (sys.exit, quit...) and nothing fixed it.
There's no error message, nothing happens with the button at all. No mouse over effect, nothing if I click it. Relevant code (I removed matrix and server logic because I think it's irrelevant - if it isn't I'll post it):
class Main():
def __init__(self, master):
self.frame = Frame(master)
self.frame.pack()
# Has to be counted up by server class
rounds = 0
# Has to be communicated by server class. If numberwin == numberrobots,
# game is won
numberwin = 0
numberrobots = 2
def draw(self):
if hasattr(self, 'info'):
self.info.destroy()
if hasattr(self, 'quit'):
self.quit.destroy()
print "Main should draw this matrix %s" % self.matrix
[...] lots of matrix stuff [...]
# Pop-Up if game was won
# TODO: Make GUI quittable
if self.numberwin == self.numberrobots:
self.top = Toplevel()
self.msg = Message(self.top, text="This game was won!")
self.msg.pack(side=LEFT)
self.quittop = Button(
self.top, text="Yay", command=self.frame.destroy)
self.quittop.pack(side=BOTTOM)
# TODO: Quit GUI
self.quit = Button(self.frame, text="Quit", command=self.frame.destroy)
self.quit.pack(side=BOTTOM)
# Information on the game
self.info = Label(
self.frame, text="Rounds played: {}, Numbers of robots in win condition: {}".format(self.rounds, self.numberwin))
self.info.pack(side=TOP)
def canvasCreator(self, numberrows, numbercolumns):
# Game board
self.canvas = Canvas(
self.frame, width=numbercolumns * 100 + 10, height=numberrows * 100 + 10)
self.canvas.pack()
class Agent(Protocol, basic.LineReceiver):
master = Tk()
main = Main(master)
# So first matrix is treated differently from later matrixes
flagFirstMatrix = 1
def connectionMade(self):
msg = dumps({"type": "monitor"})
self.sendLine(msg)
print "Sent message:", msg
def dataReceived(self, data):
# Decode the json dump
print "Data received: %s" % data
data = loads(data)
self.main.matrix = np.matrix(data["positions"])
self.main.goals = np.matrix(data["goals"])
self.main.next_move_by_agent = data["next_move"]
self.main.rounds = data["rounds"]
self.main.numberwin = data["win_states"]
if self.flagFirstMatrix == 1:
self.main.numberrows, self.main.numbercolumns = self.main.matrix.shape
self.main.canvasCreator(
self.main.numberrows, self.main.numbercolumns)
self.main.canvas.pack()
self.flagFirstMatrix = 0
self.main.canvas.delete(ALL)
self.main.draw()
self.master.update_idletasks()
self.master.update()
First there is no indentation for class Agent, second for the quit button's "call back" self.frame.destroy is never defined so it doesn't do anything. If you meant tkinter destroy method try self.frame.destroy() or try explicitly defining it. You can also try calling either fram.pack_forget() or fram.grid_forget()
Add master.mainloop() to your last line in terms of the entire lines of code

Tkinter forgetting to finish the function

I am again asking a question on this progressbar project; although this should just be a clarification question.
My code causes for a progressbar to be created to track the creation of a file. The user selects the type of file they want to create and then hits "go" which causes for the file to begin changing and for the progressbar to appear. Progressbar works great. File writing/manipulation works great.
Problem: When the user selects several files to manipulate, despite the progressbars being created correctly, they do NOT update correctly. At first I thought that clicking on a button multiple times causes for tkinter to forget the root.after() function it was doing previously but after playing with a (much simpler) sample code I realized that this is not the case.
Question: How do I make sure tkinter doesn't stop implementing the first function even when the same function is restarted with different parameters?
Below are parts of my code to describe what I am doing.
progbarlock = False # start with the prograssbar marked as not occupied
class guibuild:
def __init__(self):
self.root = root
guibuild.progbarlock = False
global theframe
theframe = Frame(root)
job_name = e.get()
label = Label(theframe,text = job_name).pack(side=LEFT,padx =2)
self.progbar = Meter(theframe) #makes the progressbar object
self.progbar.set(0.0) #sets the initial value to 0
self.progbar.pack(side=LEFT)
self.counter = 0
self.i = float(0) #i is the value set to the progressbar
def stop_progbar(self):
self.progbar.stop()
def begin(self):
self.interval()
self.Status_bar()
theframe.pack(anchor="s")
def interval(self):
if guibuild.progbarlock == False:
guibuild.progbarlock = True
def update(self):
the_file = open('running_file.json')
data = json.load(the_file)
curr = data["current_line"]
total = data["total_lines"]
if self.i == 1.0:
self.stop_progbar
rint "100% - process is done"
self.root.after_cancel(self.interval)
elif curr == self.counter:
self.root.after(5000, self.interval)
elif curr == self.counter+1:
self.i += 1.0/total
self.progbar.set(self.i) #apply the new value of i to the progressbar
self.counter += 1
self.stop_progbar
self.root.after(5000, self.interval)
elif curr > self.counter+1:
self.i += 1.0/total*(curr-self.counter)
self.progbar.set(self.i) #apply the new value of i to the progressbar
self.counter = curr
self.stop_progbar
self.root.after(5000, self.interval)
else:
print "something is wrong - running.json is not available"
self.root.after(5000, self.interval)
guibuild.progbarlock = False
def start_process():
makeRequest() #this is defined much earlier in the code and includes all the file creation and manipulation
guibuild().begin()
button4 = Button(root,text="GO", command = start_process).pack()
NOTE:makeRequest() depends entirely on user input and the user input changes each time "go" is pressed.

Pygame midi prevents other input

I wish to have real-time midi input, in order to control some wx.Sliders. I have been able to achieve this, however it prevents interaction with the sliders via the mouse or keyboard and causes the application to crash.
This is the code I have at the moment.
import wx, pygame, pygame.midi
class windowClass(wx.Frame):
def __init__(self, *args, **kwargs):
super(windowClass, self).__init__(*args, **kwargs)
self.basicGUI()
def basicGUI(self):
panel = wx.Panel(self)
self.slider = wx.Slider(panel, -1, 2, 0, 128, pos=(10,25), size=(250,-1), style=wx.SL_AUTOTICKS | wx.SL_LABELS)
sliderText = wx.StaticText(panel, -1, 'Slider 1 ', (8,8))
self.slider2 = wx.Slider(panel, -1, 2, 0, 128, pos=(10,110), size=(250,-1), style=wx.SL_AUTOTICKS | wx.SL_LABELS)
sliderText = wx.StaticText(panel, -1, 'Slider 2', (8,88))
self.Bind(wx.EVT_SLIDER, self.sliderUpdate)
self.SetTitle('Sliders Window!')
self.Show(True)
pygame.init()
pygame.midi.init()
inp = pygame.midi.Input(1)
running = True
while running:
if inp.poll():
dataset = inp.read(1)
control = dataset[0][0][1]
if control > 8:
continue
if control == 1:
value = dataset[0][0][2]
self.slider.SetValue(value)
if control == 2:
value = dataset[0][0][2]
self.slider2.SetValue(value)
pygame.time.wait(10)
def sliderUpdate(self, event):
value1 = self.slider1.GetValue()
value2 = self.slider2.GetValue()
print value1, value2
def main():
app = wx.App()
windowClass(None)
app.MainLoop()
main()
What is causing pygame.midi to take all resources? I have a feeling it is regarding while running = True, however my attempts at trying to close the instance don't seem to work.
How can I have the sliders being controlled by the midi and the mouse calling sliderUpdate? Thanks for any help.
You have a loop that never exits, so your program never reaches the parts that deal with anything except the midi input
I would move the code that is currently in that loop into a function, remove the loop, and add a timer to the panel, e.g.
def basicGUI(self):
... panel stuff
pygame.init()
pygame.midi.init()
timer = wx.Timer(self, -1)
self.Bind(wx.EVT_TIMER, self.OnTimer)
timer.Start(10, False)
def OnTimer(self, event):
inp = pygame.midi.Input(1)
if inp.poll():
dataset = inp.read(1)
control = dataset[0][0][1]
if control > 8:
continue
if control == 1:
value = dataset[0][0][2]
self.slider.SetValue(value)
if control == 2:
value = dataset[0][0][2]
self.slider2.SetValue(value)

I keep getting a "self" is not defined error

Im trying to add a media file, so that when you press the key a is plays and you let go it stops, any help would be appreciated!
I get the error code self is not defined and I just need a point the right direction.
from __future__ import division
import math
import sys
import pygame
pygame.mixer.init()
pygame.mixer.pre_init(44100, -16, 2, 2048)
class MyGame(object):
def __init__(self):
"""Initialize a new game"""
pygame.init()
self.width = 800
self.height = 600
self.screen = pygame.display.set_mode((self.width, self.height))
#Load resources
sound = pygame.mixer.music.load("a.mp3")
I keep getting a self is not defined error here
#use a black background
self.bg_color = 0, 0, 0
#Setup a timer to refresh the display FPS times per second
self.FPS = 30
self.REFRESH = pygame.USEREVENT+1
pygame.time.set_timer(self.REFRESH, 1000//self.FPS)
# Now jusr start waiting for events
self.event_loop()
def event_loop(self):
"""Loop forever processing events"""
while 1 < 2:
event = pygame.event.wait()
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
sys.exit()
if event.type == pygame.KEYDOWN and event.key == pygame.K_A:
sound.play()
if event.type == pygame.KEYUP and event.key == pygame.K_A:
sound.stop()
elif event.type == self.REFRESH:
# time to draw a new frame
self. draw()
pygame.display.flip()
else:
pass #an event we dont handle
def draw(self):
"""Updating the display"""
self.screen.fill(self.bg_color)
MyGame().run()
pygame.quit()
sys.exit()
You're mixing tabs and spaces. This confuses Python about how far code is indented: your self.bg_color = 0, 0, 0 line isn't as indented as you think it is. Looking at your raw code:
'class MyGame(object):'
'\tdef __init__(self):'
'\t\t"""Initialize a new game"""'
'\t\tpygame.init()'
'\t\t'
'\t\tself.width = 800'
'\t\tself.height = 600'
'\t\tself.screen = pygame.display.set_mode((self.width, self.height))'
'\t\t'
'\t\t#Load resources'
' sound = pygame.mixer.music.load("a.mp3")'
'\t\t#use a black background'
' self.bg_color = 0, 0, 0'
Note the absence of tabs in two of the last four lines.
Use python -tt your_program_name.py to confirm this, and switch to using four spaces for indentation. Most editors allow you to configure this.