How to Build C/C++ Barcode Reader App on Raspberry Pi 4

I recently purchased a Raspberry Pi 4 (4GB model) and an I2C OLED display module. In this article, I will share how to implement a C/C++ barcode reader project on Raspberry Pi 4 from scratch.

Raspberry Pi 4 Specifications

  • Broadcom BCM2711, Quad core Cortex-A72 (ARM v8) 64-bit SoC @ 1.5GHz
  • 2GB, 4GB or 8GB LPDDR4-3200 SDRAM (depending on model)
  • 2.4 GHz and 5.0 GHz IEEE 802.11ac wireless, Bluetooth 5.0, BLE
  • Gigabit Ethernet
  • 2 USB 3.0 ports; 2 USB 2.0 ports.
  • 2 × micro-HDMI ports (up to 4kp60 supported)

More…

My Hardware Components

Raspberry Pi OS Installation and Configuration

Installation

  1. Download Raspberry Pi OS.
  2. Write the OS image to an SD card with Win32 Disk Imager.
  3. Insert the SD card into Raspberry Pi 4 and connect to power via USB-C connector (minimum 3A*).

Configuration

Launch the OS and then enable the I2C, VNC, and SSH interfaces.

I2C interface

If you want to use Windows Remote Desktop Connection, you can install tightvncserver and xrdp:

sudo apt update
sudo apt install tightvncserver xrdp

rpi remote login

Check disk space:

df -H
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        32G  8.9G   21G  30% /
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           2.1G     0  2.1G   0% /dev/shm
tmpfs           2.1G  9.1M  2.1G   1% /run
tmpfs           5.3M  4.1k  5.3M   1% /run/lock
tmpfs           2.1G     0  2.1G   0% /sys/fs/cgroup
/dev/mmcblk0p1  265M   54M  211M  21% /boot
tmpfs           405M  4.1k  405M   1% /run/user/1000

If not all of the SD card storage is available, run:

sudo raspi-config

Select Advanced Options:

raspi config

Then select A1 to expand disk storage. A reboot is required to make it work:

rpi sd card storage

OpenCV Installation

We can use OpenCV to capture webcam frames.

Download the latest OpenCV source code: https://github.com/opencv/opencv/releases

Install the following required packages:

sudo apt install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libjpeg-dev libpng-dev libtiff-dev

Build (takes more than 1 hour) and install OpenCV:

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DOPENCV_GENERATE_PKGCONFIG=ON ..
make -j4
sudo make install

C/C++ Barcode Reader Project

Let’s create a CMake project named raspberry-pi-cpp-barcode under /home/pi directory:

cd /home/pi
mkdir raspberry-pi-cpp-barcode

Download Dynamsoft Raspberry Pi Barcode SDK to get libDynamsoftBarcodeReader.so:

Raspberry Pi barcode SDK

Link the barcode recognition library, WiringPi library and OpenCV libraries in CMakeLists.txt:

link_directories("${PROJECT_SOURCE_DIR}/platforms/linux/") 
find_package(OpenCV REQUIRED)
include_directories("${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/include/")

# Add the executable
add_executable(BarcodeReader ssd1306_i2c.c BarcodeReader.cxx)
target_link_libraries (BarcodeReader "DynamsoftBarcodeReader" ${OpenCV_LIBS} wiringPi)

Here is the OpenCV C/C++ code for grabbing frames from webcam:

    #include <opencv2/core.hpp>
    #include <opencv2/videoio.hpp>
    #include <opencv2/highgui.hpp>
    #include <opencv2/imgcodecs.hpp>
    #include <opencv2/imgproc.hpp>
    
    Mat frame;
    VideoCapture capture(0);
    for (;;)
    {
        int key = waitKey(10);
        if ((key & 0xff) == 27/*ESC*/) break;

        capture >> frame; // read the next frame from camera
        if (frame.empty())
        {
            cerr << "ERROR: Can't grab camera frame." << endl;
            break;
        }   
        imshow("Dynamsoft Barcode Reader", frame);
        
    }

To decode barcodes from camera frames, we can use the barcode video APIs which manage a frame queue and do barcode detection on a worker thread:

#include "DynamsoftBarcodeReader.h"
#include "BarcodeReaderConfig.h"

void textResultCallback(int frameId, TextResultArray *pResults, void * pUser)
{
    char * pszTemp = NULL;
    pszTemp = (char*)malloc(4096);

    if (pResults->resultsCount == 0)
    {
        snprintf(pszTemp, 4096, "No barcode found.\r\n\r\n");
        printf(pszTemp);
        free(pszTemp);
        CBarcodeReader::FreeTextResults(&pResults);
        return;
    }
    
    for (int iIndex = 0; iIndex < pResults->resultsCount; iIndex++)
    {
        snprintf(pszTemp, 4096, "Barcode %d:\r\n", iIndex + 1);
        printf(pszTemp);
        snprintf(pszTemp, 4096, "Type: %s, Value: %s\r\n", pResults->results[iIndex]->barcodeFormatString, pResults->results[iIndex]->barcodeText);
        printf(pszTemp);

        draw_OLED(pszTemp);
    }
    free(pszTemp);
    CBarcodeReader::FreeTextResults(&pResults);
}

CBarcodeReader reader;
int iRet = reader.InitLicense("DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==");
reader.SetTextResultCallback(textResultCallback,NULL);
capture >> frame;
int width = capture.get(CAP_PROP_FRAME_WIDTH);
int height = capture.get(CAP_PROP_FRAME_HEIGHT);

iRet = reader.StartFrameDecoding(10, 10, width, height, frame.step.p[0], IPF_RGB_888, "");
for (;;)
{
        int key = waitKey(10);
        if ((key & 0xff) == 27/*ESC*/) break;

        capture >> frame; // read the next frame from camera
        if (frame.empty())
        {
            cerr << "ERROR: Can't grab camera frame." << endl;
            break;
        }   
        reader.AppendFrame(frame.data);

        imshow("Dynamsoft Barcode Reader", frame);
        
}

reader.StopFrameDecoding();    

Once we get barcode decoding results, we can show the text on the OLED display:

#include <wiringPi.h>
#include <wiringPiI2C.h>

#include "ssd1306_i2c.h"

void draw_OLED(char* content)
{
    ssd1306_clearDisplay();
    ssd1306_drawString(content);
    ssd1306_display();
}

Finally, build and run the C/C++ barcode reader program:

mkdir build
cd build
cmake ..
cmake –build .
./BarcodeReader

Raspberry Pi barcode QR detection

How to AutoStart Programs

If you want to start the barcode program on OS startup, you can create a /home/pi/autostart.sh script file:

#!/bin/sh
/home/pi/raspberry-pi-cpp-barcode/build/BarcodeReader

Besides, you need to change the file permission to make it executable:

chmod a+x autostart.sh

After that, create a /home/pi/.config/autostart/autostart.desktop file:

[Desktop Entry]
Type=Application
Exec=sh /home/pi/autostart.sh

Now you can reboot the OS to verify whether the barcode program will run automatically:

sudo reboot

Source Code

https://github.com/yushulx/raspberry-pi-cpp-barcode