Detect key pressed in a loop - python

I am trying to detect the key pressed by a user in order to reset a variable for my program, a basic application to detect a barcode, which is running inside a While true
I have tried using keyboard library like in the first solution suggested here
import keyboard # using module keyboard
while True:
if keyboard.is_pressed('q'): # if key 'q' is pressed
print('You Pressed A Key!')
...
but I m getting an error You must be root to use this library on Linux. I am not sure if that it means is not possible to use this approach in my case because I m ruining the program on Raspberry Pi OS.
I also tried the second approach ( from the same link) using pynput.keyboard but as the author says, it does not perform well when using inside a loop. the application waits for a key to be pressed.
Edit : More Info
from pyzbar import pyzbar
import datetime
import imutils
import time
from imutils.video import VideoStream
import pika
import json
from pynput.keyboard import Key, Listener
connection = pika.BlockingConnection(
pika.ConnectionParameters(host="----",
virtual_host="----",
credentials=pika.credentials.PlainCredentials(
"---", "---")
))
channel = connection.channel()
channel.queue_declare(queue='barcode_queue')
print("[INFO] Connection Started ...")
vs = VideoStream(usePiCamera=True).start()
print("[INFO] starting video stream...")
time.sleep(2.0)
userWebsocket = None
while True:
# this is what I want to achive
# key = Get the key pressed
# if key == 'q' then userWebsocket = None
frame = vs.read()
frame = imutils.resize(frame, width=400)
barcodes = pyzbar.decode(frame)
for barcode in barcodes:
barcodeData = barcode.data.decode("utf-8")
barcodeType = barcode.type
if barcodeType == 'QRCODE':
decodedBarcode = json.loads(barcodeData)
print(decodedBarcode)
print(decodedBarcode['name'])
userWebsocket = decodedBarcode['id']
else:
print(datetime.datetime.now(), barcodeData, barcodeType)
if (userWebsocket is None):
print("please login before")
else:
sentObj = {"socket": userWebsocket, "barcode": barcodeData}
jsonSentObj = json.dumps(sentObj)
channel.basic_publish(exchange='', routing_key='barcode_queue', body=jsonSentObj)
time.sleep(5)
vs.stop()
What I want to achieve is to "sign-out" the user when he presses a certain key.

Related

how to convert a str key= to an integer?

I'm having difficulty converting a key into an integer numeral, or finding a better way for Input to capture directly into a numeral so I don't need to convert
I tried converting as follows tempo_init = int(tempo) but the result is still a string, while what i expected was an integer numeral, so i add it to the schedule and it runs the code every certain amount of minutes.
If I leave out the graphical interface of PySimpleGUI, the code runs normally the way I expect.
import os
import sys
import time
import schedule
import PySimpleGUI as sg
import pyautogui
sg.theme('DarkAmber')
layout = [[sg.Text('De quanto em quantos minutos rodar o anuncio?')],
[sg.InputText(key='tempo')],
[sg.Button('OK'), sg.Button('Cancel')]]
def start_python_code():
pyautogui.press('playpause')
pyautogui.PAUSE = 1.0
from pygame import mixer
mixer.init()
mixer.music.load('C:\\Sounds\\adsSound.mp3')
mixer.music.play()
while mixer.music.get_busy():
pass
pyautogui.press('playpause')
def temp_interval():
schedule.every(adsTimeInterval).minutes.do(start_python_code)
def temp_read():
while 1:
schedule.run_pending()
time.sleep(1)
window = sg.Window('Sound Ads', layout)
while True:
event, values = window.read()
tempo = sg.InputText(key='tempo')
tempo_init = int(tempo)
adsTimeInterval = tempo_init
if event == sg.WIN_CLOSED or event == 'Cancel':
break
start_python_code()
temp_interval()
temp_read()

using a python queue with an external class - not in the same file

I have a question regarding threading and queueing in python. I have a class that recognises faces and another script that is supposed to retrieve these recognised faces. And I'm unable to retrieve the recognised faces, once recognition starts
I posted another question that relates to this one, but here it's more about the actual user recognition part (this just in case someone stumbles over my other question and thinks this may be a duplicate).
So as said, I have a class that uses imutile and face_recognition to do just that - do face recognition. My issue with the class is that, once it's started it does recognise faces perfectly but it's not possible from an outside class (from within another script) to call any other method for example to retrieve a dict with the currently identified faces. I think this is problably because, once the actual recognition is called, the call to other methods within this class is not going through because of threading???. I attached the complete code for reference below.
Here is the code that is supposed to start the recogniser class and retrieve the results from within another script:
class recognizerAsync(Thread):
def __init__(self):
super(recognizerAsync,self).__init__()
print("initiating recognizer class from recognizerAsync")
if (use_user == True):
#myRecognizer = recognizer(consoleLog, debugMsg, run_from_flask)
self.myRecognizer = the_recognizer.recognizerAsync(False, True, True)
#face_thread = recognizerAsync(consoleLog, debugMsg, False)
def run(self):
print("starting up recogizer from callRecognizerThread")
self.myRecognizer.run()
if (use_user == True):
self.myRecognizer.start()
while (True):
if ( not q.full() ):
#fd = random.randint(1,10)
fd = self.myRecognizer.returnRecognizedFaces()
print(f"PRODUCER: putting into queue {fd}")
q.put(fd)
#else:
# print("ERROR :: Queue q is full")
time.sleep(10)
And I start this like so in the very end:
mirror = GUI(window)
mirror.setupGUI()
window.after(1000, mirror.updateNews)
face_thread = recognizerAsync()
face_thread.start()
window.mainloop()
My question is, how would I need to change either the recogniser classier the recognizerAsync class in the other script, so that while the method faceRecognizer() is running indefinitely, one can still call other methods - specifically returnRecognizedFaces()???
Thank you very much, folks.
#!/usr/bin/env python3
# import the necessary packages for face detection
from imutils.video import VideoStream
from imutils.video import FPS
import face_recognition
import imutils
import pickle
import time
import base64
import json
from threading import Thread
class recognizerAsync(Thread):
# How long in ms before a person detection is considered a new event
graceTimeBeforeNewRecognition = 6000 #60000
# the time in ms when a person is detected
timePersonDetected = 0
# ceate an empty faces dictionary to compare later with repetive encounterings
faces_detected_dict = {"nil": 0}
# Determine faces from encodings.pickle file model created from train_model.py
encodingsP = "" # "encodings.pickle"
# load the known faces and embeddings along with OpenCV's Haar
# cascade for face detection - i do this in the class initialization
#data = pickle.loads(open(encodingsP, "rb").read())
data = ''
# print dictionary of recognized faces on the console?
print_faces = False
debug_mnessagesa = False
called_from_flask = True # this changes the path to the
def __init__(self, print_val=False, debug_val=False, called_from_flask=True):
super(recognizerAsync,self).__init__()
self.print_faces = print_val
self.debug_messages = debug_val
if (called_from_flask == False):
encodingsP = "encodings.pickle"
else:
encodingsP = "Recognizer/encodings.pickle"
# load the known faces and embeddings along with OpenCV's Haar
# cascade for face detection
self.data = pickle.loads(open(encodingsP, "rb").read())
if (self.debug_messages == True):
print("Faces class initialized")
def run(self):
self.faceRecognizer()
def returnRecognizedFaces(self):
if (self.debug_messages == True):
print("from returnRecognizedFaces: returning: " + str((({k:self.faces_detected_dict[k] for k in self.faces_detected_dict if k!='nil'}))))
# print(f"from returnRecognizedFaces: returning: {self.faces_detected_dict}")
return(({k:self.faces_detected_dict[k] for k in self.faces_detected_dict if k!='nil'}))
def faceRecognizer(self):
try:
# initialize the video stream and allow the camera sensor to warm up
# Set the ser to the followng
# src = 0 : for the build in single web cam, could be your laptop webcam
# src = 2 : I had to set it to 2 inorder to use the USB webcam attached to my laptop
#vs = VideoStream(src=2,framerate=10).start()
vs = VideoStream(src=0,framerate=10).start()
#vs = VideoStream(usePiCamera=True).start()
time.sleep(2.0)
# start the FPS counter
fps = FPS().start()
if (self.debug_messages == True):
print("starting face detection - press Ctrl C to stop")
# loop over frames from the video file stream
while (True):
# grab the frame from the threaded video stream and resize it
# to 500px (to speedup processing)
frame = vs.read()
try:
frame = imutils.resize(frame, width=500)
except:
# Error: (h, w) = image.shape[:2]
# AttributeError: 'NoneType' object has no attribute 'shape'
break
# Detect the fce boxes
boxes = face_recognition.face_locations(frame)
# compute the facial embeddings for each face bounding box
encodings = face_recognition.face_encodings(frame, boxes)
names = []
# loop over the facial embeddings
for encoding in encodings:
# attempt to match each face in the input image to our known encodings
matches = face_recognition.compare_faces(self.data["encodings"], encoding)
name = "unknown" #if face is not recognized, then print Unknown
timePersonDetected = time.time()*1000.0
# check to see if we have found a match
if (True in matches):
# find the indexes of all matched faces then initialize a
# dictionary to count the total number of times each face
# was matched
matchedIdxs = [i for (i, b) in enumerate(matches) if b]
counts = {}
# loop over the matched indexes and maintain a count for
# each recognized face face
for i in matchedIdxs:
name = self.data["names"][i]
counts[name] = counts.get(name, 0) + 1
# determine the recognized face with the largest number
# of votes (note: in the event of an unlikely tie Python
# will select first entry in the dictionary)
name = max(counts, key=counts.get)
# If someone in your dataset is identified, print their name on the screen and provide them through rest
if (max(self.faces_detected_dict, key=self.faces_detected_dict.get) != name or timePersonDetected > self.faces_detected_dict[name] + self.graceTimeBeforeNewRecognition):
# put the face in the dictionary with time detected so we can prrovide this info
# in the rest endpoint for others - this is not really used internally,
# except for the timePersonDetected time comparison above
self.faces_detected_dict[name] = timePersonDetected
# update the list of names
names.append(name)
# exemplary way fo cleaning up the dict and removing the nil entry - kept here for reference:
#new_dict = ({k:self.faces_detected_dict[k] for k in self.faces_detected_dict if k!='nil'})
self.last_recognized_face = name
if (self.print_faces == True):
print(self.last_recognized_face)
# clean up the dictionary
new_dict = {}
for k, v in list(self.faces_detected_dict.items()):
if (v + self.graceTimeBeforeNewRecognition) < (time.time()*1000.0) and str(k) != 'nil':
if (self.debug_messages == True):
print('entry ' + str(k) + " dropped due to age")
else:
new_dict[k] = v
self.faces_detected_dict = new_dict
if (self.debug_messages == True):
print(f"faces dict: {self.faces_detected_dict}")
# update the FPS counter
fps.update()
time.sleep(1)
except KeyboardInterrupt:
if (self.debug_messages == True):
print("Ctrl-C received - cleaning up and exiting")
pass

close the frame after detecting qr code with opencv

I've been working on this project to detect qr-code and make attendance and have the outputs in sql database and so far I've gotten everything to work out,
The Problem is I actually want the frame to close when a single QR code is detected, decoded and all of the above process is completed also The camera works and the frame shows up but it is very slow when detecting the QR code.
What actually happens is after the frame is open it constantly and after it detects a QR code, it actually logs multiple (around 15) instances of a QR being detected after like 2 seconds. Also the frame is still up and I can still detect Images.
The frame closes, only after pressing the waitkey which is 27 or 'Esc'
So I am actually looking for 2 Things:
How to close the frame after detecting a QR Code?
(additional question) how do I detect only one qr code (whether the frame closes or not). So when I scan the QR code, either the frame closes and I am left with one decoded data OR I scan the QR code and the frame remains open, until I hit 'Esc' and I am left with one decoded data.
here is the full code for reference:
import cv2
import os
import csv
import sqlite3
import vobject
from datetime import datetime
import numpy as np
from pyzbar import pyzbar
path = 'qr-codes'
images = []
classNames = []
lists = os.listdir(path)
for cl in lists:
curImage = cv2.imread(f'{path}/{cl}')
images.append(curImage)
classNames.append(os.path.splitext(cl)[0])
def main():
camera = cv2.VideoCapture(0)
ret, frame = camera.read()
while ret:
ret, frame = camera.read()
recognizer = parse_vcard(frame)
win_name = 'Face and QR Detection'
cv2.imshow(win_name, recognizer)
if cv2.waitKey(1) & 0xFF == 27:
break
camera.release()
cv2.destroyAllWindows()
def parse_vcard(frame):
barcodes = pyzbar.decode(frame)
for barcode in barcodes:
x, y, w, h = barcode.rect
cv2.rectangle(frame, (x, y),(x+w, y+h), (0, 255, 0), 2)
mydata = barcode.data.decode('utf-8')
vcard = vobject.readOne(mydata)
make_attendence(vcard)
return frame
def make_attendence(vcard):
name = str(vcard.contents['n'][0].value)
# print(type(Employee.name))
profession = str(vcard.contents['title'][0].value)
now = datetime.now()
date = datetime.date(now)
attendance_time = now.strftime('%H:%M:%S')
leave_time = '21:00:00'
connection = sqlite3.connect('employee.db')
conn = connection.cursor()
# conn.execute("""CREATE TABLE employees (
# name text,
# profission text,
# date date,
# attendance_time time,
# leave_time time
# )""")
conn.execute("INSERT INTO employees VALUES \
(:name, :profession, :date, :attendance_time, :leave_time)", {
'name': name,
'profession': profession,
'date': date,
'attendance_time': attendance_time,
'leave_time': leave_time})
connection.commit()
connection.close()
if __name__ == '__main__':
main()
do not reconnect to the database for every QR code and every picture you take.
connect once. keep the connection.
the imshow window is a window. a "frame" is commonly the term for one picture/image from a video. you can't "close" a frame.
you can close imshow windows with destroyAllWindows or individual imshow windows using destroyWindow
use python's "pdb" debugger. use a profiler to investigate the time cost of your code. use time.perf_counter() and do the measurements yourself, if you don't find a profiler you like.

How To Read File Input In pySimpleGUI Then Pass It On To A Number-Crunching Processor

I would like to take input from pySimpleGUI, feed it into a normal Python var, then feed it into a music processor as I love music.
I had already tried to use wxPython for this but was unable to even get a simple fileDialog without crashing.
from pydub import AudioSegment
from os import listdir
import numpy as np
import math
import PySimpleGUI as sg
class Dankify():
song_dir = "songs"
attenuate_db = 0
accentuate_db = 2
yeet = sg.Window('Dankify ALL THE THINGS!'). Layout([[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()] ]).Read()
event, values = yeet.Read()
yeet1 = event, values
def bass_line_freq(track):
sample_track = list(track)
# c-value
est_mean = np.mean(sample_track)
# a-value
est_std = 3 * np.std(sample_track) / (math.sqrt(2))
bass_factor = int(round((est_std - est_mean) * 0.005))
return bass_factor
songfile = yeet1
for filename in listdir(songfile):
sample = AudioSegment.from_mp3(songfile)
filtered = sample.low_pass_filter(bass_line_freq(sample.get_array_of_samples()))
combined = (sample - attenuate_db).overlay(filtered + accentuate_db)
combined.export("exports/" + filename.replace(".mp3", "") + "-export.mp3", format="mp3")
However, it just does nothing, not even processing it. A reminder that I am using some open-source code and that I'm a beginner which knows nothing about how all this works and am trying to build real stuff to gain experience. Thanks!
I guess you are missing the "event loop".
Try something like this, hope it helps.
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_') ],
[sg.Input(do_not_clear=True, key='_IN_')],
[sg.Button('Show'), sg.Button('Exit')]]
window = sg.Window('Window Title').Layout(layout)
while True: # Event Loop
event, values = window.Read()
print(event, values)
if event is None or event == 'Exit':
break
if event == 'Show':
# change the "output" element to be the value of "input" element
window.FindElement('_OUTPUT_').Update(values['_IN_'])
window.Close()
You're doing 2 Read calls.
Try changing to this:
yeet = sg.Window('Dankify ALL THE THINGS!').Layout(
[[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()]])
event, values = yeet.Read()
Without the Read on the end of the first statement.
You are instantiating this class, right?
d = Dankify()

Accessing Beaglebone python opencv usb camera but the display showing black screen

I am facing issue while accessing USB camera using beagle-bone black wireless.
Firstly the error is "select timeout" exception which was resolved by this post
Now I am facing the black screen in output.
Here is the testing code I am using.
from cv2 import *
# initialize the camera
cam = VideoCapture(0) # 0 -> index of camera
print "Cam capture"
cam.set(3,320)
cam.set(4,240)
print "Cam set"
s, img = cam.read()
print "Cam read"
if s: # frame captured without any errors
namedWindow("cam-test",CV_WINDOW_AUTOSIZE)
imshow("cam-test",img)
while True:
key = waitKey(30)
if key == ord('q') :
destroyWindow("cam-test")
I have already check that video0 in /dev directory.
The issue is that you need to call 'cam.read()andimshow()` inside the while loop
What you're doing is that you're reading just the first frame, then showing it, and you whileloop isn't doing anything. When the camera boots, the first frame is just a blank screen , which is what you see.
The code should be more like:
while True:
s, img = cam.read()
imshow("cam-test",img)
key = waitKey(30)
if key == ord('q') :
destroyWindow("cam-test")

Categories