分享一个识别二维码可在单片机上运行的库---zbar
内存消耗比较多,建议外扩ram使用
大致步骤:
1.使用摄像头获取一帧RGB图像,不是拍照,就是RGB数据流
2.将RGB图像转为8位灰度图像
3.调用zbar库,直接拿结果
我在H7上实测,zbar解码240x240的二维码,需要约80KB的内存,加上RGB图像240x240x2=112.5KB,大致需要接近200KB了
-------------------------------------------------------------------------------------
下图是在STM32H743@480MHz - 240x240下得到的时间消耗
从RGB图像转灰度图像,约4ms
zbar库解析不到二维码时,约32ms
zbar库解析出二维码时,约44ms
-------------------------------------------------------------------------------------
下图是在STM32F407@168MHz - 240x240下得到的时间消耗
从RGB图像转灰度图像,约13ms
zbar库解析不到二维码时,约260ms
zbar库解析出二维码时,约370ms
(无法上传图片了.....)
-------------------------------------------------------------------------------------
zbar源码
qrcode-源码.zip
(279.7 KB, 下载次数: 2)
-------------------------------------------------------------------------------------
灰度转换
[C] 纯文本查看 复制代码 /*
************************************************************
* 函数名称: IA_Image_Gray_Light
*
* 函数功能: 灰度处理
*
* 入口参数: rgb565:源数据
* size:源数据项数
* gray:灰度缓存
*
* 返回参数: 0-成功 1-失败
*
* 说明: 亮度法
* 公式:Gray = 0.299*R + 0.587*G + 0.116*B
* 使用整数运算代替浮点:系数放大256倍(0.299 → 77)
************************************************************
*/
uint8_t IA_Image_Gray_Light(uint16_t *rgb565, uint32_t size, uint8_t *gray)
{
if((rgb565 == (void *)0) || (size == 0) || (gray == (void *)0)) return 1;
for(uint8_t r = 0, g = 0, b = 0; size--; rgb565++, gray++)
{
r = (*rgb565 >> 11) & 0x1F;
g = (*rgb565 >> 5) & 0x3F;
b = *rgb565 & 0x1F;
*gray = (r * 77 + g * 150 + b * 29) >> 8;
}
return 0;
}
/*
************************************************************
* 函数名称: IA_Image_Gray_Light_Table
*
* 函数功能: 灰度处理
*
* 入口参数: rgb565:源数据
* size:源数据项数
* gray:灰度缓存
*
* 返回参数: 0-成功 1-失败
*
* 说明: 亮度法
* 公式:Gray = 0.299*R + 0.587*G + 0.116*B
* 使用整数运算代替浮点:系数放大256倍(0.299 → 77)
************************************************************
*/
uint8_t IA_Image_Gray_Light_Table(uint16_t *rgb565, uint32_t size, uint8_t *gray)
{
#if(IA_RGB_2_GRAY_TABLE == 1)
if((rgb565 == (void *)0) || (size == 0) || (gray == (void *)0)) return 1;
if(rgb_2_gray_table == (void *)0)
{
rgb_2_gray_table = HM_Malloc(HM_TYPE_EXTRAM_1, 65536);
if(rgb_2_gray_table == (void *)0) return 1;
for(uint32_t i = 0; i < 65536; i++)
{
uint8_t r = (i >> 11) & 0x1F;
uint8_t g = (i >> 5) & 0x3F;
uint8_t b = i & 0x1F;
rgb_2_gray_table[i] = (r * 77 + g * 150 + b * 29) >> 8;
}
}
for(; size--;)
{
*gray++ = rgb_2_gray_table[*rgb565++];
}
return 0;
#else
return 1;
#endif
}
-------------------------------------------------------------------------------------
修改zbar_config.c里边的函数即可,就是动态内存,内存操作之类的,然后解码流程我也封装好放在zbar_config.c里边了,网上下载的移植好的源码没有zbar_decode函数
解码流程
[C] 纯文本查看 复制代码 unsigned char zbar_decode(unsigned short width, unsigned short heigh, unsigned char *gray, unsigned short *type, char *result)
{
unsigned char ret = 1;
zbar_image_scanner_t *scanner = NULL;
scanner = zbar_image_scanner_create();
zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_ENABLE, 1);
zbar_image_t *image = zbar_image_create();
zbar_image_set_format(image, *(int*)"Y800");
zbar_image_set_size(image, width, heigh);
zbar_image_set_data(image, gray, width * heigh, zbar_image_free_data);
if(zbar_scan_image(scanner, image) != 0)
{
const zbar_symbol_t *symbol = zbar_image_first_symbol(image);
for(; symbol; symbol = zbar_symbol_next(symbol))
{
zbar_symbol_type_t typ = zbar_symbol_get_type(symbol);
const char *data = zbar_symbol_get_data(symbol);
if(type != NULL) *type = typ;
if(result != NULL)
{
unsigned short len = strlen(data);
memcpy(result, data, len);
result[len] = 0;
}
ret = 0;
}
}
zbar_image_destroy(image);
zbar_image_scanner_destroy(scanner);
return ret;
}
|