嘿,我写了一个 Python 脚本,通过 UDP 将网络摄像头流式传输到其他设备。 但是当我启动流时,只显示图像的前几行。 即使我使用相同的变量将文件写入磁盘并显示它,我也会得到不同的结果。因为在保存的图像中,颜色是正常的,但在实时图片中,颜色(我认为)是反转的。 我已经尝试过的:
服务器代码:
import numpy as np
from cv2 import cv2
import socket,json
MESSAGE = [0,0,0]
cap = cv2.VideoCapture(0)
a = 0
class NumpyEncoder(json.JSONEncoder):
def default(self,obj):
if isinstance(obj,np.ndarray):
return obj.tolist()
return json.JSONEncoder.default(self,obj)
while(True):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame',frame)
cv2.imwrite("test.jpg",frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
UDP_IP = "192.168.1.147"
UDP_PORT = 5005
MESSAGE = json.dumps({"a" : frame[0], "b" : frame[1],"c" : frame[2]}, cls = NumpyEncoder)
with open("test.txt","w") as f:
f.write(MESSAGE)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 16384)
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE.encode(),(UDP_IP,UDP_PORT))
# When everything done, release the capture
cap.release()
客户:
import socket,json
from cv2 import cv2
import numpy as np
framecounter = 0
class NumpyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.ndarray):
return obj.tolist()
return json.JSONEncoder.default(self, obj)
UDP_IP = "192.168.1.147"
UDP_PORT = 5005
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
while True:
json_dump, addr = sock.recvfrom(65535)
json_load = json.loads(json_dump.decode())
new_rgb = np.asarray(json_load["a"]),np.asarray(json_load["b"]),np.asarray(json_load["c"])
new_rgb = np.float32(new_rgb)
cv2.imwrite("test.jpg",new_rgb)
cv2.imshow("frame",new_rgb)
cv2.resizeWindow("frame",(640,480))
framecounter = framecounter + 1
print("frame",framecounter)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
答案 0 :(得分:0)
从 cap.read() 返回的帧值只是流中的一个图像,它是一个大小矩阵(高度、宽度、通道),因此当您执行 frame[0] 时,您只会得到第一个这个矩阵的行。 其次,您的编码效率低下,如果您想一次发送一个图像(帧),您可以将图像文件转储到套接字中。
这是我的实现,请注意,由于接收器是单线程的,如果它开始执行缓慢的操作(例如写入磁盘、计算机视觉),它可能会丢失多个数据包。在这种情况下,您应该创建另一个线程,该线程仅侦听该端口并写入队列。
接收.py
import socket
import cv2
import io
import numpy as np
import traceback
DATAGRAM_SIZE = 1400 #bytes
PORT = 44000
end_bytes = bytes(17)
framecounter = 0
listening_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
listening_socket.bind(('', PORT))
while True:
image_buffer = io.BytesIO() # faster than writing to file
data, address = listening_socket.recvfrom(DATAGRAM_SIZE)
while data != end_bytes:
image_buffer.write(data)
data, address = listening_socket.recvfrom(DATAGRAM_SIZE)
image_buffer.seek(0)
try: # image may be corrupted by loss of UDP packets
img = cv2.imdecode(np.asarray(bytearray(image_buffer.read()), dtype=np.uint8), cv2.IMREAD_COLOR)
cv2.imshow("received", img) # If the code gets slow here you may loose packets
except Exception:
traceback.print_exc()
framecounter += 1
print(framecounter)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
listening_socket.close()
sender.py
import socket
import cv2
import numpy
import time
DATAGRAM_SIZE = 1400
PORT = 44000
IP = "127.0.0.1"
end_bytes = bytes(17)
cap = cv2.VideoCapture(0)
sending_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while(True):
ret, frame = cap.read()
cv2.imshow("sent",frame)
cv2.imwrite("img_to_send.jpg",frame) # You may use BytesIO
if cv2.waitKey(1) & 0xFF == ord('q'):
break
with open("img_to_send.jpg", "rb") as f:
data = f.read(DATAGRAM_SIZE)
while data:
sending_socket.sendto(data, (IP, PORT))
data = f.read(DATAGRAM_SIZE)
sending_socket.sendto(end_bytes, (IP, PORT))
sending_socket.close()
cap.release()