# Script change pipeline flow

This example shows how you can change the flow of data inside your pipeline in runtime using the
[Script](https://docs.luxonis.com/software/depthai-components/nodes/script.md) node. In this example, we send a message from the
host to choose whether we want Script node to forwards color frame to the
[MobileNetDetectionNetwork](https://docs.luxonis.com/software/depthai-components/nodes/mobilenet_detection_network.md).

## Demo

## Pipeline Graph

## Setup

Please run the [install script](https://github.com/luxonis/depthai-python/blob/main/examples/install_requirements.py) to download
all required dependencies. Please note that this script must be ran from git context, so you have to download the
[depthai-python](https://github.com/luxonis/depthai-python) repository first and then run the script

```bash
git clone https://github.com/luxonis/depthai-python.git
cd depthai-python/examples
python3 install_requirements.py
```

For additional information, please follow the [installation guide](https://docs.luxonis.com/software/depthai/manual-install.md).

## Source code

#### Python

```python
#!/usr/bin/env python3
import depthai as dai
import cv2
from pathlib import Path
import numpy as np

parentDir = Path(__file__).parent
nnPath = str((parentDir / Path('../models/mobilenet-ssd_openvino_2021.4_5shave.blob')).resolve().absolute())

pipeline = dai.Pipeline()

cam = pipeline.createColorCamera()
cam.setBoardSocket(dai.CameraBoardSocket.CAM_A)
cam.setInterleaved(False)
cam.setIspScale(2,3)
cam.setVideoSize(720,720)
cam.setPreviewSize(300,300)

xoutRgb = pipeline.create(dai.node.XLinkOut)
xoutRgb.setStreamName('rgb')
cam.video.link(xoutRgb.input)

script = pipeline.createScript()

xin = pipeline.create(dai.node.XLinkIn)
xin.setStreamName('in')
xin.out.link(script.inputs['toggle'])

cam.preview.link(script.inputs['rgb'])
script.setScript("""
    toggle = False
    while True:
        msg = node.io['toggle'].tryGet()
        if msg is not None:
            toggle = msg.getData()[0]
            node.warn('Toggle! Perform NN inferencing: ' + str(toggle))

        frame = node.io['rgb'].get()

        if toggle:
            node.io['nn'].send(frame)
""")

nn = pipeline.create(dai.node.MobileNetDetectionNetwork)
nn.setBlobPath(nnPath)
script.outputs['nn'].link(nn.input)

xoutNn = pipeline.create(dai.node.XLinkOut)
xoutNn.setStreamName('nn')
nn.out.link(xoutNn.input)

# Connect to device with pipeline
with dai.Device(pipeline) as device:
    inQ = device.getInputQueue("in")
    qRgb = device.getOutputQueue("rgb")
    qNn = device.getOutputQueue("nn")

    runNn = False

    def frameNorm(frame, bbox):
        normVals = np.full(len(bbox), frame.shape[0])
        normVals[::2] = frame.shape[1]
        return (np.clip(np.array(bbox), 0, 1) * normVals).astype(int)

    color = (255, 127, 0)
    def drawDetections(frame, detections):
        for detection in detections:
            bbox = frameNorm(frame, (detection.xmin, detection.ymin, detection.xmax, detection.ymax))
            cv2.putText(frame, f"{int(detection.confidence * 100)}%", (bbox[0] + 10, bbox[1] + 20), cv2.FONT_HERSHEY_TRIPLEX, 0.5, color)
            cv2.rectangle(frame, (bbox[0], bbox[1]), (bbox[2], bbox[3]), color, 2)

    while True:
        frame = qRgb.get().getCvFrame()

        if qNn.has():
            detections = qNn.get().detections
            drawDetections(frame, detections)

        cv2.putText(frame, f"NN inferencing: {runNn}", (20,20), cv2.FONT_HERSHEY_TRIPLEX, 0.7, color)
        cv2.imshow('Color frame', frame)

        key = cv2.waitKey(1)
        if key == ord('q'):
            break
        elif key == ord('t'):
            runNn = not runNn
            print(f"{'Enabling' if runNn else 'Disabling'} NN inferencing")
            buf = dai.Buffer()
            buf.setData(runNn)
            inQ.send(buf)
```

#### C++

```cpp
#include <iostream>

// Includes common necessary includes for development using depthai library
#include "depthai/depthai.hpp"

int main() {
    dai::Pipeline pipeline;

    auto cam = pipeline.create<dai::node::ColorCamera>();
    cam->setBoardSocket(dai::CameraBoardSocket::CAM_A);
    cam->setInterleaved(false);
    cam->setIspScale(2, 3);
    cam->setVideoSize(720, 720);
    cam->setPreviewSize(300, 300);

    auto xoutRgb = pipeline.create<dai::node::XLinkOut>();
    xoutRgb->setStreamName("rgb");
    cam->video.link(xoutRgb->input);

    auto script = pipeline.create<dai::node::Script>();

    auto xin = pipeline.create<dai::node::XLinkIn>();
    xin->setStreamName("in");
    xin->out.link(script->inputs["toggle"]);

    cam->preview.link(script->inputs["rgb"]);
    script->setScript(R"(
        toggle = False
        while True:
            msg = node.io['toggle'].tryGet()
            if msg is not None:
                toggle = msg.getData()[0]
                node.warn('Toggle! Perform NN inferencing: ' + str(toggle))
            frame = node.io['rgb'].get()
            if toggle:
                node.io['nn'].send(frame)
    )");

    auto nn = pipeline.create<dai::node::MobileNetDetectionNetwork>();
    nn->setBlobPath(BLOB_PATH);
    script->outputs["nn"].link(nn->input);

    auto xoutNn = pipeline.create<dai::node::XLinkOut>();
    xoutNn->setStreamName("nn");
    nn->out.link(xoutNn->input);

    // Connect to device with pipeline
    dai::Device device(pipeline);
    auto inQ = device.getInputQueue("in");
    auto qRgb = device.getOutputQueue("rgb");
    auto qNn = device.getOutputQueue("nn");

    bool runNn = false;

    auto color = cv::Scalar(255, 127, 0);

    auto drawDetections = [color](cv::Mat frame, std::vector<dai::ImgDetection>& detections) {
        for(auto& detection : detections) {
            int x1 = detection.xmin * frame.cols;
            int y1 = detection.ymin * frame.rows;
            int x2 = detection.xmax * frame.cols;
            int y2 = detection.ymax * frame.rows;

            std::stringstream confStr;
            confStr << std::fixed << std::setprecision(2) << detection.confidence * 100;
            cv::putText(frame, confStr.str(), cv::Point(x1 + 10, y1 + 20), cv::FONT_HERSHEY_TRIPLEX, 0.5, color);
            cv::rectangle(frame, cv::Rect(cv::Point(x1, y1), cv::Point(x2, y2)), color, cv::FONT_HERSHEY_SIMPLEX);
        }
    };

    while(true) {
        auto frame = qRgb->get<dai::ImgFrame>()->getCvFrame();
        auto imgDetections = qNn->tryGet<dai::ImgDetections>();
        if(imgDetections != nullptr) {
            auto detections = imgDetections->detections;
            drawDetections(frame, detections);
        }
        std::string frameText = "NN inferencing: ";
        if(runNn) {
            frameText += "On";
        } else {
            frameText += "Off";
        }
        cv::putText(frame, frameText, cv::Point(20, 20), cv::FONT_HERSHEY_TRIPLEX, 0.7, color);
        cv::imshow("Color frame", frame);

        int key = cv::waitKey(1);
        if(key == 'q') {
            return 0;
        } else if(key == 't') {
            if(runNn) {
                std::cout << "Disabling\n";
            } else {
                std::cout << "Enabling\n";
            }
            runNn = !runNn;
            auto buf = dai::Buffer();
            std::vector<uint8_t> messageData;
            messageData.push_back(runNn);
            buf.setData(messageData);
            inQ->send(buf);
        }
    }
}
```

## Pipeline

### examples/script_change_pipeline_flow.pipeline.json

```json
{
  "pipeline": {
    "connections": [
      {
        "node1Id": 0,
        "node1Output": "video",
        "node1OutputGroup": "",
        "node2Id": 1,
        "node2Input": "in",
        "node2InputGroup": ""
      },
      {
        "node1Id": 3,
        "node1Output": "out",
        "node1OutputGroup": "",
        "node2Id": 2,
        "node2Input": "toggle",
        "node2InputGroup": "io"
      },
      {
        "node1Id": 0,
        "node1Output": "preview",
        "node1OutputGroup": "",
        "node2Id": 2,
        "node2Input": "rgb",
        "node2InputGroup": "io"
      },
      {
        "node1Id": 2,
        "node1Output": "nn",
        "node1OutputGroup": "io",
        "node2Id": 4,
        "node2Input": "in",
        "node2InputGroup": ""
      },
      {
        "node1Id": 4,
        "node1Output": "out",
        "node1OutputGroup": "",
        "node2Id": 5,
        "node2Input": "in",
        "node2InputGroup": ""
      }
    ],
    "globalProperties": {
      "calibData": null,
      "cameraTuningBlobSize": null,
      "cameraTuningBlobUri": "",
      "leonCssFrequencyHz": 700000000.0,
      "leonMssFrequencyHz": 700000000.0,
      "pipelineName": null,
      "pipelineVersion": null,
      "sippBufferSize": 18432,
      "sippDmaBufferSize": 16384,
      "xlinkChunkSize": -1
    },
    "nodes": [
      [
        0,
        {
          "id": 0,
          "ioInfo": [
            [
              [
                "",
                "inputConfig"
              ],
              {
                "blocking": false,
                "group": "",
                "id": 1,
                "name": "inputConfig",
                "queueSize": 8,
                "type": 3,
                "waitForMessage": false
              }
            ],
            [
              [
                "",
                "raw"
              ],
              {
                "blocking": false,
                "group": "",
                "id": 6,
                "name": "raw",
                "queueSize": 8,
                "type": 0,
                "waitForMessage": false
              }
            ],
            [
              [
                "",
                "still"
              ],
              {
                "blocking": false,
                "group": "",
                "id": 7,
                "name": "still",
                "queueSize": 8,
                "type": 0,
                "waitForMessage": false
              }
            ],
            [
              [
                "",
                "inputControl"
              ],
              {
                "blocking": true,
                "group": "",
                "id": 2,
                "name": "inputControl",
                "queueSize": 8,
                "type": 3,
                "waitForMessage": false
              }
            ],
            [
              [
                "",
                "video"
              ],
              {
                "blocking": false,
                "group": "",
                "id": 3,
                "name": "video",
                "queueSize": 8,
                "type": 0,
                "waitForMessage": false
              }
            ],
            [
              [
                "",
                "isp"
              ],
              {
                "blocking": false,
                "group": "",
                "id": 4,
                "name": "isp",
                "queueSize": 8,
                "type": 0,
                "waitForMessage": false
              }
            ],
            [
              [
                "",
                "preview"
              ],
              {
                "blocking": false,
                "group": "",
                "id": 5,
                "name": "preview",
                "queueSize": 8,
                "type": 0,
                "waitForMessage": false
              }
            ],
            [
              [
                "",
                "frameEvent"
              ],
              {
                "blocking": false,
                "group": "",
                "id": 8,
                "name": "frameEvent",
                "queueSize": 8,
                "type": 0,
                "waitForMessage": false
              }
            ]
          ],
          "name": "ColorCamera",
          "properties": {
            "boardSocket": 0,
            "cameraName": "",
            "colorOrder": 0,
            "fp16": false,
            "fps": 30.0,
            "imageOrientation": -1,
            "initialControl": {
              "aeLockMode": false,
              "aeMaxExposureTimeUs": 0,
              "aeRegion": {
                "height": 0,
                "priority": 0,
                "width": 0,
                "x": 0,
                "y": 0
              },
              "afRegion": {
                "height": 0,
                "priority": 0,
                "width": 0,
                "x": 0,
                "y": 0
              },
              "antiBandingMode": 0,
              "autoFocusMode": 3,
              "awbLockMode": false,
              "awbMode": 0,
              "brightness": 0,
              "captureIntent": 0,
              "chromaDenoise": 0,
              "cmdMask": 0,
              "contrast": 0,
              "controlMode": 0,
              "effectMode": 0,
              "expCompensation": 0,
              "expManual": {
                "exposureTimeUs": 0,
                "frameDurationUs": 0,
                "sensitivityIso": 0
              },
              "frameSyncMode": 0,
              "lensPosAutoInfinity": 0,
              "lensPosAutoMacro": 0,
              "lensPosition": 0,
              "lensPositionRaw": 0.0,
              "lowPowerNumFramesBurst": 0,
              "lowPowerNumFramesDiscard": 0,
              "lumaDenoise": 0,
              "saturation": 0,
              "sceneMode": 0,
              "sharpness": 0,
              "strobeConfig": {
                "activeLevel": 0,
                "enable": 0,
                "gpioNumber": 0
              },
              "strobeTimings": {
                "durationUs": 0,
                "exposureBeginOffsetUs": 0,
                "exposureEndOffsetUs": 0
              },
              "wbColorTemp": 0
            },
            "interleaved": false,
            "isp3aFps": 0,
            "ispScale": {
              "horizDenominator": 3,
              "horizNumerator": 2,
              "vertDenominator": 3,
              "vertNumerator": 2
            },
            "numFramesPoolIsp": 3,
            "numFramesPoolPreview": 4,
            "numFramesPoolRaw": 3,
            "numFramesPoolStill": 4,
            "numFramesPoolVideo": 4,
            "previewHeight": 300,
            "previewKeepAspectRatio": true,
            "previewWidth": 300,
            "rawPacked": null,
            "resolution": 0,
            "sensorCropX": -1.0,
            "sensorCropY": -1.0,
            "stillHeight": -1,
            "stillWidth": -1,
            "videoHeight": 720,
            "videoWidth": 720
          }
        }
      ],
      [
        1,
        {
          "id": 1,
          "ioInfo": [
            [
              [
                "",
                "in"
              ],
              {
                "blocking": true,
                "group": "",
                "id": 9,
                "name": "in",
                "queueSize": 8,
                "type": 3,
                "waitForMessage": true
              }
            ]
          ],
          "name": "XLinkOut",
          "properties": {
            "maxFpsLimit": -1.0,
            "metadataOnly": false,
            "streamName": "rgb"
          }
        }
      ],
      [
        2,
        {
          "id": 2,
          "ioInfo": [
            [
              [
                "io",
                "toggle"
              ],
              {
                "blocking": true,
                "group": "io",
                "id": 10,
                "name": "toggle",
                "queueSize": 8,
                "type": 3,
                "waitForMessage": false
              }
            ],
            [
              [
                "io",
                "nn"
              ],
              {
                "blocking": false,
                "group": "io",
                "id": 12,
                "name": "nn",
                "queueSize": 8,
                "type": 0,
                "waitForMessage": false
              }
            ],
            [
              [
                "io",
                "rgb"
              ],
              {
                "blocking": true,
                "group": "io",
                "id": 11,
                "name": "rgb",
                "queueSize": 8,
                "type": 3,
                "waitForMessage": false
              }
            ]
          ],
          "name": "Script",
          "properties": {
            "processor": 1,
            "scriptName": "<script>",
            "scriptUri": "asset:__script"
          }
        }
      ],
      [
        3,
        {
          "id": 3,
          "ioInfo": [
            [
              [
                "",
                "out"
              ],
              {
                "blocking": false,
                "group": "",
                "id": 13,
                "name": "out",
                "queueSize": 8,
                "type": 0,
                "waitForMessage": false
              }
            ]
          ],
          "name": "XLinkIn",
          "properties": {
            "maxDataSize": 5242880,
            "numFrames": 8,
            "streamName": "in"
          }
        }
      ],
      [
        4,
        {
          "id": 4,
          "ioInfo": [
            [
              [
                "",
                "in"
              ],
              {
                "blocking": true,
                "group": "",
                "id": 14,
                "name": "in",
                "queueSize": 5,
                "type": 3,
                "waitForMessage": true
              }
            ],
            [
              [
                "",
                "out"
              ],
              {
                "blocking": false,
                "group": "",
                "id": 15,
                "name": "out",
                "queueSize": 8,
                "type": 0,
                "waitForMessage": false
              }
            ],
            [
              [
                "",
                "passthrough"
              ],
              {
                "blocking": false,
                "group": "",
                "id": 16,
                "name": "passthrough",
                "queueSize": 8,
                "type": 0,
                "waitForMessage": false
              }
            ]
          ],
          "name": "DetectionNetwork",
          "properties": {
            "blobSize": 14517568,
            "blobUri": "asset:__blob",
            "numFrames": 8,
            "numNCEPerThread": 0,
            "numThreads": 0,
            "parser": {
              "anchorMasks": {},
              "anchors": [],
              "classes": 0,
              "confidenceThreshold": 0.5,
              "coordinates": 0,
              "iouThreshold": 0.0,
              "nnFamily": 1
            }
          }
        }
      ],
      [
        5,
        {
          "id": 5,
          "ioInfo": [
            [
              [
                "",
                "in"
              ],
              {
                "blocking": true,
                "group": "",
                "id": 17,
                "name": "in",
                "queueSize": 8,
                "type": 3,
                "waitForMessage": true
              }
            ]
          ],
          "name": "XLinkOut",
          "properties": {
            "maxFpsLimit": -1.0,
            "metadataOnly": false,
            "streamName": "nn"
          }
        }
      ]
    ]
  }
}
```

### Need assistance?

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