I've been working hours to send video frames through a UDP socket and this is what I've done so far:
Client side: sends the captured video and then receives it and rebuilds the frame and displays it on tkinter
import socket
from tkinter import *
from PIL import ImageTk, Image
import cv2
import numpy
import threading
IP = "127.0.0.1"
PORT = 8080
my_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
my_socket.connect((IP, PORT))
root = Tk()
main_label = Label(root)
main_label.grid()
cap = cv2.VideoCapture("video.mp4")
LEN = 61440
DIV = 60
def send_msg(frame):
for i in range(DIV):
my_socket.sendto(frame[i*LEN:(i+1)*LEN], (IP, PORT))
def receive_msg():
while True:
data = b""
while len(data) != (LEN * DIV):
msg, add = my_socket.recvfrom(LEN)
data += msg
create_frame(data)
def create_frame(data):
numpy_img = numpy.frombuffer(data, dtype=numpy.uint8)
numpy_img = numpy_img.reshape(720, 1280, 4)
img = Image.fromarray(numpy_img)
tk_img = ImageTk.PhotoImage(image=img)
main_label.configure(image=tk_img)
main_label.tk_img = tk_img
def video_stream():
ret, frame = cap.read()
colored_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
bytes_frame = colored_frame.tobytes()
send_msg(bytes_frame)
main_label.after(50, video_stream)
def main():
t = threading.Thread(target=receive_msg)
t.start()
video_stream()
root.mainloop()
if __name__ == '__main__':
main()
Server side: sends everything it receives
import socket
IP = "0.0.0.0"
PORT = 8080
LEN = 61440
def main():
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
server_socket.bind((IP, PORT))
while True:
msg, add = server_socket.recvfrom(LEN)
server_socket.sendto(msg, add)
if __name__ == '__main__':
main()
the problem is that the video is displayed not like the regular video:
Regular:
Result:
as you can see, the parts of the frame itself are messy and I don't really know a possible way to fix it...
Related
i am making a GUI application, the problem that i had is that i dont know how to access the object created by .accept(), i had seen a lot of tutorials but all of them do like console application, so i need to create in some how the socket object, i open the connection with a push button and other process send the data
from email import message
from fileinput import filename
from operator import truediv
import sys
from tkinter.tix import Tree
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow
import tkinter
import tkinter.filedialog
import socket
import threading as th
from time import sleep
from tkinter import messagebox
from GUI import Ui_MainWindow, Ui_MainWindow
from tkinter import filedialog
from tkinter import *
TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024
MESSAGE = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def Stream():
while True:
while main_win.Transmit:
f = open(main_win.filename, "r")
x = len(f.readlines())
while x>=main_win.Lastline:
data=(f.readline(main_win.Lastline+1))
main_win.Lastline=main_win.Lastline+1
conn.send(data) #out of scope
f.close()
sleep(main_win.ui.doubleSpinBox.value())
T = th.Timer(0.10, Stream,args=(''))
class MainWindow:
Transmit = False
Lastline=0
filename=""
Started=False
Connected=False
def __init__(self):
self.main_win = QMainWindow()
self.ui = Ui_MainWindow()
self.ui.setupUi(self.main_win)
self.ui.pushButton.clicked.connect(self.on_pushButton_clicked)
self.ui.pushButton_2.clicked.connect(self.transmit_clicked)
self.ui.pushButton_4.clicked.connect(self.OpenConn)
def show(self):
self.main_win.show()
def on_pushButton_clicked(self):
filename = filedialog.askopenfilename(
initialdir="/", title="Select file", filetypes=(("txt files", "*.txt"), ("all files", "*.*")))
print(filename)
self.ui.lineEdit.setText(filename)
def transmit_clicked(self):
if not self.Connected:
messagebox.showerror('Error', 'Error: No hay una conexion establecida')
return
if self.filename == "":
messagebox.showerror('Error', 'Error: No ha seleccionado el archivo')
return
if (not self.Transmit):
self.Transmit = True
self.ui.pushButton_2.setText("Detener Streaming de datos")
# iniciar transmicion de datos
print(T.interval)
if (not self.Started):
T.start()
self.Started=True
else:
self.Transmit = False
self.ui.pushButton_2.setText("Iniciar Streaming de datos")
def OpenConn(self):
conn, addr = s.accept()
self.Connected=True
if __name__ == '__main__':
app = QApplication(sys.argv)
main_win = MainWindow()
main_win.show()
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
#s.setblocking(0)
#conn, addr = s.accept()
sys.exit(app.exec_())
i solved this by my self, it was more simple than i thougt i just needed to delcare two globals objects and done
class MainWindow:
conn=socket.AF_INET
addr=socket.SOCK_STREAM
We are trying to use an ethernet communication model on the raspberry Pi that receives data from an Arduino in an infinite while loop. The response of the communication is then displayed onto the GUI which is running in parallel.
The flags are being received by the Pi but the gui does not display the required images.
from tkinter import *
from PIL import ImageTk,Image
from socket import *
import select
import numpy as np
from threading import Thread
from time import sleep
global data
data = None
timeout = 3 # timeout in seconds
msg = "test"
host = "192.168.1.101"
print ("Connecting to " + host)
port = 5000
s = socket(AF_INET, SOCK_STREAM)
print ("Socket made")
ready = select.select([s],[],[],timeout)
s.connect((host,port))
print("Connection made")
def func2():
while True:
data = s.recv(4096)
print("Data received")
print (data)
if __name__ == '__main__':
Thread(target = func2).start()
w=Tk()
w.geometry('1700x900')
w.configure(bg='#ffffff')
w.resizable(True,True)
w.title('SensorNode User Interface')
imagegreen = ImageTk.PhotoImage(Image.open("green.png"))
imagered = ImageTk.PhotoImage(Image.open("red.png"))
def func1():
while True:
if (data == 0):
Button(w,
image=imagered,
border=0,
bg='#ffffff',
activebackground='#ffffff').place(x=630,y=460)
sleep(0.1)
if (data == 1):
Button(w,
image=imagegreen,
border=0,
bg='#ffffff',
activebackground='#ffffff').place(x=630,y=460)
sleep(0.1)
if __name__ == '__main__':
Thread(target = func1).start()
w.mainloop()
I went through this beautifully explained Q/A and I want something similar into a much stripped down version of the code I found there which includes PyQt4 and qdarkstyle.
My code is as follows:
import pafy
import base64
import zmq
from threading import Thread
import cv2
import time
class IPCamera(object):
def __init__(self, src=0):
self.frame = None
self.status = None
self.capture = cv2.VideoCapture(src)
self.capture.set(cv2.CAP_PROP_BUFFERSIZE, 2)
self.FPS = 1/25
self.FPS_MS = int(self.FPS * 1000)
# Start frame retrieval thread
self.thread = Thread(target=self.update, args=())
self.thread.daemon = True
self.thread.start()
def update(self):
while True:
if self.capture.isOpened():
(self.status, self.frame) = self.capture.read()
# self.frame = cv2.resize(self.frame, (640, 480)) # resize the frame
time.sleep(self.FPS)
def show_frame(self):
cv2.imshow('frame', self.frame)
cv2.waitKey(self.FPS_MS)
if __name__ == '__main__':
# Sample youtube video starts
youtube_link = 'https://www.youtube.com/watch?v=QgaUKlAuqn8'
vPafy = pafy.new(youtube_link)
play = vPafy.getbest(preftype="mp4")
src = play.url
# Sample youtube video ends
# Creating ZMQ context starts
context = zmq.Context()
footage_socket = context.socket(zmq.PUB)
footage_socket.connect('tcp://localhost:5555')
# cv2.namedWindow("Client Started!")
# Creating ZMQ context ends
threaded_camera = IPCamera(src)
while threaded_camera.capture.isOpened():
try:
if threaded_camera.status is True:
encoded, buffer = cv2.imencode('.jpg', threaded_camera.frame)
jpg_as_text = base64.b64encode(buffer)
footage_socket.send(jpg_as_text)
# key = cv2.waitKey(1)
# threaded_camera.show_frame()
# if key == 27: # exit on ESC
# break
# else:
# break
except AttributeError:
pass
The above code is running fine, I want to implement the code from the Q/A on the aforementioned link with those libraries removed. Can you help me in that?
I am using PyQt5 and Qml to create a client application. This is a simplified sample of my Qml file:
import QtQuick 2.11
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
ApplicationWindow {
visible: true
width: Screen.width/2
height: Screen.height/2
Rectangle {
id: rectangle
x: 187
y: 92
width: 200
height: 200
color: "blue"
}
}
The client app must receive the properties of the above rectangle from the server. In order to do that, I implemented a socket connection in the ".py" file. the client.py file ought to receive information in real-time from the server. I was inspired by chat application programs and I used a (while True:{}) loop to do this:
from PyQt5.QtQml import QQmlApplicationEngine, QQmlProperty
from PyQt5.QtQuick import QQuickWindow, QQuickView
from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtWidgets import QApplication
import sys, socket
def run():
myApp = QApplication(sys.argv)
myEngine = QQmlApplicationEngine()
myEngine.load('mainViewofHoomanApp.qml')
Win = myEngine.rootObjects()[0]
rect = Win.findChild(QObject, "rectangle")
rect.setProperty("height", 10) # Here I am accessing the properties of the rectangle
if not myEngine.rootObjects():
return -1
return myApp.exec_()
if __name__ == "__main__":
sys.exit(run())
And it is the format of socket connection:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Server_IPAddress = '192.168.1.163'
Port = 5000
client_socket.connect((Server_IPAddress,Port))
while True:
message = client_socket.recv(1024)
# Then the code extracts the parameters from the message
# and converts it to integer, and saves it in realT_width variable:
rect.setProperty("height", realT_width variable)
I am confused about how to merge these two codes together. If I call the socket connection after write the myApp.exec_() command, then the QML file will no longer react to the parameter change commands. On the other hand, if I write the socket connection before the QML execution, then the while loop will not allow the latter code lines to be executed.
The blocking tasks must be executed in another thread so that they do not freeze the GUI, in this case I will assume that the next one is the server so you must launch it first.
server.py
import socket
import time
import random
HOST = '127.0.0.1'
PORT = 65432
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
v = random.randint(10, 100)
conn.sendall(str(v).encode())
time.sleep(1.)
So I will create a QObject where I can create the signals that will send the information obtained by the socket that runs on a secondary thread to the handler that I publish in my other answer.
client.py
import os
import sys
import threading
import socket
from PyQt5 import QtCore, QtGui, QtQml
from functools import partial
class SocketWorker(QtCore.QObject):
heightChanged = QtCore.pyqtSignal(float)
#QtCore.pyqtSlot()
def process(self):
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 65432 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
while True:
data = s.recv(1024)
print('Received', repr(data))
try:
height = float(data)
self.heightChanged.emit(height)
except ValueError:
print("error")
class RectangleManager(QtCore.QObject):
widthChanged = QtCore.pyqtSignal(float)
heightChanged = QtCore.pyqtSignal(float)
def __init__(self, parent=None):
super(RectangleManager, self).__init__(parent)
self._width = 100
self._height = 100
def getWidth(self):
return self._width
def setWidth(self, w):
if self._width != w:
self._width = w
self.widthChanged.emit(w)
def getHeight(self):
return self._height
def setHeight(self, h):
if self._height != h:
self._height = h
self.heightChanged.emit(h)
width = QtCore.pyqtProperty(float, fget=getWidth, fset=setWidth, notify=widthChanged)
height = QtCore.pyqtProperty(float, fget=getHeight, fset=setHeight, notify=heightChanged)
def run():
myApp = QtGui.QGuiApplication(sys.argv)
myEngine = QtQml.QQmlApplicationEngine()
manager = RectangleManager()
myEngine.rootContext().setContextProperty("r_manager", manager)
directory = os.path.dirname(os.path.abspath(__file__))
myEngine.load(QtCore.QUrl.fromLocalFile(os.path.join(directory, 'main.qml')))
if not myEngine.rootObjects():
return -1
worker = SocketWorker()
threading.Thread(target=worker.process, daemon=True).start()
worker.heightChanged.connect(manager.setHeight)
return myApp.exec_()
if __name__ == "__main__":
sys.exit(run())
main.qml
import QtQuick 2.11
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
ApplicationWindow {
visible: true
width: Screen.width/2
height: Screen.height/2
Rectangle {
id: rectangle
x: 187
y: 92
width: r_manager.width
height: r_manager.height
color: "blue"
}
}
Lately I have been working on my python chat project, the server works well but when I use the threading model to run the gui of the client and the select I have a problem with it.
I am able to send data to the server and the server returns the data to the clients but the clients can't print the data.
This is the code of the client :
import socket
import select
from Tkinter import *
import thread
class client(object):
def __init__(self):
self.client_socket = socket.socket()
self.messages =[]
def connect(self):
self.client_socket.connect(('127.0.0.1', 1234))
def getgui(self, window):
self.root = window
def run(self):
while True:
self.rlist, self.wlist, self.xlist = select.select([self.client_socket], [self.client_socket], [])
for current_socket in self.rlist:
data = current_socket.recv(1024)
self.root.print_on_list(data)
def send_to_server(self, word):
self.client_socket.send(word)
class rootgui():
def __init__(self,client_socket):
self.client_socket = client_socket
self.root = Tk()
self.root.geometry('600x700')
self.root.minsize(600, 700)
self.root.maxsize(600, 700)
self.root.title('chat')
self.frame = Frame(self.root)
self.frame.pack()
self.scrollbar = Scrollbar(self.frame)
self.scrollbar.pack(side = RIGHT, fill = Y)
self.chatlist = Listbox(self.frame, yscrollcommand = self.scrollbar.set, width = 80, height = 25 )
self.chatlist.pack(side = LEFT)
self.leftframe = Frame(self.root)
self.leftframe.pack(side = LEFT)
self.send_button = Button(self.leftframe, text = 'send', bg = 'green', padx = 60, pady = 70, command = self.send)
self.send_button.pack()
self.rightframe = Frame(self.root)
self.rightframe.pack(side = RIGHT)
self.text = StringVar()
self.input_box = Entry(self.rightframe, width =55, textvariable = self.text )
self.input_box.pack()
self.scrollbar.config(command = self.chatlist.yview)
def mainloop(self):
self.root.mainloop()
def send(self):
t = self.text.get()
self.client_socket.send_to_server(t)
return
def print_on_list(self, data):
self.chatlist.insert(END, data+'\r\n')
def main():
client_socket = client()
client_socket.connect()
window = rootgui(client_socket)
client_socket.getgui(window)
thread.start_new_thread(window.mainloop())
thread.start_new_thread(client_socket.run())
if __name__ == '__main__':
main()
This is the code of the server:
import socket
import select
class server(object):
''' init function '''
def __init__(self):
self.server_socket = socket.socket()
self.open_client_sockets = []
'''this function send a message to all of the connected clients'''
def send_messages(self, message):
for client_socket in self.open_client_sockets:
client_socket.send(message)
''' this function get a port , it bind the server socket and set the listen to 5 sockets '''
def connection(self):
self.server_socket.bind(('0.0.0.0', 1234))
self.server_socket.listen(5)
''' this function use the select library and read / write from / to the client socket '''
def run(self):
while True:
self.rlist, self.wlist, self.xlist = select.select([self.server_socket]+self.open_client_sockets, self.open_client_sockets, [])
for current_socket in self.rlist:
if current_socket is self.server_socket:
(new_socket, address) = self.server_socket.accept()
self.open_client_sockets.append(new_socket)
print 'new member : ' + str(address)
else:
try:
data = current_socket.recv(1024)
self.send_messages(data)
break
except socket.error:
self.open_client_sockets.remove(current_socket)
print 'Connection with client closed.'
if __name__ == '__main__':
server_socket = server()
server_socket.connection()
server_socket.run()