Real-time Webcam Barcode Detection with OpenCV and C++
Dynamsoft Barcode Reader C++ SDK is available for Windows, Linux, and Mac (iOS and Android editions are coming soon). I have shared an article that illustrates how to build webcam barcode reader in Python. In this tutorial, I’ll use a different C++ API to implement barcode scanner applications for Windows and Raspberry Pi with a webcam.
What You Should Know
Getting Started with Webcam Barcode Reader
How to capture frame from webcam using OpenCV
VideoCapture cap(0);
if (!cap.isOpened())
return -1;
Mat frame;
for (;;)
{
cap >> frame; // Get a new frame from camera
imshow(windowName, frame); // Display the new frame
if (waitKey(30) >= 0)
break;
}
How to initialize Dynamsoft Barcode Reader
CBarcodeReader reader;
reader.InitLicense("LICENSE_KEY");
__int64 llFormat = (OneD | QR_CODE | PDF417 | DATAMATRIX);
int iMaxCount = 0x7FFFFFFF;
ReaderOptions ro = { 0 };
ro.llBarcodeFormat = llFormat;
ro.iMaxBarcodesNumPerPage = iMaxCount;
reader.SetReaderOptions(ro);
How to pre-process camera frame buffer
The barcode API only takes DIB (device-independent bitmap) structure as the input data, and thus, you have to re-construct the buffer wrapped in Mat:
int elemSize = image.elemSize();
int size = image.total() * elemSize;
// Get image data
char *imageData = (char *)image.data;
// Combine header info and image data
int width = image.cols, height = image.rows;
char *total = (char *)malloc(size + 40);
if (!total)
{
printf("Failed to allocate memory");
return;
}
memset(total, 0, size + 40);
BITMAPINFOHEADER bitmap_info = { 40, width, height, 0, 24, 0, size, 0, 0, 0, 0 };
memcpy(total, &bitmap_info, 40);
char *data = total + 40;
// Reverse the image buffer from bottom to top
width *= 3;
for (int i = 1; i <= height; i++)
{
memcpy(data, imageData + width * (height - i), width);
data += width;
}
Reading barcode image buffer on Windows
int iRet = reader.DecodeBuffer((unsigned char*)total, size + 40);
char * pszTemp = (char*)malloc(4096);
if (iRet != DBR_OK && iRet != DBRERR_LICENSE_EXPIRED && iRet != DBRERR_QR_LICENSE_INVALID &&
iRet != DBRERR_1D_LICENSE_INVALID && iRet != DBRERR_PDF417_LICENSE_INVALID && iRet != DBRERR_DATAMATRIX_LICENSE_INVALID)
{
sprintf(pszTemp, "Failed to read barcode: %s\r\n", DBR_GetErrorString(iRet));
printf(pszTemp);
free(pszTemp);
free(total);
return;
}
pBarcodeResultArray paryResult = NULL;
reader.GetBarcodes(&paryResult);
if (paryResult->iBarcodeCount > 0)
{
for (int iIndex = 0; iIndex < paryResult->iBarcodeCount; iIndex++)
{
sprintf(pszTemp, "Barcode %d:\r\n", iIndex + 1);
printf(pszTemp);
sprintf(pszTemp, " Page: %d\r\n", paryResult->ppBarcodes[iIndex]->iPageNum);
printf(pszTemp);
sprintf(pszTemp, " Type: %s\r\n", GetFormatStr(paryResult->ppBarcodes[iIndex]->llFormat));
printf(pszTemp);
char *pszTemp1 = (char*)malloc(paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
memset(pszTemp1, 0, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
memcpy(pszTemp1, paryResult->ppBarcodes[iIndex]->pBarcodeData, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength);
sprintf(pszTemp, " Value: %s\r\n", pszTemp1);
printf(pszTemp);
free(pszTemp1);
sprintf(pszTemp, " Region: {Left: %d, Top: %d, Width: %d, Height: %d}\r\n\r\n",
paryResult->ppBarcodes[iIndex]->iLeft, paryResult->ppBarcodes[iIndex]->iTop,
paryResult->ppBarcodes[iIndex]->iWidth, paryResult->ppBarcodes[iIndex]->iHeight);
printf(pszTemp);
}
}
free(pszTemp);
reader.FreeBarcodeResults(&paryResult);
free(total);
Reading barcode image buffer on Linux
Porting the source code from Windows to Linux is a little bit tricky because DIB structure is not defined on Linux platform. We can define it ourselves:
typedef unsigned long DWORD;
typedef long LONG;
typedef unsigned short WORD;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
Build the source code:
g++ -ggdb -I$(DynamsoftBarcodeReader)/include -o barcodereader barcodereader.cpp -lDynamsoftBarcodeReader `pkg-config --libs opencv`
Source Code
https://github.com/dynamsoftlabs/cplusplus-webcam-barcode-reader