树莓派正在被广泛应用在工业领域,条形码扫描就是其中一个应用。

准备工作

Camera数据获取

安装Node模块v4l2camera用于获取摄像头数据:

npm install v4l2camera

把摄像头支持的格式打印出来:

var v4l2camera = require("v4l2camera");
 
var cam = new v4l2camera.Camera("/dev/video0");
 
// list all supported formats
console.log(cam.formats);

我的摄像头只支持YUYV的:

v4l2 camera configuration

了解一下YUYV格式的数据排布:

YUYV

要做条形码识别,只需要提取所有Y的数据。

定制Node.js插件

SDK是C++实现的,因此需要做一个Node.js插件。

首先需要一个配置文件binding.gyp。设置一下头文件和库文件的路径:

{
  "targets": [
    {
      'target_name': "dbr",
      'sources': [ "dbr.cc" ],
      'conditions': [
          ['OS=="linux"', {
            'defines': [
              'LINUX_DBR',
            ],
            'include_dirs': [
                "/home/pi/dbr-V4.2.0-linux-armv7l/include"
            ],
            'libraries': [
                "-lDynamsoftBarcodeReader", "-L/home/pi/dbr-V4.2.0-linux-armv7l/lib"
            ]
          }]
      ]
    }
  ]
}

创建C++文件。提取Y值并转换成条形码API需要的数据格式:

bool ConvertCameraGrayDataToDIBBuffer(unsigned char* psrc, int size, int width, int height, unsigned char** ppdist, int *psize)
{
    BITMAPINFOHEADER bitmapInfo;
    memset(&bitmapInfo, 0, sizeof(BITMAPINFOHEADER));
 
    bitmapInfo.biBitCount = 8;
    bitmapInfo.biWidth = width;
    bitmapInfo.biHeight = height;
    bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
 
    int iStride = ((width * 8 + 31) >> 5) << 2;
    int iImageSize = iStride * height;
    if (size < iImageSize)
        return false;
 
    bitmapInfo.biSizeImage = iImageSize;
 
    *psize = iImageSize + bitmapInfo.biSize + 1024;
    *ppdist = new unsigned char[*psize];
 
    //1. copy BITMAPINFOHEADER
    memcpy(*ppdist, &bitmapInfo, sizeof(BITMAPINFOHEADER));
 
    //2. copy gray color map
    char rgba[1024] = { 0 };
    for (int i = 0; i < 256; ++i)
    {
        rgba[i * 4] = rgba[i * 4 + 1] = rgba[i * 4 + 2] = rgba[i * 4 + 3] = i;
    }
    memcpy(*ppdist + sizeof(BITMAPINFOHEADER), rgba, 1024);
 
    //3. copy gray data (should be fliped)
    unsigned char* srcptr = psrc + (height - 1)*width;
    unsigned char* dstptr = *ppdist + sizeof(BITMAPINFOHEADER) + 1024;
 
    for (int j = 0; j < height; ++j, srcptr -= width, dstptr += iStride)
    {
        memcpy(dstptr, srcptr, width);
    }
 
    return true;
}
 
unsigned char* pdibdata = NULL;
int dibsize = 0;
int width = worker->width, height = worker->height;
int size = width * height;
int index = 0;
unsigned char* data = new unsigned char[size];
// get Y from YUYV
for (int i = 0; i < size; i++)
{
    data[i] = worker->buffer[index];
    index += 2;
}
// gray conversion
ConvertCameraGrayDataToDIBBuffer(data, size, width, height, &pdibdata, &dibsize);
// read barcode
ret = DBR_DecodeBuffer(pdibdata, dibsize, &ro, &pResults);
// release memory
delete []data, data=NULL;
delete []pdibdata, pdibdata=NULL;

编译插件:

node-gyp configure
node-gyp build

引入插件:

var dbr = require('./build/Release/dbr');

使用setTimeout不断获取帧数据用于条形码检测:

cam.start();
 
function capture() {
    cam.capture(function(success) {
        var frame = cam.frameRaw();
 
        dbr.decodeYUYVAsync(frame, format.width, format.height, barcodeTypes,
            function(msg) {
                var result = null;
                for (index in msg) {
                    result = msg[index]
                    console.log("Format: " + result['format']);
                    console.log("Value : " + result['value']);
                    console.log("##################");
                }
                setTimeout(capture, 0);
            });
    });
}
 
setTimeout(capture, 0);

运行创建的camera_barcode_reader.js

node.js barcode scanner for raspberry pi

源码

https://github.com/dynamsoftlabs/raspberry-pi-nodejs-barcode-reader-

Logo

更多推荐