Outils pour utilisateurs

Outils du site


streaming_over_network_with_opencv_et_zeromq

Ceci est une ancienne révision du document !


Streaming over network with OpenCV et ZeroMQ

Z = Zero
M = Messaging
Q = Queuing

Pas de latence, peu ce consommation CPU, en python super facile à implémenter
mais pas de réception dans VLC et Pure Data.
Utiliser Streamer des images OpenCV avec v4l2-loopback

ZeroMQ

zeromq.org (également écrit ØMQ, 0MQ ou ZMQ) est une bibliothèque de messagerie asynchrone haute performance

Ressources

Implémentation dans Pure Data

Installation de puredata

sudo apt install multimedia-puredata libzmq3-dev

Compilation du patch zmq

git clone git@github.com:sansculotte/pd-zmq.git
cd pd-zmq
make

Utilisation des scripts fournis

Ça envoie et reçoit des int/string, mais pas d'images !
Extrait de https://github.com/sansculotte/pd-zmq/blob/master/TODO

LATER
* proper architecture workflows
** multiconnects/multicast (pgm?)
* complex objects
** [zmf_router] -- [broker] as abstraction?
** [zmf_dealer] -/
** [zmf_pair]
* implement streams to send audio blocks
** binary modes
* send/receive modes
** binary (for audio/video frames)
** string (for communication w external programs)

Le paquet de la première image est reçu, mais il ne passe passe rien ensuite …

Installation du module python

Dans un environnement virtuel python (3.9)

requirements.txt
opencv-python
imagezmq
sudo apt install python3-pip
python3 -m pip install --upgrade pip
sudo apt install python3-venv
 
cd /le/dossier/de/votre/projet
python3 -m venv mon_env
source mon_env/bin/activate
python3 -m pip install -r requirements.txt
ou
python3 -m pip install opencv-python imagezmq

Lancement d'un script

cd /le/dossier/de/votre/projet
./mon_env/bin/python3 sender_cam.py  # sender_cam.py est le script ci_dessous

Sender avec python et receive dans pd

Bon, là je suis nul en pd !

Exemples

Caméra

Le principe est simple, sender envoie “image”, c'est une image en np.array
Cet array peut être définit par ce que vous voulez.

Les exemples utilisent souvent imutils, qui est une surcouche en python sur OpenCV, et qui a quelques bugs. On peut s'en passer facilement, il suffit de lire la doc OpenCV, par exemple pour retailler les images, les convertir en jpg etc …

sender_cam.py
import time
import imagezmq
import cv2
 
sender = imagezmq.ImageSender(connect_to='tcp://127.0.0.1:5555')
my_name = "moi"
cap = cv2.VideoCapture(2)
time.sleep(2.0)
while 1:
    # image peut venir de n'importe quoi !
    # ici, c'est pour une caméra
    ret, image = cap.read()
    if ret:
        cv2.imshow("moi", image)
        sender.send_image(my_name, image)
        print("send:", image.shape)
    if cv2.waitKey(10) == 27:
        break
receiver_cam.py
import cv2
import imagezmq
 
image_hub = imagezmq.ImageHub()
while 1:
    your_name, image = image_hub.recv_image()
    print(your_name, image.shape)
    cv2.imshow(your_name, image)
    image_hub.send_reply(b'OK')
    if cv2.waitKey(10) == 27:
        break

Profondeur d'une OAK-D Lite

cd /le/dossier/de/votre/projet
source mon_env/bin/activate
python3 -m pip install depthai numpy
sender_oak_depth.py
import time
import imagezmq
import cv2
import depthai as dai
import numpy as np
 
sender = imagezmq.ImageSender(connect_to='tcp://127.0.0.1:5555')
time.sleep(2.0)
 
pipeline = dai.Pipeline()
# Define a source - two mono (grayscale) cameras
left = pipeline.createMonoCamera()
left.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
left.setBoardSocket(dai.CameraBoardSocket.LEFT)
right = pipeline.createMonoCamera()
right.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
right.setBoardSocket(dai.CameraBoardSocket.RIGHT)
# Create a node that will produce the depth map (using disparity output as it's easier to visualize depth this way)
depth = pipeline.createStereoDepth()
depth.setConfidenceThreshold(200)
 
# Options: MEDIAN_OFF, KERNEL_3x3, KERNEL_5x5, KERNEL_7x7 (default)
median = dai.StereoDepthProperties.MedianFilter.KERNEL_7x7 # For depth filtering
depth.setMedianFilter(median)
 
# Better handling for occlusions:
depth.setLeftRightCheck(False)
# Closer-in minimum depth, disparity range is doubled:
depth.setExtendedDisparity(False)
# Better accuracy for longer distance, fractional disparity 32-levels:
depth.setSubpixel(False)
 
left.out.link(depth.left)
right.out.link(depth.right)
 
# Create output
xout = pipeline.createXLinkOut()
xout.setStreamName("disparity")
depth.disparity.link(xout.input)
 
with dai.Device(pipeline) as device:
    device.startPipeline()
    # Output queue will be used to get the disparity frames from the outputs defined above
    q = device.getOutputQueue(name="disparity", maxSize=4, blocking=False)
 
    while True:
        inDepth = q.get()  # blocking call, will wait until a new data has arrived
        frame = inDepth.getFrame()
        frame = cv2.normalize(frame, None, 0, 255, cv2.NORM_MINMAX)
        # Convert depth_frame to numpy array to render image in opencv
        depth_gray_image = np.asanyarray(frame)
        # Resize Depth image to 640x480
        resized = cv2.resize(depth_gray_image, (640, 480), interpolation = cv2.INTER_AREA)
        sender.send_image("moi", resized)
        cv2.imshow("disparity", resized)
        if cv2.waitKey(1) == 27:
            break

Le receiver est le même que ci-dessus.

streaming_over_network_with_opencv_et_zeromq.1645794919.txt.gz · Dernière modification : 2022/02/25 13:15 de serge