簡體   English   中英

如何使用套接字、pickle 和 OpenCV 使用 Python 流式傳輸網絡攝像頭?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM