# Neural Assisted Stereo

This example demonstrates the
[NeuralAssistedStereo](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/neural_assisted_stereo.md) node,
which fuses [NeuralDepth](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/neural_depth.md) with classical
[StereoDepth](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/stereo_depth.md).

This example requires the DepthAI v3 API, see [installation instructions](https://docs.luxonis.com/software-v3/depthai.md).

## Source code

#### Python

```python
import numpy as np
import cv2 as cv
import depthai as dai

FPS = 20

def showDepth(depthFrame, windowName="Depth", minDistance=500, maxDistance=5000,
               colormap=cv.COLORMAP_TURBO, useLog=False):
    """
    Nicely visualize a depth map.

    Args:
        depthFrame (np.ndarray): Depth frame (in millimeters).
        windowName (str): OpenCV window name.
        minDistance (int): Minimum depth to display (in mm).
        maxDistance (int): Maximum depth to display (in mm).
        colormap (int): OpenCV colormap (e.g., cv.COLORMAP_JET, COLORMAP_TURBO, etc.).
        useLog (bool): Apply logarithmic scaling for better visual contrast.

    Example:
        frame = depth.getCvFrame()
        showDepth(frame)
    """
    # Convert to float for processing
    depthFrame = depthFrame.astype(np.float32)

    # Optionally apply log scaling
    if useLog:
        depthFrame = np.log(depthFrame + 1)

    # Clip to defined range (avoid far-out values)
    depthFrame = np.uint8(np.clip(depthFrame, minDistance, maxDistance) / maxDistance * 255)

    # Apply color map
    depthColor = cv.applyColorMap(depthFrame, colormap)

    # Show in a window
    cv.imshow(windowName, depthColor)

if __name__ == "__main__":
    device = dai.Device()
    pipeline = dai.Pipeline(device)
    if not device.isNeuralDepthSupported():
        print("Exiting NeuralAssistedStereo example: device doesn't support NeuralDepth.")
        exit()

    monoLeft = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_B, sensorFps=FPS)
    monoRight = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_C, sensorFps=FPS)

    monoLeftOut = monoLeft.requestFullResolutionOutput()
    monoRightOut = monoRight.requestFullResolutionOutput()

    neuralAssistedStereo = pipeline.create(dai.node.NeuralAssistedStereo).build(monoLeftOut, monoRightOut, neuralModel=dai.DeviceModelZoo.NEURAL_DEPTH_NANO)

    disparityQueue = neuralAssistedStereo.disparity.createOutputQueue()

    with pipeline:
        pipeline.start()
        while pipeline.isRunning():
            disparity = disparityQueue.get()
            showDepth(disparity.getCvFrame(), minDistance=100, maxDistance=6000, useLog=False)

            key = cv.waitKey(1)
            if key == ord('q'):
                quit()
```

#### C++

```cpp
#include <depthai/depthai.hpp>
#include <depthai/device/Device.hpp>
#include <depthai/pipeline/node/Camera.hpp>
#include <depthai/pipeline/node/NeuralAssistedStereo.hpp>
#include <iostream>
#include <opencv2/opencv.hpp>

constexpr float FPS = 20.0f;
// Nicely visualize a depth map.
// The input depthFrame is assumed to be the raw disparity (CV_16UC1 or similar)
// received from the DepthAI pipeline.
void showDepth(const cv::Mat& depthFrameIn,
               const std::string& windowName = "Depth",
               int minDistance = 500,
               int maxDistance = 5000,
               int colormap = cv::COLORMAP_TURBO,
               bool useLog = false) {
    cv::Mat depthFrame = depthFrameIn.clone();

    cv::Mat floatFrame;
    depthFrame.convertTo(floatFrame, CV_32FC1);

    // # Optionally apply log scaling
    if(useLog) {
        // depthFrame = np.log(depthFrame + 1)
        cv::log(floatFrame + 1, floatFrame);
    }

    cv::Mat upperClamped;
    cv::min(floatFrame, maxDistance, upperClamped);

    cv::Mat clippedFrame;
    cv::max(upperClamped, minDistance, clippedFrame);

    double alpha = 255.0 / maxDistance;
    clippedFrame.convertTo(clippedFrame, CV_8U, alpha);

    cv::Mat depthColor;
    cv::applyColorMap(clippedFrame, depthColor, colormap);

    cv::imshow(windowName, depthColor);
}

int main() {
    // 1. Create device and pipeline
    auto device = std::make_shared<dai::Device>();
    dai::Pipeline pipeline(device);
    if(!device->isNeuralDepthSupported()) {
        std::cout << "Exiting NeuralAssistedStereo example: device doesn't support NeuralDepth.\n";
        return 0;
    }

    // 2. Define nodes
    auto monoLeft = pipeline.create<dai::node::Camera>()->build(dai::CameraBoardSocket::CAM_B, std::nullopt, FPS);
    auto monoRight = pipeline.create<dai::node::Camera>()->build(dai::CameraBoardSocket::CAM_C, std::nullopt, FPS);
    auto monoRightOut = monoRight->requestFullResolutionOutput();
    auto monoLeftOut = monoLeft->requestFullResolutionOutput();

    auto neuralAssistedStereo = pipeline.create<dai::node::NeuralAssistedStereo>()->build(*monoLeftOut, *monoRightOut, dai::DeviceModelZoo::NEURAL_DEPTH_NANO);

    // 6. Get output queue
    auto disparityQueue = neuralAssistedStereo->disparity.createOutputQueue();

    pipeline.start();
    while(pipeline.isRunning()) {
        auto disparityPacket = disparityQueue->get<dai::ImgFrame>();
        showDepth(disparityPacket->getCvFrame(), "Depth", 100, 6000, cv::COLORMAP_TURBO, false);
        int key = cv::waitKey(1);
        if(key == 'q') {
            break;
        }
    }
    return 0;
}
```

### Need assistance?

Head over to [Discussion Forum](https://discuss.luxonis.com/) for technical support or any other questions you might have.
