J
jpickens

  • May 28, 2024
  • Joined May 7, 2022
  • 0 best answers
  • Raspberry Pi/Oak D Lite Depth Camera
    Setup for a portable, battery powered digital depth camera.
    Generates RGBD depth images compatible with the Looking Glass Portrait 3D display.
    Here is a link to the project at Prusa Printables with the full BOM and 3D printable mount.
    [https://www.printables.com/model/196422-raspberry-pi-4b-oak-d-lite-portable-3d-camera]


    The built in touchscreen display:

    And the output as shown on the Looking Glass Portrait:

    Video of the display in action, its hard to show how good this looks IRL.

  • I'm using a slightly modified Python script from the Luxonis examples for a Raspberry Pi connected to an Oak-D Lite.
    The example uses the AI single image depth process to create an RGBD depth map.
    If I'm not mistaken, this only uses the RGB camera and an AI algorithm to generate a depth map.

    Why would Luxonis use this as its specified example for creating an RGBD image?
    Why do you even need a 3 camera Depth system like Oak-D Lite for this?

    What I'd like to do is use the mono L+R cameras to create a greyscale (Black is Back) depth map and align it with a suitably cropped RGB camera image, and output a standard RGBD image.

    I've looked through the examples, and I cannot find where this might be posted on the Luxonis Raspberry Pi download.

    What appears to be the technique in OpenCV for this is the StereoBM module.
    Are there any examples of this in the Oak-D files? Haven't found it yet.
    Any insights would be appreciated.

    • erik replied to this.
    • Erik,
      Thanks for your response. Your explanation sounds reasonable.
      I guess what I'm looking for is more tied to procedural Left/Right depth mapping from stereo pairs than ML from single images. I've browsed through the example scripts in the depthai sections, and haven't found what I'm looking for.

      My ideal I/O would be a 640 x 480 pixel stereo pair derived depth map used to create a 4:3 RGBD still image at the Oak-D Lite maximum color camera resolution of 3840 x 2880.

      Anyone with suggestions as to how to achieve this would be greatly appreciated.

    • I'm using depthai_experiments main.py script to generate aligned RGBD images.
      The blob file /depthai-experiments/gen2-mega-depth/models/megadepth_192x256_openvino_2021.4_6shave.blob
      seems to be set to 192X256 pixels. Is it possible to change this file to the full resolution of the depth camera pair (640X480)?

      I tried the command:
      NN_WIDTH, NN_HEIGHT = 480, 640
      into the script, and it gives an error:
      [18443010510F8E1200] [333.752] [NeuralNetwork(0)] [warning] Input image (480x640) does not match NN (256x192)

      I assume that means that even though the NN_WIDTH command is used to specify width, that the blob file is preloaded with the lower resolution parameters.

      I'm using an Oak-D lite, and its stated depth camera resolution is 640 X 480.

      Any ideas how to get to the stated resolution? There are significant object edge artifacts in the RGBD image, which may be caused by mapping the much lower resolution depth map to the 1080 X 1440 color image which is 31 times less dense. The 480X640 resolution would be lower by a factor of 5, which would improve things greatly.

      • erik replied to this.
      • I'm not sure how to embed code without it displaying in line in the posting. Sorry about that.

        Anyway, here is my first attempt at doing the rotation. It takes the image variable "concated_rgbd" and applies the rotate command as so:

        rotate_concated_rgbd = ndimage.rotate(concated_rgbd, 90)

        Then the variable "rotate_concated_rgbd" is saved as an image file:

        cv2.imwrite(filename, rotate_concated_rgbd)

        I guess I need more information as to how to use the ndimage.rotate command, because this did not work.

        Again, any help would be appreciated.

        • erik replied to this.
        • Hi there, I'm new to the Luxonis OpenCV software, and am trying to create a toolpath for capturing RGBD depth images from an Oak-D Lite attached to a Raspberry Pi. The final image display output is to be on a Looking Glass Portrait (LGP) 3D holographic display frame.

          I'm using the depthai-experiments/gen2-mega-depth python script main.py to capture still RGBD images, and it is working just fine. I already modified the script to make it save the images to a filename with date and time so that it would not overwrite files. The main.py script just starts numbering files as RGBD1.PNG and incrementing the filename by one, but it restarts at 1 when you restart the script. Anyway, that modification is working well.

          My problem is that I want to be able to rotate the Oak-D Lite camera to take portrait mode images which will better fit the LGP display. I can do this in post processing simply by opening the RGBD image in an image editor, rotate 90 degrees, and resave the image. Again, this works fine, but I would like to eliminate this step.

          Here is an example output image:

          As you can see, this image is two 1440 Width by 1080 Height pixel images side by side (2880 X1080 pixels) with the RGB portion on the left and the greyscale "heat map" depth image on the right. When imported into the LGP Holoplay Studio software, it is not possible to rotate the image, so it is displayed sideways.

          This is the same image rotated with an image editor (in this case, Irfanview):

          This works in Holoplay studio, as you can designate where the D image is relative to the RGB image. In this case, you just specify "Above" and you get the properly rotated portrait mode image on the display.

          So on to the python script. It takes an RGB frame grab and concatenates it with a Depth AI frame to create an image variable. What I would like to do is rotate the image before the final save, and I don't know the best way to do this.
          Any suggestions would be appreciated. Here is the main.py script:

          
          #!/usr/bin/env python3
          
          import cv2
          import depthai as dai
          import numpy as np
          import argparse
          import time
          
          '''
          FastDepth demo running on device.
          https://github.com/zl548/MegaDepth
          
          
          Run as:
          python3 -m pip install -r requirements.txt
          python3 main.py
          
          Onnx taken from PINTO0309, added scaling flag, and exported to blob:
          https://github.com/PINTO0309/PINTO_model_zoo/tree/main/153_MegaDepth
          '''
          
          # --------------- Arguments ---------------
          nn_path = "models/megadepth_192x256_openvino_2021.4_6shave.blob"
          
          # choose width and height based on model
          NN_WIDTH, NN_HEIGHT = 256, 192
          
          # --------------- Pipeline ---------------
          # Start defining a pipeline
          pipeline = dai.Pipeline()
          pipeline.setOpenVINOVersion(version = dai.OpenVINO.VERSION_2021_4)
          
          # Define a neural network
          detection_nn = pipeline.createNeuralNetwork()
          detection_nn.setBlobPath(nn_path)
          detection_nn.setNumPoolFrames(4)
          detection_nn.input.setBlocking(False)
          detection_nn.setNumInferenceThreads(2)
          
          # Define camera
          cam = pipeline.createColorCamera()
          cam.setPreviewSize(NN_WIDTH, NN_HEIGHT)
          cam.setInterleaved(False)
          cam.setFps(40)
          cam.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1080_P)
          
          # Create outputs
          xout_cam = pipeline.createXLinkOut()
          xout_cam.setStreamName("cam")
          
          xout_nn = pipeline.createXLinkOut()
          xout_nn.setStreamName("nn")
          
          # Link
          cam.preview.link(detection_nn.input)
          detection_nn.passthrough.link(xout_cam.input)
          detection_nn.out.link(xout_nn.input)
          
          
          # --------------- Inference ---------------
          # Pipeline defined, now the device is assigned and pipeline is started
          with dai.Device(pipeline) as device:
          
              # Output queues will be used to get the rgb frames and nn data from the outputs defined above
              q_cam = device.getOutputQueue("cam", 4, blocking=False)
              q_nn = device.getOutputQueue(name="nn", maxSize=4, blocking=False)
          
              start_time = time.time()
              counter = 0
              fps = 0
              layer_info_printed = False
              while True:
                  in_frame = q_cam.get()
                  in_nn = q_nn.get()
          
                  frame = in_frame.getCvFrame()
          
                  # Get output layer
                  pred = np.array(in_nn.getFirstLayerFp16()).reshape((NN_HEIGHT, NN_WIDTH))
          
                  # Scale depth to get relative depth
                  d_min = np.min(pred)
                  d_max = np.max(pred)
                  depth_relative = (pred - d_min) / (d_max - d_min)
          
                  # Color it
                  depth_relative = np.array(depth_relative) * 255
                  depth_relative = depth_relative.astype(np.uint8)
                  depth_relative = 255 - depth_relative
                  depth_relative = cv2.applyColorMap(depth_relative, cv2.COLORMAP_INFERNO)
          
                  # Show FPS
                  color_black, color_white = (0, 0, 0), (255, 255, 255)
                  label_fps = "Fps: {:.2f}".format(fps)
                  (w1, h1), _ = cv2.getTextSize(label_fps, cv2.FONT_HERSHEY_TRIPLEX, 0.4, 1)
                  cv2.rectangle(frame, (0, frame.shape[0] - h1 - 6), (w1 + 2, frame.shape[0]), color_white, -1)
                  cv2.putText(frame, label_fps, (2, frame.shape[0] - 4), cv2.FONT_HERSHEY_TRIPLEX,
                              0.4, color_black)
          
                  # Concatenate NN input and produced depth
                  cv2.imshow("Detections", cv2.hconcat([frame, depth_relative]))
          
                  counter += 1
                  if (time.time() - start_time) > 1:
                      fps = counter / (time.time() - start_time)
          
                      counter = 0
                      start_time = time.time()
          
                  if cv2.waitKey(1) == ord('q'):
                      break
                      
          >
        • I have a Looking Glass Portrait 3D Holographic Display, and I wanted a quick way to import 3D images into the display system. The Oak-D Lite attached to a raspberry pi running Luxonis OpenCV is one way to achieve this. However, this setup has lots of cables and needs power to be portable, so I put together a build which turns it into a portable camera.


          The camera consists of a Raspberry pi 4B, 4 in. touchscreen display, power board with 4000mAh Li-ion battery, mounting plates, cables, and, of course, the Oak-D Lite AI camera.

          The system outputs 1440 X 2160 pixel RGBD PNG files which have a left half RGB image and a right half greyscale depth image "heat map" where brighter objects are closer. These files are then imported into a Windows PC running Looking Glass HoloPlay Studio software which converts the file into a holographic display image on the Portrait display.

          Here is the full documentation on the Prusa Printables website if you want to make your own 3D camera.

          https://www.printables.com/model/196422-raspberry-pi-4b-oak-d-lite-portable-3d-camera