我正在尝试创建一个简单的应用程序,通过OpenCV在Python 3中通过套接字发送实时流视频。我是OpenCV和socket编程的新手,所以如果你能详细提供答案,我将非常感激。谢谢。
这是sender.py
import socket
import time
import cv2
capture = cv2.VideoCapture(0)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('192.168.1.10', 50505))
while True:
ret, frame = capture.read()
data = cv2.imencode('.jpg', frame)[1].tostring()
sock.sendall(data)
time.sleep(2)
这是receiver.py
import socket
import cv2
import numpy as np
import time
HOST = '192.168.1.10'
PORT = 50505
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Socket created')
s.bind((HOST, PORT))
print('Socket bind complete')
s.listen(10)
print('Socket now listening')
conn, addr = s.accept()
while True:
data = conn.recv(8192)
nparr = np.fromstring(data, np.uint8)
frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
cv2.imshow('frame', frame)
time.sleep(2)
这是错误
receiver.py", line 29, in <module>
cv2.imshow('frame', frame)
cv2.error: D:\Build\OpenCV\opencv-3.4.0\modules\highgui\src\window.cpp:339:
error: (-215) size.width>0 && size.height>0 in function cv::imshow
答案 0 :(得分:1)
这是因为您收到少量数据,而且图像不完整。在99.99%的时间内,8192个字节是不够的,因为每个图像都大于8Kb。您需要获取发件人发送的所有数据,以便将其转换为图像。
您可以在github上查看我的代码,并根据您的需要进行更改。
长话短说,简单的选择是首先向客户端发送字节数,然后自己发送图像。在客户端代码中,在接收到图像长度后,循环直到接收到所有字节。 例如:
...
img_len = 175428 # received by sender.py
e=0
data = ''
while e < img_len:
d = sock.recv(1024)
e += len(d)
data += d
nparr = np.fromstring(data, np.uint8)
frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
cv2.imshow('frame', frame)
答案 1 :(得分:0)
我是功能强大的VidGear视频处理python库的作者,该库现在还提供NetGear API,该库专门用于在网络上的互连系统之间实时实时传输视频帧。您可以如下尝试:
打开您喜欢的终端并执行以下python代码:
注意: 您可以通过在服务器端按键盘上的[Ctrl + c]来随时在服务器和客户端上结束流式传输!
# import libraries
from vidgear.gears import VideoGear
from vidgear.gears import NetGear
stream = VideoGear(source='test.mp4').start() #Open any video stream
server = NetGear() #Define netgear server with default settings
# infinite loop until [Ctrl+C] is pressed
while True:
try:
frame = stream.read()
# read frames
# check if frame is None
if frame is None:
#if True break the infinite loop
break
# do something with frame here
# send frame to server
server.send(frame)
except KeyboardInterrupt:
#break the infinite loop
break
# safely close video stream
stream.stop()
# safely close server
writer.close()
然后在同一系统上打开另一个终端,并执行以下python代码并查看输出:
# import libraries
from vidgear.gears import NetGear
import cv2
#define netgear client with `receive_mode = True` and default settings
client = NetGear(receive_mode = True)
# infinite loop
while True:
# receive frames from network
frame = client.recv()
# check if frame is None
if frame is None:
#if True break the infinite loop
break
# do something with frame here
# Show output window
cv2.imshow("Output Frame", frame)
key = cv2.waitKey(1) & 0xFF
# check for 'q' key-press
if key == ord("q"):
#if 'q' key-pressed break out
break
# close output window
cv2.destroyAllWindows()
# safely close client
client.close()
NetGear截至目前支持两种ZeroMQ消息传递模式:即zmq.PAIR
和zmq.REQ and zmq.REP
,支持的协议为:'tcp', 'upd', 'pgm', 'inproc', 'ipc'
可以在此处找到更多高级用法: https://github.com/abhiTronix/vidgear/wiki/NetGear
答案 2 :(得分:0)
最新答案,但是对于那些希望通过套接字传输实时视频的人: 这是结果的快照:
import socket, cv2, pickle,struct
# Socket Create
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host_name = socket.gethostname()
host_ip = socket.gethostbyname(host_name)
print('HOST IP:',host_ip)
port = 9999
socket_address = (host_ip,port)
# Socket Bind
server_socket.bind(socket_address)
# Socket Listen
server_socket.listen(5)
print("LISTENING AT:",socket_address)
# Socket Accept
while True:
client_socket,addr = server_socket.accept()
print('GOT CONNECTION FROM:',addr)
if client_socket:
vid = cv2.VideoCapture(0)
while(vid.isOpened()):
img,frame = vid.read()
a = pickle.dumps(frame)
message = struct.pack("Q",len(a))+a
client_socket.sendall(message)
cv2.imshow('TRANSMITTING VIDEO',frame)
key = cv2.waitKey(1) & 0xFF
if key ==ord('q'):
client_socket.close()
import socket,cv2, pickle,struct
# create socket
client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host_ip = '192.168.1.20' # paste your server ip address here
port = 9999
client_socket.connect((host_ip,port)) # a tuple
data = b""
payload_size = struct.calcsize("Q")
while True:
while len(data) < payload_size:
packet = client_socket.recv(4*1024) # 4K
if not packet: break
data+=packet
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("Q",packed_msg_size)[0]
while len(data) < msg_size:
data += client_socket.recv(4*1024)
frame_data = data[:msg_size]
data = data[msg_size:]
frame = pickle.loads(frame_data)
cv2.imshow("RECEIVING VIDEO",frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
client_socket.close()