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)
My Hardware Components
- Raspberry Pi 4 (4GB model)
- Raspberry Pi RGB Cooling HAT with adjustable fan and OLED display
- Micro-HDMI to HDMI cable
- HDMI Female to HDMI Female Coupler Connector (used to extend Micro-HDMI to HDMI cable)
- SanDisk Ultra 32GB MicroSDHC UHS-I Card
- USB Webcam
Raspberry Pi OS Installation and Configuration
Installation
- Download Raspberry Pi OS.
- Write the OS image to an SD card with Win32 Disk Imager.
- 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.
If you want to use Windows Remote Desktop Connection, you can install tightvncserver and xrdp:
sudo apt update
sudo apt install tightvncserver xrdp
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:
Then select A1 to expand disk storage. A reboot is required to make it work:
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:
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
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