streamer_des_images_opencv_avec_v4l2-loopback
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
streamer_des_images_opencv_avec_v4l2-loopback [2022/02/21 19:39] – [Streamer des images OpenCV avec v4l2-loopback] serge | streamer_des_images_opencv_avec_v4l2-loopback [2022/03/03 12:35] (Version actuelle) – [Profondeur d'une RealSense D455] serge | ||
---|---|---|---|
Ligne 3: | Ligne 3: | ||
<WRAP center round box 60%> | <WRAP center round box 60%> | ||
Le **[[streaming_over_network_with_opencv_et_zeromq|stream avec zeromq]]** est sans latence, mais ne peut pas être reçu par Pure Data et VLC.\\ | Le **[[streaming_over_network_with_opencv_et_zeromq|stream avec zeromq]]** est sans latence, mais ne peut pas être reçu par Pure Data et VLC.\\ | ||
- | **v4l2-loopback** a un peu de latence (0.1 à 0.2 seconde) en lecture dans VLC, mais pas si lecture avec OpenCV | + | **v4l2-loopback** a un peu de latence (0.1 à 0.2 seconde) en lecture dans VLC, mais pas de latence |
+ | **Nous utilisons pyfakewebcam** | ||
</ | </ | ||
=====Ressources===== | =====Ressources===== | ||
+ | **pyfakewebcam** | ||
Il y a divers projets qui font ça sur GitHub, celui ci à cette qualité de marcher! | Il y a divers projets qui font ça sur GitHub, celui ci à cette qualité de marcher! | ||
* https:// | * https:// | ||
Ligne 12: | Ligne 14: | ||
* https:// | * https:// | ||
- | =====Installation==== | + | =====Sources des exemples===== |
- | A voir, nécessaire mais peut-être pas suffisant: | + | * **[[https:// |
- | sudo apt install v4l2loopback-utils | + | |
- | + | ||
- | <code bash> | + | |
- | sudo apt install python3-pip | + | |
- | python3 -m pip install --upgrade pip | + | |
- | sudo apt install python3-venv | + | |
- | cd /le/ | + | ====Installation==== |
- | python3 | + | Voir le README ci-dessus. |
- | source mon_env/ | + | |
- | python3 -m pip install opencv-python pyfakewebcam | + | |
- | </ | + | |
=====Exemple simple pour tester===== | =====Exemple simple pour tester===== | ||
<file python cam_relay.py> | <file python cam_relay.py> | ||
- | """ | ||
- | Insert the v4l2loopback kernel module. | ||
- | modprobe v4l2loopback devices=2 | ||
- | will create two fake webcam devices | ||
- | """ | ||
- | import time | ||
import pyfakewebcam | import pyfakewebcam | ||
import cv2 | import cv2 | ||
Ligne 40: | Ligne 27: | ||
cap = cv2.VideoCapture(0) | cap = cv2.VideoCapture(0) | ||
- | camera = pyfakewebcam.FakeWebcam('/ | + | camera = pyfakewebcam.FakeWebcam('/ |
while True: | while True: | ||
ret, image = cap.read() | ret, image = cap.read() | ||
Ligne 48: | Ligne 36: | ||
if cv2.waitKey(1) == 27: | if cv2.waitKey(1) == 27: | ||
break | break | ||
- | |||
- | """ | ||
- | Run the following command to see the output of the fake webcam. | ||
- | ffplay /dev/video1 | ||
- | or open a camera in vlc | ||
- | """ | ||
</ | </ | ||
- | Exécuter le script avec: | + | Run the following command to see the output of the fake webcam.\\ |
- | cd / | + | ffplay /dev/video11\\ |
- | modprobe v4l2loopback devices=2 | + | or open the camera 11 in vlc |
- | | + | |
- | Dans un autre terminal | + | |
- | | + | |
- | Il faudra peut-être adapter les numéro de /dev/video | + | |
- | + | ||
===== Profondeur d'une OAK-D Lite ===== | ===== Profondeur d'une OAK-D Lite ===== | ||
- | < | ||
- | cd / | ||
- | source mon_env/ | ||
- | python3 -m pip install depthai numpy | ||
- | </ | ||
- | |||
<file python sender_oak_depth.py> | <file python sender_oak_depth.py> | ||
import cv2 | import cv2 | ||
Ligne 78: | Ligne 49: | ||
pipeline = dai.Pipeline() | pipeline = dai.Pipeline() | ||
+ | |||
# Define a source - two mono (grayscale) cameras | # Define a source - two mono (grayscale) cameras | ||
left = pipeline.createMonoCamera() | left = pipeline.createMonoCamera() | ||
Ligne 111: | Ligne 83: | ||
depth.disparity.link(xout.input) | depth.disparity.link(xout.input) | ||
- | camera = pyfakewebcam.FakeWebcam('/ | + | camera = pyfakewebcam.FakeWebcam('/ |
with dai.Device(pipeline) as device: | with dai.Device(pipeline) as device: | ||
Ligne 133: | Ligne 105: | ||
break | break | ||
</ | </ | ||
- | Exécuter le script avec: | + | |
- | cd / | + | Ouvrir /dev/video11 |
- | modprobe v4l2loopback devices=2 | + | |
- | ./ | + | |
- | Ouvrir /dev/video1 | + | |
{{ : | {{ : | ||
- | ====Profondeur d'une RealSense D455==== | + | =====Profondeur d'une RealSense D455===== |
Pour l' | Pour l' | ||
- | <code bash> | ||
- | cd / | ||
- | source mon_env/ | ||
- | python3 -m pip install | ||
- | </ | ||
<file python sender_rs_depth.py> | <file python sender_rs_depth.py> | ||
+ | """ | ||
+ | Voir https:// | ||
+ | |||
+ | Suppression du fond, voir | ||
+ | https:// | ||
+ | """ | ||
+ | |||
import os | import os | ||
import time | import time | ||
Ligne 154: | Ligne 125: | ||
import numpy as np | import numpy as np | ||
import pyrealsense2 as rs | import pyrealsense2 as rs | ||
+ | |||
+ | |||
+ | # Le faux device | ||
+ | VIDEO = '/ | ||
+ | |||
+ | # Avec ou sans slider pour régler CLIPPING_DISTANCE_IN_MILLIMETER | ||
+ | SLIDER = 1 | ||
+ | # Réglable avec le slider | ||
+ | # We will be removing the background of objects more than | ||
+ | # CLIPPING_DISTANCE_IN_MILLIMETER away | ||
+ | CLIPPING_DISTANCE_IN_MILLIMETER = 2000 | ||
+ | |||
class MyRealSense: | class MyRealSense: | ||
- | """ | + | |
- | def __init__(self): | + | def __init__(self, video, slider, clip): |
+ | self.video = video | ||
+ | self.slider = slider | ||
+ | self.clip = clip | ||
self.width = 1280 | self.width = 1280 | ||
self.height = 720 | self.height = 720 | ||
Ligne 180: | Ligne 167: | ||
format=rs.format.z16, | format=rs.format.z16, | ||
framerate=30) | framerate=30) | ||
- | | + | |
+ | profile = self.pipeline.start(config) | ||
self.align = rs.align(rs.stream.color) | self.align = rs.align(rs.stream.color) | ||
unaligned_frames = self.pipeline.wait_for_frames() | unaligned_frames = self.pipeline.wait_for_frames() | ||
frames = self.align.process(unaligned_frames) | frames = self.align.process(unaligned_frames) | ||
- | | + | |
- | self.depth_intrinsic | + | # Getting the depth sensor' |
+ | depth_sensor | ||
+ | self.depth_scale | ||
+ | print(" | ||
# Affichage de la taille des images | # Affichage de la taille des images | ||
color_frame = frames.get_color_frame() | color_frame = frames.get_color_frame() | ||
Ligne 191: | Ligne 183: | ||
print(f" | print(f" | ||
f" | f" | ||
- | | + | |
+ | | ||
+ | |||
+ | if self.slider: | ||
+ | self.create_slider() | ||
+ | |||
+ | def create_slider(self): | ||
+ | cv2.namedWindow('controls' | ||
+ | cv2.createTrackbar(' | ||
+ | self.remove_background_callback) | ||
+ | cv2.setTrackbarPos(' | ||
+ | cv2.namedWindow(' | ||
+ | |||
+ | def remove_background_callback(self, | ||
+ | if value != 1000: | ||
+ | self.clip = int(value) | ||
def run(self): | def run(self): | ||
""" | """ | ||
+ | |||
while self.pose_loop: | while self.pose_loop: | ||
- | | + | |
+ | # Get frameset of color and depth | ||
+ | | ||
+ | # frames.get_depth_frame() is a 640x360 depth image | ||
# Align the depth frame to color frame | # Align the depth frame to color frame | ||
aligned_frames = self.align.process(frames) | aligned_frames = self.align.process(frames) | ||
- | depth_color_frame = aligned_frames.get_depth_frame() | ||
- | # Convert 16bit data: à vérifier, c'est bon pour gray, en RGB ? | + | # aligned_depth_frame is a 640x480 depth image |
- | | + | aligned_depth_frame = aligned_frames.get_depth_frame() |
- | | + | color_frame = aligned_frames.get_color_frame() |
- | self.camera.schedule_frame(detph_color_16bit) | + | |
- | + | # Validate that both frames are valid | |
+ | if not aligned_depth_frame or not color_frame: | ||
+ | continue | ||
+ | |||
+ | | ||
+ | color_image = np.asanyarray(color_frame.get_data()) | ||
+ | |||
+ | # Remove background - Set pixels further than clipping_distance to grey | ||
+ | # depth image is 1 channel, color is 3 channels | ||
+ | depth_image_3d | ||
+ | | ||
+ | bg_removed | ||
+ | (depth_image_3d <= 0), 0, color_image) | ||
+ | |||
+ | depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, | ||
+ | | ||
+ | | ||
+ | images = np.hstack((bg_removed, | ||
+ | |||
+ | if self.slider: | ||
+ | cv2.imshow(' | ||
+ | |||
+ | self.camera.schedule_frame(bg_removed) | ||
if cv2.waitKey(1) == 27: | if cv2.waitKey(1) == 27: | ||
break | break | ||
+ | |||
+ | |||
if __name__ == ' | if __name__ == ' | ||
- | | + | |
+ | | ||
mrs.run() | mrs.run() | ||
</ | </ | ||
+ | | ||
+ | =====Réception===== | ||
+ | Ouvrir / | ||
- | Exécuter le script avec: | + | {{:media_15: |
- | cd / | + | |
- | | + | ou |
- | ./ | + | <file python receiver.py> |
- | Ouvrir /dev/video1 dans VLC | + | import cv2 |
+ | cap = cv2.VideoCapture(2) | ||
+ | while 1: | ||
+ | ret, image = cap.read() | ||
+ | if ret: | ||
+ | cv2.imshow(" | ||
+ | if cv2.waitKey(1) == 27: | ||
+ | break | ||
+ | </file> | ||
{{tag> | {{tag> |
streamer_des_images_opencv_avec_v4l2-loopback.1645472371.txt.gz · Dernière modification : 2022/02/21 19:39 de serge