通常,在进行条形码检测时,我们会将以RGB或YUV编码的彩色图像传递给一些条形码解码API,其中图像数据将从彩色转换为灰度,然后从灰度转换为二进制。操作像素会占用大量CPU时间。为了加速图像处理,我们可以利用GPU。Dynamsoft JavaScript条码SDK具有强大的功能,可用于开发Web条码扫描应用程序,但到目前为止,它仅适用于CPU。在本文中,我将向您展示如何使用WebGL将彩色图像转换为灰度图像,以减少从Web应用程序中的摄像头视频流读取条形码时的总CPU时间成本。
在5分钟内构建Web条形码扫描应用程序
Dynamsoft JavaScript条形码SDK可在npmjs.com上获得:
https://www.npmjs.com/package/dynamsoft-javascript-barcode
“ hello world”示例非常简单:
运行代码时,您可以在开发人员控制台中查看相机视图并检查条形码读取结果。该BarcodeScanner类所做的一切都是为了你。另外,您可以从视频元素中手动读取图像数据,并使用BarcodeReader类以编程方式调用encodeBuffer()方法:
var barcodereader = null;
(async()=>{
barcodereader = await Dynamsoft.BarcodeReader.createInstance();
await barcodereader.updateRuntimeSettings(‘speed’);
let settings = await barcodereader.getRuntimeSettings();
settings.deblurLevel = 0;
barcodereader.updateRuntimeSettings(settings);
})();
let canvas2d = document.createElement(‘canvas’);
canvas2d.width = width;
canvas2d.height = height;
var ctx2d = canvas2d.getContext(‘2d’);
ctx2d.drawImage(videoElement, 0, 0, width, height);
buffer = ctx2d.getImageData(0, 0, width, height).data;
if (barcodereader){
barcodereader
.decodeBuffer(
buffer,
width,
height,
width * 4,
Dynamsoft.EnumImagePixelFormat.IPF_ARGB_8888
)
.then((results) => {
showResults(results);
});
}
使用WebGL将视频色框转换为灰度图像
从理论上讲,相同尺寸的灰度图像的处理速度要快于彩色图像,因为彩色图像有4个通道,而灰度图像只有1个通道。如果缓冲区是灰度图像,则可以如下更改上面的代码:
barcodereader
.decodeBuffer(
gray,
width,
height,
width,
Dynamsoft.EnumImagePixelFormat.IPF_GrayScaled
)
.then((results) => {
showResults(results);
});
下一个问题是如何使用WebGL获取灰度图像缓冲区?我发现一个名为WebGLFundamentals的网站 对于学习WebGL很方便。
首先,我创建了一个着色器程序以将颜色转换为灰度:
接下来,我使用在线教程提供的draw()函数将视频元素绑定到WebGL纹理:
var drawInfo = {
x: 0,
y: 0,
dx: 1,
dy: 1,
textureInfo: loadImageAndCreateTextureInfo(videoElement)
};
draw(drawInfo);
然后,我将图像数据读取到Uint8Array:
buffer = new Uint8Array(width * height * 4);
gl.readPixels(
0,
0,
gl.drawingBufferWidth,
gl.drawingBufferHeight,
gl.RGBA,
gl.UNSIGNED_BYTE,
buffer
);
有趣的是输出图像是颠倒的。要沿其垂直轴翻转图像数据,可以调用gl.pixelStorei():
function drawImage(tex, texWidth, texHeight, dstX, dstY) {
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
最后,从缓冲区中提取灰度数据:
gray = new Uint8Array(width * height);
let gray_index = 0;
for (i = 0; i < width * height * 4; i += 4) { gray[gray_index++] = buffer[i]; }
这是在我的网络浏览器中运行该应用程序的屏幕截图。
Dynamic Web TWAIN教程:如何使用WebGL加快Web条形码的解码速度
条形码解码性能比较:灰度图像与彩色图像
要衡量性能差异,我们可以使用以下公式:
total time = image data obtaining time + barcode decoding time
我对640×480视频流进行了简单测试。
Dynamic Web TWAIN教程:如何使用WebGL加快Web条形码的解码速度
如您所见,在我的PC上从WebGL(灰度图像)获取图像数据的时间成本比从画布(彩色图像)获取图像数据的时间成本大约慢5倍,因为GPU数据传输需要时间。但是,使用WebGL进行条形码解码的总CPU时间成本较低。