【问题标题】:python video streaming in tkintertkinter中的python视频流
【发布时间】:2021-04-14 13:03:37
【问题描述】:

我正在尝试将视频帧部分发送到服务器,然后使用线程、tkinter 和 opencv 使用 UDP 套接字在客户端(一种视频流)中再次构建它,但我不明白我的错误/error,真的不知道我划分视频部分的方式是否正确。

服务器:

import socket


IP = "0.0.0.0"
PORT = 8080
LEN = 12000


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()

客户:

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 = 12000


def send_msg(frame):
    for i in range(0, len(frame), LEN):
        data = frame[i:i+LEN]
        if len(data) == LEN:
            my_socket.sendto(data, (IP, PORT))
        else:
            my_socket.sendto(data + b"done", (IP, PORT))


def recv_msg():
    while True:
        data = b""
        msg, add = my_socket.recvfrom(LEN)
        while b"done" not in msg:
            data += msg
            msg, add = my_socket.recvfrom(LEN)
        data += msg.split(b"done")[0]
        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()
    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
    bytes_img = cv2image.tobytes()
    send_msg(bytes_img)
    main_label.after(50, video_stream)


def main():
    video_stream()
    t1 = threading.Thread(target=recv_msg)
    t1.start()
    root.mainloop()


if __name__ == '__main__':
    main()

错误:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Users\eitan\Anaconda3\lib\threading.py", line 917, in _bootstrap_inner
    self.run()
  File "C:\Users\eitan\Anaconda3\lib\threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "E:/Chat/ex_client.py", line 38, in recv_msg
    numpy_img = numpy_img.reshape((720, 1280, 4))
ValueError: cannot reshape array of size 3182400 into shape (720,1280,4)

非常感谢帮助! 非常感谢!

【问题讨论】:

    标签: python opencv tkinter


    【解决方案1】:

    在错误消息中,大小匹配 1105x720x4(不是 1280x720x4)。

    如果您将其设置为该分辨率,它会起作用吗?

    numpy_img = numpy_img.reshape((720, 1105, 4))
    img = Image.fromarray(numpy_img)
    

    另外,您能否进行测试运行,它不会形成图像等,而只是打印接收到的图像、数据的大小等,看看是否一致(例如,相机实际以该分辨率捕获?或者是因为相机窗口的某些默认大小?-我不知道)。

    data = b""
    data += msg.split(b"done")[0]
    

    那效率不高,我认为您最好使用具有预期大小的 numpy 数组,并像拆分帧一样使用切片:[i:i+LEN] 等。

    另外,最好先握手了解分辨率和格式(我猜你已经意识到了,不压缩发送它,因为即使对于 LAN 来说这也是一种矫枉过正)。

    您可以尝试使用不同的数据包大小 (LEN=12000) 以查看错误是否相同:

     LEN=...
     msg, add = my_socket.recvfrom(LEN)
    

    【讨论】:

    • 你好!首先,我真的很感谢你的帮助!其次,可悲的是,它仍然打印出相同的错误,但大小不同:“无法将大小为 3216400 的数组重塑为形状 (720,1105,4)”。如果我理解正确,说“握手”,你的意思是我应该先发送帧的大小,然后开始分部分发送帧吗?
    • 握手 - 是的,某种初始交互,一种协议。您还必须检查这是否是正确的分辨率,错误消息报告它不是您设置的分辨率。如果您希望 1280x720x4,即 3686400 字节,您的代码不会发送或接收正确数量的数据,或者源图像不是 1280x720(您检查了吗?cv2.imshow("Frame", frame),以及更好的 cv2 .imwrite("frame.jpg", frame) - 查看其分辨率)或传输中的其他内容。您是否也尝试过其他建议?
    • 另外,您可以扩展接收数据的大小以适应该大小 3686400,例如创建一个空数组并在开始时复制收到的数组(其余的将是黑色的),然后重新整形并查看输出并发布它。是否带有一些垃圾边框,不同步等(顺便说一句,如果您发现对您的问题有用的答案/评论,您可以标记它。)
    • 嗨!我真的不明白你的意思。您是否有机会尝试修复代码?如果没有,那就太好了!
    • 不要尝试将不足的数据调整到固定的分辨率,注释在接收端创建图像的代码,并仅记录/打印接收数据的大小(打印(data.shape) ),在 cv2image = .... 之后打印 h, w, c = frame.shape 并打印 w * h * c 并在此处显示输出 - 值是否重复?您的图像分辨率错误。一种创建具有 4 个通道的空图像的方法:numpy_img = np.zeros((h, w, 4), h = height, w = width。还可以查看 numpy 切片/numpy 数组和使用 python 的基本 opencv 教程。
    猜你喜欢
    • 2023-01-07
    • 2018-11-28
    • 2020-04-29
    • 2019-12-10
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 2019-05-02
    相关资源
    最近更新 更多