Build and Deploy a Retail Store Items Detection System Using No-Code AI Vision at the Edge

Retail store item detection

Low-code and no-code platforms have risen sharply in popularity over the past few years. These platforms let users with little or no knowledge of coding build apps 20x faster with minimal coding. They’ve even evolved to a point where they’ve become indispensable tools for expert developers. Such platforms are highly visual and follow a user-friendly, modular approach. Consequently, you need to drag and drop software components into place — all of which are visually represented — to create an app.

Node-RED is a low-code programming language for event-driven applications. It’s a programming tool for wiring together hardware devices, APIs, and online services in new and interesting ways. Node-RED also provides a browser-based flow editor that makes it easy to wire together flows using the wide range of nodes within the palette. Accordingly, you can deploy it to its runtime with a single-click. Once more, you can create JavaScript functions within the editor using the rich-text editor. Finally, Node-RED ships with a built-in library that lets you save useful and reusable functions, templates or flows.

Node-RED’s lightweight runtime is built upon Node.js, taking full advantage of Node’s event-driven, non-blocking model. This helps it run at the edge of the network on low-cost hardware — like the Raspberry Pi and in the cloud. With over 225,000 modules in Node’s package repository, it’s easy to extend the range of palette nodes and add new capabilities.The flows created in Node-RED are stored using JSON, which is easily importable and exportable for sharing purposes. An online flow library lets you publish your best flows publicly.

Users have downloaded our Node-RED Docker Official Image over 100 million times from Docker Hub. What’s driving this significant download rate? There’s an ever-increasing demand for Docker containers to streamline development workflows, while giving Node-RED developers the freedom to innovate with their choice of project-tailored tools, application stacks, and deployment environments. Our Node-RED Official Image also supports multiple architectures like amd64, arm32v6, arm32v7, arm64v8, and s390x.

Why is containerizing Node-RED important?

The Node-RED Project has a huge community of third-party nodes available for installation. Also, note that the community doesn’t generally recommend using an odd-numbered Node version. This advice is tricky for new users, since they might end up fixing Node compatibility issues.

Running your Node-RED app in a Docker container lets users get started quickly with sensible defaults and customization via environmental variables. Users no longer need to worry about compatibility issues. Next, Docker enables users to build, share, and run containerized Node-RED applications — made accessible for developers of all skill levels.

Building your application

In this tutorial, you’ll learn how to build a retail store items detection system using Node-RED. First, you’ll set up Node-RED manually on an IoT Edge device without Docker. Second, you’ll learn how to run it within a Docker container via a one-line command. Finally, you’ll see how Docker containers help you build and deploy this detection system using Node-RED. Let’s jump in.

Hardware components

Software Components

Preparing your Seeed Studio reComputer and development environment

For this demonstration, we’re using a Seeed Studio reComputer. The Seeed Studio reComputer J1010 is powered by the Jetson Nano development kit. It’s a small, powerful, palm-sized computer that makes modern AI accessible to embedded developers. It’s built around the NVIDIA Jetson Nano system-on-module (SoM) and designed for edge AI applications.

Wire it up

Plug your WiFi adapter/Ethernet cable, Keyboard/Mouse, and USB camera into the reComputer system and turn it on using the power cable. Follow the steps to perform initial system startup.

Item detection usb cameraRecomputer system

Before starting, make sure you have Node installed in your system. Then, follow these steps to set up Node-RED on your Edge device.

Installing Node.js

Ensure that you have the latest stable version of Node.js installed in your system.

curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs

Verify Node.js and npm versions

The above installer will install both Node.js and npm. Let’s verify that they’re installed properly:

# check Node.js version
nodejs -v
v16.16.0
# check npm version
npm -v
8.11.0

Installing Node-RED

To install Node-RED, you can use the npm command that comes with Node.js:

sudo npm install -g --unsafe-perm node-red

changed 294 packages, and audited 295 packages in 17s

38 packages are looking for funding
run `npm fund` for details

found 0 vulnerabilities

Running Node-RED

Use the node-red command to start Node-RED in your terminal:

node-red
27 Jul 15:08:36 - [info]

Welcome to Node-RED
===================

27 Jul 15:08:36 - [info] Node-RED version: v3.0.1
27 Jul 15:08:36 - [info] Node.js  version: v16.16.0
27 Jul 15:08:36 - [info] Linux 4.9.253-tegra arm64 LE
27 Jul 15:08:37 - [info] Loading palette nodes
27 Jul 15:08:38 - [info] Settings file  : /home/ajetraina/.node-red/settings.js
27 Jul 15:08:38 - [info] Context store  : 'default' [module=memory]
27 Jul 15:08:38 - [info] User directory : /home/ajetraina/.node-red
27 Jul 15:08:38 - [warn] Projects disabled : editorTheme.projects.enabled=false
27 Jul 15:08:38 - [info] Flows file     : /home/ajetraina/.node-red/flows.json
27 Jul 15:08:38 - [info] Creating new flow file
27 Jul 15:08:38 - [warn]

---------------------------------------------------------------------
Your flow credentials file is encrypted using a system-generated key.

If the system-generated key is lost for any reason, your credentials
file will not be recoverable, you will have to delete it and re-enter
your credentials.

You should set your own key using the 'credentialSecret' option in
your settings file. Node-RED will then re-encrypt your credentials
file using your chosen key the next time you deploy a change.
---------------------------------------------------------------------

27 Jul 15:08:38 - [info] Server now running at http://127.0.0.1:1880/
27 Jul 15:08:38 - [warn] Encrypted credentials not found
27 Jul 15:08:38 - [info] Starting flows
27 Jul 15:08:38 - [info] Started flows

You can then access the Node-RED editor by navigating to http://localhost:1880 in your browser.

The log output shares some important pieces of information:

  • Installed versions of Node-RED and Node.js
  • Any errors encountered while trying to load the palette nodes
  • The location of your Settings file and User Directory
  • The name of the flow file currently being used

Welcom to node red

Node-RED consists of a Node.js based runtime that provides a web address to access the flow editor. You create your application in the browser by dragging nodes from your palette into a workspace, From there, you start wiring them together. With one click, Node-RED deploys your application back to the runtime where it’s run.

Running Node-RED in a Docker container

The Node-RED Official Image is based on our Node.js Alpine Linux images, in order to keep them as slim as possible. Run the following command to create and mount a named volume called node_red_data to the container’s /data directory. This will allow us to persist any flow changes.

docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red

You can now access the Node-RED editor via http://localhost:1880 or http://<ip_address_Jetson>:1880.

Building and running your retail store items detection system

To build a fully functional retail store items detection system, follow these next steps.

Write the configuration files

We must define a couple of files that add Node-RED configurations — such as custom themes and custom npm packages.

First, create an empty folder called “node-red-config”:

mkdir node-red-config

Change your directory to node-red-config and run the following command to setup a new NPM package.

npm init

This utility will walk you through the package.json file creation process. It only covers the most common items, and tries to guess sensible defaults.

{
"name": "node-red-project",
"description": "A Node-RED Project",
"version": "0.0.1",
"private": true,
"dependencies": {
"@node-red-contrib-themes/theme-collection": "^2.2.3",
"node-red-seeed-recomputer": "git+https://github.com/Seeed-Studio/node-red-seeed-recomputer.git"
}
}

Create a file called settings.js inside the node-red-config folder and enter the following content. This file defines Node-RED server, runtime, and editor settings. We’ll mainly change the editor settings. For more information about individual settings, refer to the documentation.

module.exports = {

flowFile: 'flows.json',

flowFilePretty: true,

uiPort: process.env.PORT || 1880,

logging: {
console: {
level: "info",
metrics: false,
audit: false
}
},

exportGlobalContextKeys: false,

externalModules: {
},

editorTheme: {
theme: "midnight-red",

page: {
title: "reComputer Flow Editor"
},
header: {
title: "  Flow Editor&amp;amp;amp;lt;br/&amp;amp;amp;gt;",
image: "/data/seeed.webp", // or null to remove image
},

palette: {
},

projects: {
enabled: false,
workflow: {
mode: "manual"
}
},

codeEditor: {
lib: "ace",
options: {
theme: "vs",
}
}
},

functionExternalModules: true,

functionGlobalContext: {
},

debugMaxLength: 1000,

mqttReconnectTime: 15000,

serialReconnectTime: 15000,

}

You can download this image and put it under the node-red-config folder. This image file’s location is defined inside the settings.js file we just created.

Write the script

Create an empty file by running the following command:

touch docker-ubuntu.sh

In order to print colored output, let’s first define a few colors in the shell script. This will get reflected as an output when you execute the script at a later point of time:

IBlack='\033[0;90m'       # Black
IRed='\033[0;91m'         # Red
IGreen='\033[0;92m'       # Green
IYellow='\033[0;93m'      # Yellow
IBlue='\033[0;94m'        # Blue
IPurple='\033[0;95m'      # Purple
ICyan='\033[0;96m'        # Cyan
IWhite='\033[0;97m'       # White

The sudo command allows a normal user to run a command with elevated privileges so that they can perform certain administrative tasks. As this script involves running multiple tasks that involve administrative privileges, it’s always recommended to check if you’re running the script as a “sudo” user.

if ! [ $(id -u) = 0 ] ; then
echo "$0 must be run as sudo user or root"
exit 1
fi

The reComputer for Jetson is sold with 16 GB of eMMC. This ready-to-use hardware has Ubuntu 18.04 LTS and NVIDIA JetPack 4.6 installed, so the remaining user space available is about 2 GB. This could be a significant obstacle to using the reComputer for training and deployment in some projects. Hence, it’s sometimes important to remove unnecessary packages and libraries. This code snippet confirms that you have enough storage to install all included packages and Docker images.

If you have the required storage space, it’ll continue to the next section. Otherwise, the installer will ask if you want to free up some device space. Typing “y” for “yes” will delete unnecessary files and packages to clear some space.

storage=$(df   | awk '{ print  $4  } ' | awk 'NR==2{print}' )
#if storage &amp;amp;amp;gt; 3.8G
if [ $storage -gt 3800000 ] ; then
echo -e "${IGreen}Your storage space left is $(($storage /1000000))GB, you can install this application."
else
echo -e "${IRed}Sorry, you don't have enough storage space to install this application. You need about 3.8GB of storage space."
echo -e "${IYellow}However, you can regain about 3.8GB of storage space by performing the following:"
echo -e "${IYellow}-Remove unnecessary packages (~100MB)"
echo -e "${IYellow}-Clean up apt cache (~1.6GB)"
echo -e "${IYellow}-Remove thunderbird, libreoffice and related packages (~400MB)"
echo -e "${IYellow}-Remove cuda, cudnn, tensorrt, visionworks and deepstream samples (~800MB)"
echo -e "${IYellow}-Remove local repos for cuda, visionworks, linux-headers (~100MB)"
echo -e "${IYellow}-Remove GUI (~400MB)"
echo -e "${IYellow}-Remove Static libraries (~400MB)"
echo -e "${IRed}So, please agree to uninstall the above. Press [y/n]"
read yn
if [ $yn = "y" ] ; then
echo "${IGreen}starting to remove the above-mentioned"
# Remove unnecessary packages, clean apt cache and remove thunderbird, libreoffice
apt update
apt autoremove -y
apt clean
apt remove thunderbird libreoffice-* -y

# Remove samples
rm -rf /usr/local/cuda/samples \
/usr/src/cudnn_samples_* \
/usr/src/tensorrt/data \
/usr/src/tensorrt/samples \
/usr/share/visionworks* ~/VisionWorks-SFM*Samples \
/opt/nvidia/deepstream/deepstream*/samples

# Remove local repos
apt purge cuda-repo-l4t-*local* libvisionworks-*repo -y
rm /etc/apt/sources.list.d/cuda*local* /etc/apt/sources.list.d/visionworks*repo*
rm -rf /usr/src/linux-headers-*

# Remove GUI
apt-get purge gnome-shell ubuntu-wallpapers-bionic light-themes chromium-browser* libvisionworks libvisionworks-sfm-dev -y
apt-get autoremove -y
apt clean -y

# Remove Static libraries
rm -rf /usr/local/cuda/targets/aarch64-linux/lib/*.a \
/usr/lib/aarch64-linux-gnu/libcudnn*.a \
/usr/lib/aarch64-linux-gnu/libnvcaffe_parser*.a \
/usr/lib/aarch64-linux-gnu/libnvinfer*.a \
/usr/lib/aarch64-linux-gnu/libnvonnxparser*.a \
/usr/lib/aarch64-linux-gnu/libnvparsers*.a

# Remove additional 100MB
apt autoremove -y
apt clean
else
exit 1
fi
fi

This code snippet checks if the required software (curl, docker, nvidia-docker2, and Docker Compose) is installed:

apt update

if ! [ -x "$(command -v curl)" ]; then
apt install curl
fi

if ! [ -x "$(command -v docker)" ]; then
apt install docker
fi

if ! [ -x "$(command -v nvidia-docker)" ]; then
apt install nvidia-docker2
fi

if ! [ -x "$(command -v docker-compose)" ]; then
curl -SL https://files.seeedstudio.com/wiki/reComputer/compose.tar.bz2  -o /tmp/compose.tar.bz2
tar xvf /tmp/compose.tar.bz2 -C /usr/local/bin
chmod +x  /usr/local/bin/docker-compose
fi

Next, you need to create a node-red directory under $HOME and then copy all your Node-RED configuration files to your device’s home directory as shown in the snippet below:

mkdir -p $HOME/node-red
cp node-red-config/*  $HOME/node-red

The below snippet allows the script to bring up container services using Docker Compose CLI:

docker compose --file docker-compose.yaml  up -d

Note: You’ll see how to create a Docker Compose file in the next section.

Within the script, let’s specify the command to install a custom Node-RED theme package with three Node-RED blocks corresponding to video input, detection, and video view. We’ll circle back to these nodes later.

docker exec node-red-contrib-ml-node-red-1 bash -c "cd /data &amp;amp;amp;amp;&amp;amp;amp;amp; npm install"

Finally, the below command embedded in the script allows you to restart the node-red-contrib-ml-node-red-1 container to implement your theme changes:

docker restart node-red-contrib-ml-node-red-1

Lastly, save the script as docker-ubuntu.sh.

Define your services within a Compose file

Create an empty file by running the following command inside the same directory as docker-ubuntu.sh:

touch docker-compose.yaml

Add the following lines within your docker-compose.yml file. These specify which services Docker should initiate concurrently at application launch:

services:
node-red:
image: nodered/node-red:3.0.1
restart: always
network_mode: "host"
volumes:
- "$HOME/node-red:/data"
user: "0"
dataloader:
image: baozhu/node-red-dataloader:v1.2
restart: always
runtime: nvidia
network_mode: "host"
privileged: true
devices:
- "/dev:/dev"
- "/var/run/udev:/var/run/udev"
detection:
image: baozhu/node-red-detection:v1.2
restart: always
runtime: nvidia
network_mode: "host"

Your application has the following parts:

  • Three services backed by Docker images: your Node-RED node-red app, dataloader, and detection
  • The dataloader service container will broadcast an OpenCV video stream (either from a USB webcam or an IP camera with RTSP) using the Pub/Sub messaging pattern to port 5550. It’s important to note that one needs to pass privileged:true to allow your service containers to get access to USB camera devices.
  • The detection service container will grab the above video stream and perform inference using TensorRT implementation of YOLOv5. This is an object-detection algorithm that can identify objects in real-time.

Execute the script

Open your terminal and run the following command:

sudo ./docker-ubuntu.sh

It’ll take approximately 2-3 minutes for these scripts to execute completely.

View your services

Once your script is executed, you can verify that your container services are up and running:

docker compose ps

CONTAINER ID   IMAGE                             COMMAND                  CREATED          STATUS                        PORTS     NAMES
e487c20eb87b   baozhu/node-red-dataloader:v1.2   "python3 python/pub_…"   48 minutes ago   Up About a minute                       retail-store-items-detection-nodered-dataloader-1
4441bc3c2a2c   baozhu/node-red-detection:v1.2    "python3 python/yolo…"   48 minutes ago   Up About a minute                       retail-store-items-detection-nodered-detection-1
dd5c5e37d60d   nodered/node-red:3.0.1            "./entrypoint.sh"        48 minutes ago   Up About a minute (healthy)             retail-store-items-detection-nodered-node-red-1

Visit http://127.0.0.1:1880/ to access the app.

Seeed studio node red

You’ll find built-in nodes (video input, detection, and video view) available in the palette:

Seeed studio flow detection

Let’s try to wire nodes by dragging them one-by-one from your palette into a workspace. First, let’s drag video input from the palette to the workspace. Double-click “Video Input” to view the following properties, and select “Local Camera”.

Note: We choose a local camera here to grab the video stream from the connected USB webcam. However, you can also grab the video stream from an IP camera via RTSP.

Seeed studio video input

You’ll see that Node-RED chooses “COCO dataset” model name by default:

Seeed studio object detection

Next, drag Video View from the palette to the workspace. If you double-click on Video View, you’ll discover that msg.payload is already chosen for you under the Property section.

Seeed studio video view

Wire up the nodes

Once you have all the nodes placed in the workspace, it’s time to wire nodes together. Nodes are wired together by pressing the left-mouse button on a node’s port, dragging to the destination node and releasing the mouse button (as shown in the following screenshot).

Seeed studio video flow

Trigger Deploy at the top right corner to start the deployment process. By now, you should be able to see the detection process working as Node-RED detects items.

Seeed studio image detection flow

Conclusion

The ultimate goal of modernizing software development is to deliver high-value software to end users even faster. Low-code technology like Node-RED and Docker help us achieve this by accelerating the time from ideation to software delivery. Docker helps accelerate the process of building, running, and sharing modern AI applications.

Docker Official Images help you develop your own unique applications — no matter what tech stack you’re accustomed to. With one YAML file, we’ve demonstrated how Docker Compose helps you easily build Node-RED apps. We can even take Docker Compose and develop real-world microservices applications. With just a few extra steps, you can apply this tutorial while building applications with much greater complexity. Happy coding!

References: