Stream video in python use pygame lib - python-2.7

I use library pygame in python to stream video from webcam of RasberryPi to my computer.
But I have a problem when receive image. It's not convert true image.
I've replaced my cam's ip adress with a placeholder <my_ip>.
This is my code:
Server:
import socket,os
from PIL import *
import pygame,sys
import pygame.camera
from pygame.locals import *
#Create server:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((<my_ip>,5000))
server.listen(5)
#Start Pygame
pygame.init()
pygame.camera.init()
screen = pygame.display.set_mode((320,240))
cam = pygame.camera.Camera("/dev/video0",(320,240),"RGB")
cam.start()
#Send data
while True:
s,add = server.accept()
print "Connected from",add
image = cam.get_image()
screen.blit(image,(0,0))
data = cam.get_raw()
s.sendall(data)
pygame.display.update()
#Interupt
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
Client:
import socket,sys
import pygame
from PIL import Image
#Create a var for storing an IP address:
ip = <my_ip>
#Start PyGame:
pygame.init()
screen = pygame.display.set_mode((320,240))
pygame.display.set_caption('Remote Webcam Viewer')
font = pygame.font.SysFont("Arial",14)
clock = pygame.time.Clock()
timer = 0
previousImage = ""
image = ""
#Main program loop:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
#Receive data
if timer < 1:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((str(ip),5000))
data = client_socket.recv(1024000)
timer = 30
else:
timer -= 1
previousImage = image
#Convert image
try:
image = Image.fromstring("RGB",(120,90),data)
image = image.resize((320,240))
image = pygame.image.frombuffer(image.tostring(),(320,240),"RGB")
#Interupt
except:
image = previousImage
output = image
screen.blit(output,(0,0))
clock.tick(60)
pygame.display.flip()
But this is result after tranfer:

You are reassembling an image from the raw data received, but because you are sending a bigger resolution that you are re-creating, the pixels are 'overflowing' creating this effect.
the offending line is:
image = Image.fromstring("RGB",(120,90),data)
which should be:
image = Image.fromstring("RGB",(320,240),data)
*Not tested but should work.

Related

How to find the mouse hover positions (preferably timestamps) on a video?

I am trying to save the mouse hover positions in a given video. I need to load the video on a 'Load Video' button press. When the mouse is outside the canvas no (x,y) should be saved. I also want the video to streamed at much lower rate (say, 4 times slower). Presently, I have the following code:`
import Tkinter as tk
from Tkinter import *
import PIL.Image,PIL.ImageTk
import time
import cv2
class App:
def __init__(self, window, window_title, video_source=0):
self.window = window
self.window.title(window_title)
self.video_source = video_source
self.video_loaded=False
# open video source (by default this will try to open the computer webcam)
self.vid = MyVideoCapture(self.video_source)
# Create a canvas that can fit the above video source size
self.canvas = tk.Canvas(window, width = self.vid.width, height =
self.vid.height)
self.canvas.pack()
self.canvas.bind('<Motion>',self.canvas.motion)
#self.canvas.bind("<Enter>", self.on_enter)
#self.canvas.bind("<Leave>", self.on_leave)
# Button that lets the user take a snapshot
self.btn_snapshot=tk.Button(window, text="Snapshot", width=50,
command=self.snapshot)
self.btn_snapshot.pack(anchor=tk.CENTER, expand=True)
self.btn_collapse=tk.Button(window, text="Collapse", width=50,
command=self.collapse)
self.btn_collapse.pack(anchor=tk.CENTER, expand=True)
self.btn_load_video=tk.Button(window, text="Load Video", width=50,
command=self.load_video)
self.btn_load_video.pack(anchor=tk.CENTER, expand=True)
#if self.video_loaded==True:
# After it is called once, the update method will be automatically
called every delay milliseconds
self.delay = 15
self.update()
self.window.mainloop()
def load_video(self):
# open video source (by default this will try to open the computer
webcam)
self.vid = MyVideoCapture(self.video_source)
self.video_loaded=True
def snapshot(self):
# Get a frame from the video source
ret, frame = self.vid.get_frame()
if ret:
cv2.imwrite("frame-" + time.strftime("%d-%m-%Y-%H-%M-%S") + ".jpg",
cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
def collapse(self):
self.window.quit()
def motion(self):
self.x=self.canvas.winfo_pointerx
self.y=self.canvas.winfo_pointery
print('{},{}'.format(self.x, self.y))
#self.canvas.itemconfigure(text='({x},{y})'.format(x = self.x,
y=self.y))
#print('{},{}'.format(self.x, self.y))
#def motion(self):
# x, y = self.x, self.y
# print('{}, {}'.format(x, y))
#def on_enter(self, event):
# self.l2.configure(text="Hello world")
#def on_leave(self, enter):
# self.l2.configure(text="")
def update(self):
# Get a frame from the video source
ret, frame = self.vid.get_frame()
if ret:
self.photo = PIL.ImageTk.PhotoImage(image =
PIL.Image.fromarray(frame))
self.canvas.create_image(0, 0, image = self.photo, anchor = tk.NW)
self.window.after(self.delay, self.update)
class MyVideoCapture:
def __init__(self, video_source=0):
# Open the video source
video_source='./videofilename.wmv'
self.vid = cv2.VideoCapture(video_source)
if not self.vid.isOpened():
raise ValueError("Unable to open video source", video_source)
# Get video source width and height
self.width = self.vid.get(cv2.CAP_PROP_FRAME_WIDTH)
self.height = self.vid.get(cv2.CAP_PROP_FRAME_HEIGHT)
def get_frame(self):
if self.vid.isOpened():
ret, frame = self.vid.read()
if ret:
# Return a boolean success flag and the current frame converted
to BGR
return (ret, cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
else:
return (ret, None)
else:
return (ret, None)
# Release the video source when the object is destroyed
def __del__(self):
if self.vid.isOpened():
self.vid.release()
# Create a window and pass it to the Application object
root = tk.Tk()
App(root, "Tkinter and OpenCV")
When I run this, I get the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/home/anaconda2/envs/my_env/lib/python2.7/lib-tk/Tkinter.py", line
1541, in __call__
return self.func(*args)
TypeError: motion() takes exactly 1 argument (2 given)
I want the function motion() to return the mouse hover positions. Appreciate help. Thanks in advance.
Here is the link from which the I got the main code.
The bind() function sends an event object to the callback function, but the motion() function only accepts self. Try:
def motion(self, event):
self.x=event.x
self.y=event.y
Binding the function for saving mouse positions can be done as in teh example below.
from tkinter import *
root = Tk()
root.geometry('300x200+800+50')
c = Canvas(root, bg='tan')
c.pack(fill='both', expand='yes')
def motion(event):
if follow:
print(event.x, event.y)
follow = False
def follow_motion(event):
global follow
follow = not follow
c.bind('<Motion>', motion)
c.bind('<Button-1>', follow_motion)
root.mainloop()
Click the left mouse button on the canvas and the function motion() is enabled. One more click disables it.

How can i display a resized image in python tkinter

I'm developing a GUI in Python using Tkinter to learn image processing. GUI's process flow would be as
Load image (jpg|png|...) => Resize/ thumbnail image (240 * 240) => Preview image
from Tkinter import *
import PIL
class Window:
def __init__(self, master):
master.title("Image Processing test")
master.minsize(800, 400)
from PIL import Image
im = Image.open("IMG_0562.png")
size = 240, 240
im.thumbnail(size)
p = im.tobytes()
# photo = PhotoImage(file="IMG_0562.gif")
# photo = BitmapImage(data=p)
w = Label(root, image=photo, width=240, height=240).grid(row=20, column=2)
self.photo = photo
root = Tk()
window = Window(root)
root.mainloop()
My problem is I couldn't get the image in a proper format to use it in Label. As Label only accepts PhotoImage and BitmapImage. PhotoImage doesn't support png or jpg file. So I used Image from PIL to load and resize my colored image. I've tried Image.tobitmap() and Image.tobytes() too but not useful in this case.
Solved the problem by saving the image in memory using io.BytesIO()
from Tkinter import *
from PIL import Image
import io
class Window:
def __init__(self, master):
master.title("Image Processing test")
master.minsize(800, 400)
im = Image.open("IMG_0562.png")
size = 240, 240
im.thumbnail(size)
b = io.BytesIO()
im.save(b, 'gif')
p = b.getvalue()
photo = BitmapImage(data=p)
w = Label(root, image=photo, width=240, height=240).grid(row=20, column=2)
self.photo = photo
root = Tk()
window = Window(root)
root.mainloop()

opencv face detection CAPTCHA

please im working on using face detection as a captcha system. how do i make the system print an error message if a face is not detected in the webcam. and also make the number of attempts to detect a face is 3 such that after 3 attempts it closes in python
from Tkinter import *
import numpy as np
import cv2
import Tkinter as tk
import tkMessageBox
import random
import webbrowser
def Request_1(event):
#messagebox gestures
trials = 0
while trials<3:
tkMessageBox.showinfo("ATTENTION!!!", "press letter a when you see the yellow box on your nose")
#this aspect is to generate random requests for the captcha system
detector2= cv2.CascadeClassifier('haarcascade_mcs_nose.xml')
cap = cv2.VideoCapture(0)
access = True
while(access):
#reads the image
ret2, img2 = cap.read()
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# Detect faces in the image . the image is read and convertedd to grayscale
faces2 = detector2.detectMultiScale(gray2, 1.3, 5)
if(len(faces2)!=0):
for (x,y,w,h) in faces2:
cv2.rectangle(img2,(x,y),(x+w,y+h),(0,255,255),1)
cv2.imshow('frame',img2)
break
if cv2.waitKey(1) & 0xFF == ord('a'):
#grant access to webpage
cap.release()
cv2.destroyAllWindows()
new=2
url="file:///C:/Users/jayrush/Desktop/lmarku/index.html";
webbrowser.open(url, new=new);
break
if(len(faces2)==0):
trials=trials+1
print("Access Denied")
#defining the interface of the captcha
#INTERFACE
root = Tk()
root.title("Face Detection CAPTCHA")
root.geometry("350x50")
bottomFrame = Frame(root)
bottomFrame.pack()
button_1 = Button(bottomFrame, fg="blue", text="I am not a robot")
button_1.bind("<Button-1>", Request_1)
button_1.pack()
status = Label(root, fg="red", text="Starting captcha...", bd=1, relief=SUNKEN, anchor=W)
status.pack(side=BOTTOM, fill=X)
root.mainloop()

Issue defining gstreamer video window on Raspbian

Using Gstreamer 'playbin' in python the 'set_window_handle' code tells Gstreamer the window id in which to render the video:
This works in standard Linux Mate and also on a Raspberry Pi 3 running Ubuntu-Mate. However, running on the same Raspberry but running an up to date Raspbian OS, Gstreamer totally ignores the instruction to run in a specific window, instead it creates its own window, smack in the middle of the screen.
This wouldn't be an issue, if the new window was capable of being manipulated, moved and/or resized but it can't. It cannot be moved, it cannot be closed and the mouse pointer vanishes behind it.
Does anyone know if this is a bug in Raspbian, X windows or Gstreamer or have I not spotted some change that has to be implemented for this to work on the Raspbian OS?
Here is a minimal, working example, which illustrates the behaviour described above.
#!/usr/bin/env python
import os,time
import wx
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gst
from gi.repository import GstVideo
class Player(wx.App):
def OnInit(self):
window = wx.Frame(None)
window.SetTitle("Gstreamer Player Test")
window.SetSize((-1,-1))
window.Bind(wx.EVT_CLOSE,self.close)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
self.fileid = wx.TextCtrl(window,style=wx.TE_PROCESS_ENTER)
self.fileid.SetToolTipString("Enter full path to media file")
hbox.Add(self.fileid, 1)
self.start = wx.Button(window,label="Start")
hbox.Add(self.start, 0)
self.start.Bind(wx.EVT_BUTTON, self.control)
self.fileid.Bind(wx.EVT_TEXT_ENTER, self.control)
vbox.Add(hbox, 0, wx.EXPAND, 0)
self.video_window = wx.Panel(window)
vbox.Add(self.video_window,1,wx.EXPAND,5)
window.SetSizer(vbox)
window.Layout()
window.Show()
self.SetTopWindow(window)
Gst.init(None) #initialise gstreamer
self.player = Gst.ElementFactory.make("playbin", "player")
bus = self.player.get_bus()
bus.add_signal_watch() #hook up bus to signals from gstreamer
bus.enable_sync_message_emission()
bus.connect('message', self.on_message)
bus.connect('sync-message::element', self.on_sync_message)
return True
def control(self, event):
if self.start.GetLabel() == "Start":
fileid = self.fileid.GetValue()
if os.path.exists(fileid):
self.start.SetLabel("Stop")
fileid = "file://"+unicode(fileid)
self.player.set_property('uri', fileid)
self.player.set_state(Gst.State.PLAYING)
else:
print "File error - No such file"
else:
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_message(self, bus, message):
t = message.type
if t == Gst.MessageType.EOS: # media has ended
self.player.set_state(Gst.State.NULL)
self.button.SetLabel("Start")
elif t == Gst.MessageType.ERROR:
print "Player error"
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_sync_message(self, bus, message):
if message.get_structure() is None:
return True
message_name = message.get_structure().get_name()
if message_name == 'prepare-window-handle': #Assign the window id to display in
imagesink = message.src
imagesink.set_property('force-aspect-ratio', True) #Force size to fit window
X_id = self.video_window.GetHandle()
print ("Window Id:", X_id)
imagesink.set_window_handle(X_id)
return True
def close(self,event):
self.player.set_state(Gst.State.NULL)
time.sleep(0.1) #Allow a little time to reach Null state
event.Skip()
app = Player()
app.MainLoop()
The answer to this is that it is a bug.
Bugzilla link
Whether it is in gstreamer or the Rpi stack seems a moot point.
The resolution is to specify the videosink in the playbin pipeline.
So for this particular program is should read as follows:
#!/usr/bin/env python
import os,time
import wx
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gst
from gi.repository import GstVideo
class Player(wx.App):
def OnInit(self):
window = wx.Frame(None)
window.SetTitle("Gstreamer Player Test")
window.SetSize((-1,-1))
window.Bind(wx.EVT_CLOSE,self.close)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
self.fileid = wx.TextCtrl(window,style=wx.TE_PROCESS_ENTER)
self.fileid.SetToolTipString("Enter full path to media file")
hbox.Add(self.fileid, 1)
self.start = wx.Button(window,label="Start")
hbox.Add(self.start, 0)
self.start.Bind(wx.EVT_BUTTON, self.control)
self.fileid.Bind(wx.EVT_TEXT_ENTER, self.control)
vbox.Add(hbox, 0, wx.EXPAND, 0)
video_window = wx.Panel(window)
vbox.Add(video_window,1,wx.EXPAND,5)
window.SetSizer(vbox)
window.Layout()
window.Show()
self.SetTopWindow(window)
Gst.init(None) #initialise gstreamer
self.X_id = video_window.GetHandle()
self.player = Gst.ElementFactory.make("playbin", "player")
# self.ximagesink = Gst.ElementFactory.make("xvimagesink", None)
self.ximagesink = Gst.ElementFactory.make("ximagesink", None)
self.player.set_property('video-sink', self.ximagesink)
bus = self.player.get_bus()
bus.add_signal_watch() #hook up bus to signals from gstreamer
bus.enable_sync_message_emission()
bus.connect('message', self.on_message)
bus.connect('sync-message::element', self.on_sync_message)
return True
def control(self, event):
if self.start.GetLabel() == "Start":
fileid = self.fileid.GetValue()
if os.path.exists(fileid):
self.start.SetLabel("Stop")
fileid = "file://"+unicode(fileid)
self.player.set_property('uri', fileid)
self.player.set_state(Gst.State.PLAYING)
else:
print "File error - No such file"
else:
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_message(self, bus, message):
t = message.type
if t == Gst.MessageType.EOS: # media has ended
self.player.set_state(Gst.State.NULL)
self.button.SetLabel("Start")
elif t == Gst.MessageType.ERROR:
print "Player error"
self.player.set_state(Gst.State.NULL)
self.start.SetLabel("Start")
def on_sync_message(self, bus, message):
if message.get_structure() is None:
return True
message_name = message.get_structure().get_name()
if message_name == 'prepare-window-handle': #Assign the window id to display in
imagesink = message.src
# imagesink.set_property('force-aspect-ratio', True) #Defaults anyway
imagesink.set_window_handle(self.X_id)
return True
def close(self,event):
self.player.set_state(Gst.State.NULL)
time.sleep(0.1) #Allow a little time to reach Null state
event.Skip()
app = Player()
app.MainLoop()
However, if you are getting the same issue using "com.sun.star.comp.avmedia.Manager_GStreamer" in a LibreOffice macro, this does you no good whatsoever, because the Libreoffice developers made the same assumption that I did and there appears to be no way to define the videosink from within Libreoffice. In this case we will simply have to wait until the bug fix makes its way into a general release.
Notes: use ximagesink
using xvimagesink gives an error on Raspbian, as the Xv software has an issue where no adaptors are available.
Using glimagesink gives us the dreaded window stuck in the middle of the screen and it seems that eglesssink has been quietly retired from service, as it is not longer included in the gstreamer plugins on the Raspberry.

python code for serial data to print on window.

I am quite new to python and pyserial. My pc was installed with python 2.7.4 with pyserial and I want to print the serially received data on a seperate window on my pc. First the window has to be opened, then after the serial data should print on that window. Here the window has to be opened once and the serial data has to be continously print on the window until the device stops tramsmitting the data.
I tried with this code, but its worthless.
please someone help me with the code.
import serial
import Tkinter
from Tkinter import *
s = serial.Serial('COM10',9600) # open serial port
master = Tk()
master.geometry("1360x750") # a window pop up with width (1360) and height(750) which exatly fits my monitor screen..
while 1:
if s.inWaiting():
text = s.readline(s.inWaiting())
frameLabel = Frame( master, padx=40, pady =40)
frameLabel.pack()
w = Text( frameLabel, wrap='word', font="TimesNewRoman 37")
w.insert(12.0,text )
w.pack()
w.configure( bg=master.cget('bg'), relief='flat', state='Normal' )
mainloop()
The problem here is that you have two loops that should be constantly running: The mainloop for the GUI and the loop for transmitting the serial data. What you can do to solve this is to start a new thread to receive the content of the serial port, put it in a Queue, and check periodically in the GUI thread the content of this queue:
import serial
import threading
import time
import Queue
import Tkinter as tk
class SerialThread(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
s = serial.Serial('/dev/ttyS0',9600)
s.write(str.encode('*00T%'))
time.sleep(0.2)
while True:
if s.inWaiting():
text = s.readline(s.inWaiting())
self.queue.put(text)
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.geometry("1360x750")
frameLabel = tk.Frame(self, padx=40, pady =40)
self.text = tk.Text(frameLabel, wrap='word', font='TimesNewRoman 37',
bg=self.cget('bg'), relief='flat')
frameLabel.pack()
self.text.pack()
self.queue = Queue.Queue()
thread = SerialThread(self.queue)
thread.start()
self.process_serial()
def process_serial(self):
value=True
while self.queue.qsize():
try:
new=self.queue.get()
if value:
self.text.delete(1.0, 'end')
value=False
self.text.insert('end',new)
except Queue.Empty:
pass
self.after(100, self.process_serial)
app = App()
app.mainloop()
This code is tested with my Pi3 ttyS0 serial port and serially connected PC and slave device:
its 100% working with single device connected serially