Anda di halaman 1dari 12

31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

Real-time Barcode Scanning from Camera Stream


Xiao Ling

25 Jul 2019 CPOL

In this post, we discuss how to leverage Dynamsoft Barcode Reader video decoding APIs to implement the barcode scanning
functionality in camera preview scenario. Also, we demonstrate how to implement for desktop and mobile platforms respectively
with the code snippet.

This article is in the Product Showcase section for our sponsors at CodeProject. These articles are intended to provide you with
information on products and services that we consider useful and of value to developers.

Barcode detection and recognition technology, especially the application of real-time barcode scanning, is imperative to industries
such as warehouse management and mobile payment. Dynamsoft Barcode Reader, as a cross-platform and cross-programing
language SDK, is a lifesaver for developers who are dedicated to building enterprise-class barcode solutions in a short time.

In this post, we discuss how to leverage Dynamsoft Barcode Reader video decoding APIs to implement the barcode scanning
functionality in camera preview scenario. Also, we demonstrate how to implement for desktop and mobile platforms respectively
with the code snippet.

The Challenge of Camera Real-time Barcode Scanning


The process of reading barcodes consists of various computer vision algorithms, some of which are CPU-intensive. To make the
camera preview run smoothly, you have to execute intensive computation asynchronously in a worker thread. A multithreading
model is required for this case, in which developers have to spend a lot more time on thread scheduling, shared memory, status
synchronization, and lock. Developers are prone to make mistakes in such a complicated scenario.

To eliminate the complexity of multi-threaded programming and improve developers’ efficiency, Dynamsoft Barcode Reader 7.0
brings a set of thread-based APIs for decoding continuous frames.

Dynamsoft Barcode Reader Overview


Dynamsoft's Barcode Reader SDK enables you to efficiently embed barcode reading functionality in your web, desktop or mobile
application using just a few lines of code, which saves your development time and cost. With the SDK, you can create high-speed
and reliable barcode scanner software to meet your business needs.

License
Get a FREE 30-day trial license.

Supported Barcode Symbologies


Linear Barcodes (1D): Code 39, Code 93, Code 128, Codabar, Interleaved 2 of 5, EAN-8, EAN-13, UPC-A, UPC-E, Industrial 2 of 5.

2D Barcodes: QR Code, DataMatrix, PDF417 and Aztec Code.

https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 1/12
31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

Developer’s Guide
https://www.dynamsoft.com/help/Barcode-Reader/devguide/index.html

API Documentation
https://www.dynamsoft.com/help/Barcode-Reader/index.html

Code Gallery
https://www.dynamsoft.com/Downloads/Dynamic-Barcode-Reader-Sample-Download.aspx

Online Demo
https://demo.dynamsoft.com/DBR/BarcodeReaderDemo.aspx

How Barcode Video Decoding APIs Work


The video decoding model contains a user main thread, a decoding thread, and a result consumer thread.

User Main Thread

The user main thread is initiated when StartFrameDecoding() is being called. Invoke AppendFrame() to add frames to
an auto-managed frame queue in a video frame callback function.

Decoding Thread
The decoding thread takes all CPU-intensive work, running barcode algorithms. It uses some strategies to select and discard frames
in order to avoid lagging.

https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 2/12
31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

Result Consumer Thread


This thread manages registered callback functions for fetching results.

Desktop Barcode Scanning


To build a desktop barcode app quickly, we recommend using Python and OpenCV.

Breaking Through Python’s GIL


The performance of Python multithreading code, especially for computation-intensive tasks, is restricted due to
Python’s GIL (Global Interpreter Lock). The new video decoding APIs of Dynamsoft Barcode Reader is based on native C/C++
thread, which will not be affected by Python’s virtual machine.

Let’s take a glimpse of the Python sample code:

import cv2
import dbr
import time
import os

# The callback function for receiving barcode results


def onBarcodeResult(format, text):
print("Type: " + format)
print("Value: " + text + "\n")

def read_barcode():
video_width = 640
video_height = 480

vc = cv2.VideoCapture(0)
vc.set(3, video_width) #set width
vc.set(4, video_height) #set height

if vc.isOpened():
dbr.initLicense('LICENSE-KEY')
rval, frame = vc.read()
else:
return

windowName = "Barcode Reader"

max_buffer = 2
max_results = 10
barcodeTypes = 0x3FF | 0x2000000 | 0x4000000 | 0x8000000 | 0x10000000 # 1D, PDF417, QRCODE,
DataMatrix, Aztec Code
image_format = 1 # 0: gray; 1: rgb888

dbr.startVideoMode(max_buffer, max_results, video_width, video_height, image_format,


barcodeTypes, onBarcodeResult)

while True:
cv2.imshow(windowName, frame)
rval, frame = vc.read()

start = time.time()
try:
ret = dbr.appendVideoFrame(frame)
except:
pass

cost = (time.time() - start) * 1000


print('time cost: ' + str(cost) + ' ms')

https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 3/12
31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

# 'ESC' for quit


key = cv2.waitKey(1)
if key == 27:
break

dbr.stopVideoMode()
dbr.destroy()
cv2.destroyWindow(windowName)

if __name__ == "__main__":
print("OpenCV version: " + cv2.__version__)
read_barcode()

The dbr module is the Python extension built with Dynamsoft Barcode Reader. We created three methods:
startVideoMode(), appendVideoFrame() and stopVideoMode(). The corresponding C/C++ code is as follows.

static PyObject *
startVideoMode(PyObject *self, PyObject *args)
{
printf("Start the video mode\n");
CHECK_DBR();

PyObject *callback = NULL;


int maxListLength, maxResultListLength, width, height, imageformat, iFormat, stride;
if (!PyArg_ParseTuple(args, "iiiiiiO", &maxListLength, &maxResultListLength, &width,
&height, &imageformat, &iFormat, &callback)) {
return NULL;
}

updateFormat(iFormat);

if (!PyCallable_Check(callback))
{
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
return NULL;
}
else
https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 4/12
31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

{
Py_XINCREF(callback); /* Add a reference to new callback */
Py_XDECREF(py_callback); /* Dispose of previous callback */
py_callback = callback;
}

ImagePixelFormat format = IPF_RGB_888;

if (imageformat == 0)
{
stride = width;
format = IPF_GRAYSCALED;
}
else {
stride = width * 3;
format = IPF_RGB_888;
}

DBR_SetTextResultCallback(hBarcode, onResultCallback, NULL);

int ret = DBR_StartFrameDecoding(hBarcode, maxListLength, maxResultListLength, width,


height, stride, format, "");
return Py_BuildValue("i", ret);
}

appendVideoFrame()

static PyObject *
appendVideoFrame(PyObject *self, PyObject *args)
{
CHECK_DBR();

PyObject *o;
if (!PyArg_ParseTuple(args, "O", &o))
return NULL;

#if defined(IS_PY3K)
//Refer to numpy/core/src/multiarray/ctors.c
Py_buffer *view;
int nd;
PyObject *memoryview = PyMemoryView_FromObject(o);
if (memoryview == NULL) {
PyErr_Clear();
return -1;
}

view = PyMemoryView_GET_BUFFER(memoryview);
unsigned char *buffer = (unsigned char *)view->buf;
nd = view->ndim;
int len = view->len;
int stride = view->strides[0];
int width = view->strides[0] / view->strides[1];
int height = len / stride;
#else

PyObject *ao = PyObject_GetAttrString(o, "__array_struct__");

if ((ao == NULL) || !PyCObject_Check(ao)) {


PyErr_SetString(PyExc_TypeError, "object does not have array interface");
return NULL;
}

PyArrayInterface *pai = (PyArrayInterface*)PyCObject_AsVoidPtr(ao);

if (pai->two != 2) {
PyErr_SetString(PyExc_TypeError, "object does not have array interface");
Py_DECREF(ao);
https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 5/12
31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

return NULL;
}

// Get image information


unsigned char *buffer = (unsigned char *)pai->data; // The address of image data
int width = (int)pai->shape[1]; // image width
int height = (int)pai->shape[0]; // image height
int stride = (int)pai->strides[0]; // image stride
#endif

// Initialize Dynamsoft Barcode Reader


TextResultArray *paryResult = NULL;

// Detect barcodes
ImagePixelFormat format = IPF_RGB_888;

if (width == stride)
{
format = IPF_GRAYSCALED;
}
else if (width == stride * 3)
{
format = IPF_RGB_888;
}
else if (width == stride * 4)
{
format = IPF_ARGB_8888;
}

int frameId = DBR_AppendFrame(hBarcode, buffer);


return 0;
}

stopVideoMode()

static PyObject *
stopVideoMode(PyObject *self, PyObject *args)
{
printf("Stop the video mode\n");
if (hBarcode)
{
int ret = DBR_StopFrameDecoding(hBarcode);
return Py_BuildValue("i", ret);
}

return 0;
}

You have to call Python code between PyGILState_Ensure() and PyGILState_Release() when executing the
callback function on the native thread:

void onResultCallback(int frameId, TextResultArray *pResults, void * pUser)


{
// Get barcode results
int count = pResults->resultsCount;
int i = 0;

// https://docs.python.org/2/c-api/init.html
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();

for (; i < count; i++)


{
// https://docs.python.org/2.5/ext/callingPython.html
PyObject *result = PyObject_CallFunction(py_callback, "ss", pResults->results[i]-
>barcodeFormatString, pResults->results[i]->barcodeText);
https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 6/12
31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

if (result == NULL) return NULL;


Py_DECREF(result);
}

PyGILState_Release(gstate);
/////////////////////////////////////////////

// Release memory
DBR_FreeTextResults(&pResults);
}

Source Code
https://github.com/dynamsoft-dbr/python/tree/7.x

Android Barcode Scanning


To build a simple Android barcode scanning app with Android camera API and Dynamsoft Barcode Reader.

cameraView.addFrameProcessor(new FrameProcessor() {
@SuppressLint("NewApi")
@Override
public void process(@NonNull final Frame frame) {
try {
if (isDetected && isCameraOpen) {
YuvImage yuvImage = new YuvImage(frame.getData(), ImageFormat.NV21,
frame.getSize().getWidth(), frame.getSize().getHeight(), null);
if (width == 0) {
width = yuvImage.getWidth();
height = yuvImage.getHeight();
stride = yuvImage.getStrides()[0];
reader.setErrorCallback(errorCallback, null);
reader.setTextResultCallback(textResultCallback, null);
reader.setIntermediateResultCallback(intermediateResultCallback,
null);
reader.startFrameDecoding(10, 10, width, height, stride,
EnumImagePixelFormat.IPF_NV21, "");
} else {
PublicRuntimeSettings s = reader.getRuntimeSettings();
int frameid = reader.appendFrame(yuvImage.getYuvData());
Log.i("FrameId", frameid + "");
}
if (bUpateDrawBox) {
bUpateDrawBox = false;
Message message = handler.obtainMessage();
Rect imageRect = new Rect(0, 0, width, height);
message.obj = imageRect;
message.what = 0x001;
handler.sendMessage(message);
}
isDetected = true;
}
} catch (Exception e) {
e.printStackTrace();
}
}
});

https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 7/12
31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

Call startDecodingFrame() to initialize the environment and call appendFrame() repeatedly to add the preview
images.

https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 8/12
31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

Source Code
https://github.com/dynamsoft-dbr/android-barcode-decode-video

iOS Barcode Scanning


To build a simple iOS barcode scanning app with iOS camera API and Dynamsoft Barcode Reader.

(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:


(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection;
{
isCurrentFrameDecodeFinished = NO;
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
int bufferSize = (int)CVPixelBufferGetDataSize(imageBuffer);
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
NSData * buffer = [NSData dataWithBytes:baseAddress length:bufferSize];
startRecognitionDate = [NSDate date];
if (width != (int)CVPixelBufferGetWidth(imageBuffer)) {
width = (int)CVPixelBufferGetWidth(imageBuffer);
height = (int)CVPixelBufferGetHeight(imageBuffer);
stride = CVPixelBufferGetBytesPerRow(imageBuffer);
[m_barcodeReader setDBRErrorDelegate:self userData:nil];
[m_barcodeReader setDBRTextResultDelegate:self userData:nil];
[m_barcodeReader setDBRIntermediateResultDelegate:self userData:nil];
[m_barcodeReader startFrameDecoding:10 maxResultQueueLength:100 width:width
height:height stride:stride format:EnumImagePixelFormatARGB_8888 templateName:@"" error:nil];
} else {
[m_barcodeReader appendFrame:buffer];
}
}

https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 9/12
31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

Call the following to initialize the environment and call -(NSInteger)appendFrame:(NSData*) bufferBytes
repeatedly to add the preview images.

https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 10/12
31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

(void)startFrameDecoding:(NSInteger)maxQueueLength
maxResultQueueLength:(NSInteger)maxResultQueueLength
width:(NSInteger)width
height:(NSInteger)height
stride:(NSInteger)stride
format:(EnumImagePixelFormat)format
templateName:(NSString* _Nonnull)templateName
error:(NSError* _Nullable * _Nullable)error

Source Code
https://github.com/dynamsoft-dbr/ios-barcode-decode-video

Technical Support
If you have any questions about Dynamsoft Barcode Reader SDK, please feel free to contact support@dynamsoft.com.

Release History
v7.0, 07/12/2019

New
Refactored most modules to provide a flexible barcode reading framework that allows for parameter customization suited
for a variety of barcode scenarios
Enabled access to intermediate results (grayscale image, binarized image, text zone, etc) during the decoding process
Added new interfaces to support video decoding, and frame decoding to improve interactive sensitivity
Provided methods to terminate the decoding process at different phases such as during binarization, localization or barcode
type identification.
Added a new barcode localization method, Scan Directly, to reduce decoding time significantly for high-quality images.

Improved
Enhanced error messages related to license initiation failure.
Improved detailed results for decoded barcodes, including more barcode format specification
Improved results output to enable outputting barcode results in the order of confidence level, barcode position or format.

Fix
Fixed an issue where the barcode could be calculated incorrectly on some occasions.

License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 11/12
31/07/2019 Real-time Barcode Scanning from Camera Stream - CodeProject

Xiao Ling
Technical Writer Dynamsoft
Canada

Xiao Ling is A technical content writer at Dynamsoft, the leading company of document capture and image processing SDKs.
He is in charge of managing Dynamsoft blog site codepool.biz and Dynamsoft GitHub community.

Comments and Discussions


0 messages have been posted for this article Visit https://www.codeproject.com/Articles/5163187/Real-time-Barcode-
Scanning-from-Camera-Stream-2 to post and view comments on this article, or click here to get a print view with messages.

Permalink Article Copyright 2019 by Xiao Ling


Advertise Everything else Copyright © CodeProject, 1999-2019
Privacy
Cookies Web01 2.8.190731.1
Terms of Use

https://www.codeproject.com/Articles/5163187/Real-time-Barcode-Scanning-from-Camera-Stream-2?display=Print 12/12