I had thought cv.waitKey would pause execution until a key was pressed, but it doesn't seem to be doing so. When I run the following code:
import cv2 as cv
print("Start")
k = cv.waitKey(0)
print("Stop")
It does not wait for a key to be pressed before completing execution. Must there actually be an image shown for the delay to occur? Is there something (one of the many things) about event loop creation occurring, that I don't understand?
(Note: I'm not just looking for something to act as an 'input' line. I'm currently using OpenCV with an eyetracker and was trying to figure out why OpenCV seems to block the callback function of the eyetracker, when I ran into this misunderstanding.)
You need a HighGUI window created and active(in focus):
https://docs.opencv.org/3.4/d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7
So the following would work (with imagefile.png some image on disk):
import cv2 as cv
print("Start")
image=cv.imread("imagefile.png")
cv.imshow("test",image)
k = cv.waitKey(0)
print("Stop")
Related
I am using python 3.5 and OSX 10.13.2.
I am attempting to gather EEG data from a bluetooth EEG recording device while a human is watching a pygame GUI. Because the bluetooth device sends data at about 512 Hz and the pygame GUI updates at about 25Hz, I'm thinking that including the gathering of the bluetooth data and the updating of the GUI in the same loop/process is not appropriate.
Therefore, I want to create two concurrent processes: one for the gathering of bluetooth input and one for displaying/updating the pygame GUI. I think I have figured out how to run a pygame window in a separate process, but creating a separate process using the multiprocessing module that connects to and reads input from my bluetooth device is not working out well.
When I run the code below, execution seems to stop on this line socket.connect(('B0:B4:48:F6:38:A1', 1)): nothing in the connect() method is printed. Is this a problem with Mac OSX, the bluetooth module, Python, or something else? Does anyone know how I can fix this? If not, does anyone have a different way I could approach my initial problem of gathering data from a bluetooth device and updating a GUI in parallel using python 3.5?
import multiprocessing, time, bluetooth
def connect():
socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
try:
socket.connect(('B0:B4:48:F6:38:A1', 1))
print("connected to device!!")
except Exception as e:
print("failed to connect :(")
def wait_and_do_nothing():
print("just sleeping over here in this process")
time.sleep(5)
process1 = multiprocessing.Process(target=connect, args=())
process2 = multiprocessing.Process(target=wait_and_do_nothing, args=())
process1.start()
process2.start()
process1.join()
process2.join()
print("finished")
The output of the above code is:
finished
I solved my problem. For one, I should have wrapped the multiprocessing code in an if statement like the one below. Two, I should have set the start method to 'spawn' instead of 'fork' like I do below:
if __name__ == '__main__':
multiprocessing.set_start_method('spawn', force=True)
process1 = multiprocessing.Process(target=connect, args=())
process2 = multiprocessing.Process(target=wait_and_do_nothing, args=())
process1.start()
process2.start()
process1.join()
process2.join()
I'm writing a code to stream images form raspberry-pi3 to my laptop.
I wrote two versions of code, one using module and other as single block of code.
I'm putting the code here (more details follow the code)
Code that runs fast:
import picamera
import socket
import struct
import time
import io
stream_client= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
stream_client.connect(('192.168.43.34',9000))
print('connected')
camera = picamera.PiCamera()
camera.resolution=(320,240)
camera.color_effects=(128,128)
camera.framerate=18
time.sleep(2)
stream = io.BytesIO()
count=0
start=time.time()
try:
for i in camera.capture_continuous(stream,'jpeg',use_video_port=True):
count+=1
stream_client.sendall(struct.pack('<L',stream.tell()))
stream_client.sendall(struct.pack('<h',count))
stream_client.sendall(stream.getvalue())
stream.seek(0)
stream.truncate()
if(time.time()-start>10):
break
finally:
stream_client.sendall(struct.pack('<L',0))
stream_client.close()
camera.close()
print('connection closed')
The codes that runs slowly:
Module (contained in a different file "CameraStreamModule.py" in same folder):
'''
MODULE NAME: CAMERA STREAMING MODULE
OBJECTIVE: TO SEND IMAGE DATA FROM RASPBERRY-PI3 TO LAPTOP VIA TCP/IP STREAM
HARDWARE USED: RASPBERRY PI 3, PI CAMERA REV 1.3
PYTHON VERSION: 3.5.3
DATE WRITTEN: 8-1-2018
'''
'''************************************************************** IMPORTING MODULES ***********************************************************************'''
import picamera # PI CAMERA MODULE
import socket # MODULE TO HANDLE TCP/IP CONNECTION AND TRANSFER
import struct # MODULE TO CONVERT DATA TO BYTE-LIKE OBJECTS (REQUIRED BY SOCKET METHODS)
import time # MODULE FOR TIME RELATED FUNCTIONS
import io # MODULE USED TO CREATE IN-MEMORY DATA STREAMS
'''************************************************************ MODULE IMPORTS END HERE *******************************************************************'''
'''*********************************************************** DECLARING GLOBAL VARIABLES *****************************************************************'''
LIMITED_STREAM = False # Stream only for short time when true
LIMIT_TIME= 10 # Seconds
stream = io.BytesIO()
stream_client= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
camera = picamera.PiCamera()
count=0
'''*********************************************************** GLOBAL VARIABLES END HERE ******************************************************************'''
'''************************************************************** METHOD DEFINITIONS ***********************************************************************'''
def Client_init (Server_ip,Server_port): # (str,int) expected as parameter
global stream_client,start,LIMITED_STREAM
stream_client.connect((Server_ip,Server_port))
if LIMITED_STREAM :
start=time.time()
print('connected')
def Camera_init (Resolution_tuple,Colour_tuple,Frame_rate): # (int_tuple,int_tuple,int) expected as parameter
global camera
camera.resolution= Resolution_tuple
camera.color_effects=Colour_tuple
camera.framerate= Frame_rate
time.sleep(2)
'''
THIS METHOD IS INTENDED TO BE CALLED INSIDE "for i in camera.capture_continuous(stream,'jpeg',use_video_port=True):" CONTINUOUSLY. ALSO .close() FOR SOCKET
AND CAMERA MUST BE CALLED SEPERATELY.
'''
def Send_frame ():
global count,stream_client,stream,LIMITED_STREAM
count+=1
stream_client.sendall(struct.pack('<L',stream.tell()))
stream_client.sendall(struct.pack('<h',count))
stream_client.sendall(stream.getvalue())
stream.seek(0)
stream.truncate()
if LIMITED_STREAM:
if(time.time()-start>LIMIT_TIME):
raise Exception('Time Finished')
'''********************************************************* METHOD DEFINITIONS END HERE ******************************************************************'''
The calling code:
import importlib
Camera_module= importlib.import_module('CameraStreamModule')
Camera_module.LIMITED_STREAM= True
Camera_module.Client_init('192.168.1.102',9000)
Camera_module.Camera_init((320,240),(128,128),18)
try:
for i in Camera_module.camera.capture_continuous(Camera_module.stream,'jpeg',use_video_port=True):
Camera_module.Send_frame()
finally:
Camera_module.camera.close()
Camera_module.stream_client.sendall(struct.pack('<L',0))
Camera_module.stream_client.close()
print('connection closed')
The first code streams about 179 images in 10 seconds and the second version does about 133 images which is a drastic reduction. I just wanted to create a module to make code more manageable and readable.
I have started coding in Python quite recently and I know that my method of coding may look ridiculous to more experienced coders (trust me, I'm trying to improve). Can anyone tell me what could be the reason of this slowdown?
I have observed that even changing the WiFi connection has an effect on the amount of data transferred in a given amount of time, so I have kept the WiFi connection the same for both versions of code.
I think that this slowdown occurrs because I'm passing a lot of data back and forth between modules ?
In any case, any advice/help regarding the code is welcome.
P.S: If you feel that my way of asking questions on this platform is not up to the mark and I need to give more or reduce the details, please let me know.
OK I found out the problem. Actually in the reciever code that I created , I had written a lot of print() statements for debugging purpose. which were causing the delay and due to this I was loosing some data since the socket transmission was asynchronous (and i did not handle the problem of data loss in the code). Along with this and probably the delay in passing large array data, back and forth between the modules caused this problem
Leaving this answer here just in case someone finds it useful.
I'm plotting an animation of circles. It looks and works great as long as speed is set to a positive number. However, I want to set speed to 0.0. When I do that, something changes and it no longer animates. Instead, I have to click the 'x' on the window after each frame. I tried using combinations of plt.draw() and plt.show() to get the same effect as plt.pause(), but the frames don't show up. How do I replicate the functionality of plt.pause() precisely either without the timer involved or with it set to 0.0?
speed = 0.0001
plt.ion()
for i in range(timesteps):
fig, ax = plt.subplots()
for j in range(num):
circle = plt.Circle(a[j], b[j]), r[j], color='b')
fig.gca().add_artist(circle)
plt.pause(speed)
#plt.draw()
#plt.show()
plt.clf()
plt.close()
I've copied the code of pyplot.pause() here:
def pause(interval):
"""
Pause for *interval* seconds.
If there is an active figure it will be updated and displayed,
and the GUI event loop will run during the pause.
If there is no active figure, or if a non-interactive backend
is in use, this executes time.sleep(interval).
This can be used for crude animation. For more complex
animation, see :mod:`matplotlib.animation`.
This function is experimental; its behavior may be changed
or extended in a future release.
"""
backend = rcParams['backend']
if backend in _interactive_bk:
figManager = _pylab_helpers.Gcf.get_active()
if figManager is not None:
canvas = figManager.canvas
canvas.draw()
show(block=False)
canvas.start_event_loop(interval)
return
# No on-screen figure is active, so sleep() is all we need.
import time
time.sleep(interval)
As you can see, it calls start_event_loop, which starts a separate crude event loop for interval seconds. What happens if interval == 0 seems backend-dependend. For instance, for the WX backend a value of 0 means that this loop is blocking and never ends (I had to look in the code here, it doesn't show up in the documentation. See line 773).
In short, 0 is a special case. Can't you set it to a small value, e.g. 0.1 seconds?
The pause docstring above says that it can only be used for crude anmiations, you may have to resort to the animation module if you want something more sophisticated.
def updateV(self, event):
""""""
global v
v=random.uniform(1,10)
print('battery voltage =')
print(v)
if v>3:
self.labelOne.SetBackgroundColour('red')
self.labelOne.SetLabel('Battery Voltage : ' + str(v))
else:
self.labelOne.SetBackgroundColour('white')
self.labelOne.SetLabel('Battery Voltage : ' + str(v))
self.Refresh()
this is a function in my wxpython GUI which i use for generating random values.I have added this function in my panel class of the GUI. I have put a wx.Bind function that assigns a timer value to it and refreshes it regularly for value change regularly.
Now the GUI needs to have serial communication as I need to get sensor values and get them input in my GUI screen. So i found this code for serially inputing the value:
def updateV(self, event):
""""""
global v
v=ser.readline()
print v
if v>3:
self.labelOne.SetBackgroundColour('red')
self.labelOne.SetLabel('Battery Voltage : ' + str(v))
else:
self.labelOne.SetBackgroundColour('white')
self.labelOne.SetLabel('Battery Voltage : ' + str(v))
self.Refresh()
I then went it the init part of the panel class and added this code:
ser = serial.Serial('COM3', 9600, timeout=0)
On running the GUI, the value doesnt appear nor does it print it on the GUI. I know I am doing a big mistake here. Anyways the values right now come through an arduino uno connected to a XBEE shield which receives 1-20 values through another arduino conencted to a XBEE shield. By the way, random variables are generated properly and are printed in the GUI so there is'nt any proble with the function.
I need a way for python to read the value serially and assign it to a variable such that I can print the value I get in my GUI screen.
PS: I used the same serial code to properly get 0 1 2 3 4 5 6 7 8 9 10 value on the command screen of python module.
import serial
import time
ser = serial.Serial('COM3', 9600, timeout=0)
while 1:
v=ser.readline()
print v
time.sleep(1)
I am trying to get used to python, but these small things hinder my progress.. I am new to python, please bear with me!
Your problem is essentially that reading the serial interface in the while loop with ser.readline() as in your last example (EDIT1: and also when polling with a wx.Timer event) will block the GUI when it is waiting for data on the serial interface. Calling the app.MainLoop() will loop the wxPython event system. However, the only thing your GUI example will do is blocking at ser.readline(). As soon some data comes it will continue in the updateV method. But because the next timer event is waiting already, it will run to ser.readline() and block there again and preventing any GUI updates.
Did you try out the wxTerminal example in the pyserial package?
It shows how to spin of a thread which will do the reading and sending a user-defined SerialRxEvent so that everything is thread-safe.
You also should read LongRunningTasks in the wxPython wiki to get an idea how to use threads for long running/blocking tasks in wxPython and communicate back to the main GUI thread safely.
Is there a way to set matlab to come to the foreground of the windows when the command in complete? I can see it happening by executing a dos() but I'm unaware how window management works? Maybe there is a better way? Someone?
Two options. Neither exactly what you are asking for.
Option 1: Open a new figure.
figure();
imagesc(processingDoneSplashImage);
If you want to get fancy, put this in a script, with a timer, and flash the image between bright green, and bright red....
Option 2: My solution to your problem. (I find popping up windows extremely annoying.) I put this function call at the end of my long running scripts, and the computer tells me when it's done processing....
function [ ] = matSpeak( textToSpeak )
%matSpeak takes some text, and outputs onto the speaker the text,
% using the .Net SpeechSynthesizer.
% This only works on Windoze.
if ~exist('textToSpeak','var')
textToSpeak = 'Your processing has completed.';
end
NET.addAssembly('System.Speech');
speak = System.Speech.Synthesis.SpeechSynthesizer;
speak.Volume = 100;
speak.Speak(textToSpeak);
end
Why not just use Growl for your notification windows?
cmd = ['/usr/local/bin/growlnotify -m ' messagestr];
system(cmd);
Of course with Windows you need to fix the path to the growlnotify binary.
Source: http://www.mathworks.com/matlabcentral/newsreader/view_thread/259142
A wrapper with lots of features: Send a notification to Growl on MATLAB Exchange
Many more examples: https://www.google.com/search?q=growl+matlab