I’m trying to stream the video feed from my webcam to a program running in a docker container that streams it back to the host (Windows) were I visualize it.
The code of the three nodes is the following:
source.py
import pickle
import socket
import cv2
ip = "127.0.0.1"
port = 49152
print('Connecting to process...')
while True:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, port)) #no longer throws error
break
except socket.error:
pass
print('Connected to process')
camera = cv2.VideoCapture(0)
while True:
_, image = camera.read()
data = {'image': image,
'index': 0}
out = pickle.dumps(data)
sock.sendall(len(out).to_bytes(24, 'big') + pickle.dumps(data))
cv2.imshow('original', image)
cv2.waitKey(1)
sink.py
import io
import pickle
import socket
import cv2
import numpy as np
#Create a socket object.
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("172.30.160.1", 49153)) # 172.30.160.1
sock.listen()
#Accept client.
print('Wainting for connections...')
client, addr = sock.accept()
print('Connection received')
#Receive all the bytes and write them into the file.
while True:
data_length = int.from_bytes(client.recv(24), 'big')
stream = io.BytesIO()
while (data_length - stream.tell()) > 0:
stream.write(client.recv(data_length - stream.tell()))
data = pickle.loads(stream.getbuffer())
cv2.imshow('test', data['image'])
cv2.waitKey(1)
socket.py
import io
import pickle
import socket
#Output Socket Setup
import time
print('Connecting to sink...')
while True:
try:
out_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
out_sock.connect(("172.30.160.1", 49153)) #no longer throws error
break
except socket.error:
pass
print('Connected to sink')
#Input Socket Setup
in_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
in_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 57344)
in_sock.bind(("0.0.0.0", 49152))
in_sock.listen()
#Accept client.
print('Waiting for connections...')
client, addr = in_sock.accept()
print('Connection received')
while True:
data_length = int.from_bytes(client.recv(24), 'big')
stream = io.BytesIO()
while (data_length - stream.tell()) > 0:
stream.write(client.recv(data_length - stream.tell()))
data = pickle.loads(stream.getbuffer())
out = pickle.dumps(data)
out_sock.sendall(len(out).to_bytes(24, 'big') + out)
If I run process.py on Ubuntu18.4 running on the WSL I cannot observe any delay. When I run it on Docker the received stream is visibly delayed and the fps are lower.
For reproducibility this is the Dockerfile I’m using:
FROM python:3.8
# Install cv2 dependencies
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ffmpeg libsm6 libxext6
RUN pip install --no-cache-dir \
numpy \
opencv-python
RUN addgroup grasping \
&& useradd -ms /bin/bash grasping -g grasping
USER grasping:grasping
COPY ./ /home/grasping
WORKDIR /home/grasping
ENV PYTHONPATH /home/grasping
CMD ["python", "process.py"]
Is this a Docker limitation or can I somehow achieve the same performance I get using the WSL?
Also, after I run and terminate the scripts once, if I run the docker container it connects to the sink.py socket even if sink.py is not running. This just happens if process.py is being run on docker.