java彩色图转灰度图,WebGL彩图转灰度图,提升Web条形码识别性能

图像识别算法通常都要把彩图,转成灰度图,再转成二值图。如果把图像处理部分放到GPU上,就可以减少CPU的时间消耗。这篇文章分享下用WebGL把摄像头传入的彩图转成灰度图,以此提高Web条形码SDK的解码性能。

Web条形码识别

使用Dynamsoft JavaScript Barcode SDK(https://www.npmjs.com/package/dynamsoft-javascript-barcode) 可以快速实现一个Web条码扫描App。比如下面的代码,可以直接创建一个带webcam的扫码app:

let scanner = null;

(async()=>{

scanner = await Dynamsoft.BarcodeScanner.createInstance();

scanner.onFrameRead = results => {console.log(results);};

scanner.onUnduplicatedRead = (txt, result) => {alert(txt);};

await scanner.show();

})();

这里的BarcodeScanner类对camera做了封装,用户不需要手写摄像头相关代码,传入接口的图像是彩图。如果是自己通过canvas来实现,就需要使用BarcodeReader类,然后调用decodeBuffer()接口:

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彩图转灰度图

灰度图是单通道,而彩图是四通道,所以理论上传入灰度图的解码速度要比彩图快。根据上面的解码代码,如果是灰度图,可以改成:

barcodereader

.decodeBuffer(

gray,

width,

height,

width,

Dynamsoft.EnumImagePixelFormat.IPF_GrayScaled

)

.then((results) => {

showResults(results);

});

根据网站的示例代码,修改shader来实现灰度转换:

precision mediump float;

varying vec2 v_texcoord;

uniform sampler2D u_texture;

uniform float u_colorFactor;

void main() {

vec4 sample = texture2D(u_texture, v_texcoord);

float grey = 0.21 * sample.r + 0.71 * sample.g + 0.07 * sample.b;

gl_FragColor = vec4(sample.r * u_colorFactor + grey * (1.0 - u_colorFactor), sample.g * u_colorFactor + grey * (1.0 - u_colorFactor), sample.b * u_colorFactor + grey * (1.0 - u_colorFactor), 1.0);

}

接下来就是通过视频元素来创建绘制纹理:

var drawInfo = {

x: 0,

y: 0,

dx: 1,

dy: 1,

textureInfo: loadImageAndCreateTextureInfo(videoElement)

};

draw(drawInfo);

通过纹理显示,会发现图像是颠倒的,所以需要调用pixelStorei做Y轴翻转:

function drawImage(tex, texWidth, texHeight, dstX, dstY) {

gl.bindTexture(gl.TEXTURE_2D, tex);

gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

从纹理中获取灰度图的数据:

buffer = new Uint8Array(width * height * 4);

gl.readPixels(

0,

0,

gl.drawingBufferWidth,

gl.drawingBufferHeight,

gl.RGBA,

gl.UNSIGNED_BYTE,

buffer

);

这里创建的依然是4通道数据,因为不支持单通道数据读取。获取数据之后,要把灰度数据从数组中提取出来:

gray = new Uint8Array(width * height);

let gray_index = 0;

for (i = 0; i < width * height * 4; i += 4) {

gray[gray_index++] = buffer[i];

}

最后运行程序,可以看到事实的转换效果:

f69bc7bace678dd12c17eff44d5a6988.png

性能比较

通过console观察发现,使用WebGL之后,数据获取的时间5ms左右,而从canvas获取数据的时间只有1ms。WebGL的数据传输会比较耗时。但是灰度图的解码时间和彩图比要快上不少。所以总时间消耗是减少的。

d8ddae3ad6353867c550bcab2540f8eb.png

视频

源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值