[英]How to stream a webcam with Python using socket, pickle, and OpenCV?
在 Python 中,我需要流式傳輸用戶的網絡攝像頭,但在接收數據時遇到問題。 我使用 pickle 發送一個名為 data 的列表,其中包含發件人的身份、數據類型(消息、命令和圖像)和數據本身。 問題是,當我發送帶有pickle 的圖像時,會發生錯誤。
服務器代碼:
import socket
import threading
import pickle
class Server:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
connections = []
def __init__(self):
self.sock.bind(('127.0.0.1', 1234))
self.sock.listen(5)
print("Server created")
def handler(self, c, a):
while True:
try:
raw_data = c.recv(1024)
except ConnectionResetError:
print("Error")
print(str(a[0]) + ':' + str(a[1]), "disconnected roughly")
self.connections.remove(c)
c.close()
break
except:
print("Error while recieving data")
continue
for connection in self.connections:
if connection != c:
connection.sendall(raw_data)
if not raw_data:
print(str(a[0]) + ':' + str(a[1]), "disconnected")
self.connections.remove(c)
c.close()
break
def run(self):
print("Server is running")
while True:
try:
c, a = self.sock.accept()
print(str(a[0]) + ':' + str(a[1]), "connected")
except:
print("Error during client connection")
continue
cThread = threading.Thread(target=self.handler, args=(c, a), name="HandlerTh")
cThread.daemon = True
cThread.start()
self.connections.append(c)
def main():
server = Server()
server.run()
if __name__ == '__main__':
while True:
main()
發送網絡攝像頭流的客戶端:
## Import modules
import socket
import threading
import pickle
import cv2, numpy as np
## CLIENT CLASS INITIALISATION ##
class Client:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
count = 0
keys = []
def __init__(self,server_ip = '127.0.0.1' ,server_port = 1234):
self.sock.connect((server_ip, server_port))
promptThread = threading.Thread(target=self.prompt, name="bPrompt")
promptThread.daemon = True
promptThread.start()
self.KL_STATE = 0
self.EYE_STATE = 0
while True:
raw_data = self.sock.recv(4096)
data = pickle.loads(raw_data)
# data[0] = ID
# data[1] = DATA_TYPE
# data[2] = CMD_DATA
if data[1] == "command":
self.execute_command(data[2])
elif not data:
break
print(data)
## DATA TREATMENT ##
def send_data(self,data_type,data):
raw_data = ["vb",data_type,data]
data_p = pickle.dumps(raw_data)
self.sock.sendall(data_p)
def execute_command(self,command):
if command == "Eye-start":
eyeThread = threading.Thread(target=self.eye, name="EyeTh")
self.EYE_STATE = 1
eyeThread.start()
elif command == "Eye-stop":
self.stopTool("Eye")
else:
print("unknown command")
self.send_data("log_msg","unknown command")
def prompt(self):
while True:
command = input("client@v >")
self.send_data("command",command)
## KIT ##
def stopTool(self,tool):
if tool == "Eye-stop":
self.EYE_STATE = 0
else:
msg = f"{tool} dont exist"
print(msg)
self.send_data("stopTool-log",msg)
## 2nd tool : eye
def eye(self):
video = cv2.VideoCapture(0)
while self.EYE_STATE == 1:
check, frame = video.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
self.send_data("eye",gray)
if self.EYE_STATE == 0:
break
cv2.destroyAllWindows
video.release()
## MAIN PROGRAM ##
def main ():
client = Client()
if __name__ == '__main__':
while True:
main()
然后是發送命令的客戶端:
import socket
import threading
import pickle
import datetime
import cv2, numpy as np
TIME = datetime.datetime.now()
TIME = TIME.strftime("%m/%d/%Y, %H:%M:%S")
class Client:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def __init__(self):
self.sock.connect(('127.0.0.1', 1234))
iThread = threading.Thread(target=self.prompt, name="aPromptTh")
iThread.daemon = True
iThread.start()
while True:
raw_data = self.sock.recv(4096)
data = pickle.loads(raw_data)
# print(data)
if data[1] == "eye":
cv2.imshow("Window name",data[2])
else:
print(data)
if not data:
break
def prompt(self):
while True:
command = input("client@a >")
raw_data = ["a","command",command]
self.send_data(raw_data)
def send_data(self,data):
# while True:
data = pickle.dumps(data)
self.sock.sendall(data)
client = Client()
我收到此錯誤:
Traceback (most recent call last):
File "C:\Users\**\**.py", line **, in <module>
client = Client()
File "C:\Users\**\**.py", line **, in __init__
data = pickle.loads(raw_data)
_pickle.UnpicklingError: pickle data was truncated
基本上這里發生的事情是,當您發送圖像文件時,它必須分解成數據包,並且您的圖像太大而無法放入 1 個數據包。 因此,圖像以多個數據包發送。
您的程序嘗試僅接收第一個數據包,該數據包不包含完整的腌制圖像,然后對其進行取消腌制,這會引發錯誤。
相反,請嘗試以下操作:
while True:
raw_data = b""
while True:
packet = s.recv(4096)
if not packet:
break
raw_data += packet
data = pickle.loads(raw_data)
if data[1] == "eye":
cv2.imshow("Window name",data[2])
else:
print(data)
if not data:
break
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.