python - cv2 网络摄像头流仅显示前几行图像
问题描述
嘿,所以我编写了一个 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
解决方案
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()
发件人.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()
推荐阅读
- mqtt - Mosquitto MQTT 设置下行
- javascript - 用户重新加载页面时打开最后一个活动选项卡
- docker - 使用 docker 在远程的 pycharm 中配置解释器
- reactjs - 当仅参数更改但更改浏览器中的 url 时,History.push 不会重定向
- office-addins - Outlook 加载项 - 检测是否在 Outlook for Mac“新外观”中运行?
- react-native - React Native expo-location:如何让后台位置服务更新更频繁?
- c# - 无法命中包含泛型类型的 API 端点
- c++ - 在链接列表中打印最大值时输出错误
- c - 我需要使用 C 语言中 Vernam Cipher 的变体来加密文件。你能检查我的代码吗?
- eigenvector - 为什么对称矩阵的特征向量是离散的 2x2 而不是 3x3