问题
I am developing a wx application in python for streaming and displaying video from two different webcams. This works fine, but now I need to do this in a different scenario in which the two cameras are connected in separate machine running on Windows connected over a network. My application will run on machine 1. The video from the camera 1 can be fetched using opencv and display on a panel. And also I want to fetch video from camera 2 connected to machine 2, and display it in the application.
Is there any way to do this?
回答1:
VLC can stream the image of a capture device's over RTSP, see the "Streaming using the GUI" chapter of VLC's "Streaming HowTo".
Then OpenCV's VideoCapture
can grab frames from RTSP stream such as:
std::string address = "rtsp://<username:password>@<ip_address>:<port>";
cv::VideoCapture cap;
if(!cap.open(address))
{
std::cout << "Error opening video stream: " << address << std::endl;
return -1;
}
Where address
is something like rtsp://127.0.0.1:554
or rtsp://username:password@127.0.0.1:554
if it is password protected.
回答2:
I have used websockets to stream data between the two machines. You grab the image in machine 1 and stream it to machine 2 which is listening for connections on a certain port.
Machine 1 (client):
cap=cv2.VideoCapture(0)
clientsocket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
clientsocket.connect(('localhost',8089))
while(cap.isOpened()):
ret,frame=cap.read()
memfile = StringIO.StringIO()
np.save(memfile, frame)
memfile.seek(0)
data = json.dumps(memfile.read().decode('latin-1'))
clientsocket.sendall(struct.pack("L", len(data))+data)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
Machine 2 (server thread):
self.isRunning = True
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
s.bind((self.hostname, self.port))
print 'Socket bind complete'
data = ""
payload_size = struct.calcsize("L")
s.listen(10)
print 'Socket now listening'
while self.isRunning:
conn, addr = s.accept()
while True:
data = conn.recv(4096)
if data:
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("L", packed_msg_size)[0]
while len(data) < msg_size:
data += conn.recv(10000)
frame_data = data[:msg_size]
memfile = StringIO.StringIO()
memfile.write(json.loads(frame_data).encode('latin-1'))
memfile.seek(0)
frame = numpy.load(memfile)
ret, jpeg = cv2.imencode('.jpg', frame)
self.jpeg = jpeg
self.connected = True
else:
conn.close()
self.connected = False
break
self.connected = False
Note for the the json serializer which greatly increases the performance of the serialization process, specially comparing to pickle, as explained in this awesome article.
Source code can be found here.
来源:https://stackoverflow.com/questions/29099839/opencv-stream-from-a-camera-connected-to-a-remote-machine