Fork me on GitHub

成功在 stm32 上用 Zbar 库识别二维码!

目前能在网上找到的二维码资料,都是编码居多,也就是从一串字符串生成二维码(常用算法如 QRCode),而解码识别方面的参考教程比较少。二维码解码库有 Quirc、Zbar 等,更多的开发者是用在安卓、OpenCV 和 Python 等高级环境上,对于 MCU 级别的使用,并且基本是经过封装后的实现,灵活性较差。于是便想着自己从头使用 Zbar 库的接口,实现图片中的二维码检测及识别。
测试环境
  • 开发板:STM32F429I Disco
  • CPU:Arm® 32-bit Cortex®-M4 180 MHz
  • 内存:2Mbytes Flash, 256KMbytes RAM, 64-Mbit 外部 SDRAM
  • 软件:RT-Thread 操作系统
实现过程
        这里说明一下,Zbar 库要求输入的是灰度图像数据(也就是黑白照),每个像素用一个字节表示灰度,从 0x00 全白到 0xff 全黑,有了图像数据,再传入图像的宽高便能解码了。
通过 Zbar 库识别二维码,大致可以分为下面 3 个过程:
  • 创建配置 image_scanner、zbar_image 对象,并设置图像信息
  • 扫描图像并识别
  • 提取解码结果
        我写了一个函数,能够直接读取 bmp 8 位灰度图片(因为 bmp 文件包含了图像数据便于处理),并打印输出其中的二维码识别结果:

  1. #include <rtthread.h>
  2. #include <rtdevice.h>
  3. #include "zbar.h"
  4. #define BITMAP_IMG_OFFSET               0x0A
  5. #define BITMAP_IMG_WIDTH_OFFSET         0x12
  6. #define BITMAP_IMG_HEIGHT_OFFSET        0x16
  7. #define BITMAP_IMG_FILE_SIZE_OFFSET     0x02
  8. zbar_image_scanner_t *rt_scanner = NULL;
  9. void qr_bitmap_decoder(const rt_uint8_t *img_buffer)
  10. {
  11.     /* create a reader */
  12.     rt_scanner = zbar_image_scanner_create();
  13.     /* configure the reader */
  14.     zbar_image_scanner_set_config(rt_scanner, 0, ZBAR_CFG_ENABLE, 1);
  15.     /* obtain image data */
  16.     void *raw = (void *)img_buffer;
  17.     int img_width = *(int *)(&img_buffer[BITMAP_IMG_WIDTH_OFFSET]);
  18.     int img_height = *(int *)(&img_buffer[BITMAP_IMG_HEIGHT_OFFSET]);
  19.     int img_offset = *(int *)(&img_buffer[BITMAP_IMG_OFFSET]);
  20.     int file_size = *(int *)(&img_buffer[BITMAP_IMG_FILE_SIZE_OFFSET]);
  21.     rt_kprintf("img_info: width=%d, height=%d, file_size=%d\n", img_width, img_height, file_size);
  22.     /* wrap image data */
  23.     zbar_image_t *image = zbar_image_create();
  24.     zbar_image_set_format(image, *(int*)"Y800");
  25.     zbar_image_set_size(image, img_width, img_height);
  26.     zbar_image_set_data(image, (void *)(&img_buffer[img_offset]), img_width * img_height, zbar_image_free_data);
  27.     /* scan the image for barcodes */
  28.     int n = zbar_scan_image(rt_scanner, image);
  29.     /* extract results */
  30.     const zbar_symbol_t *symbol = zbar_image_first_symbol(image);
  31.     for(; symbol; symbol = zbar_symbol_next(symbol)) {
  32.         /* do something useful with results */
  33.         zbar_symbol_type_t typ = zbar_symbol_get_type(symbol);
  34.         const char *data = zbar_symbol_get_data(symbol);
  35.         rt_kprintf("decoded %s symbol "%s"\n",
  36.                zbar_get_symbol_name(typ), data);
  37.     }
  38.     /* clean up */
  39.     zbar_image_destroy(image);
  40.     zbar_image_scanner_destroy(rt_scanner);
  41. }
复制代码



运行结果
        来看下实测的识别效果,RT-Thread 提供了 finsh Shell,可以很方便地使用命令行的方式运行写好的测试例程:
样本1(图片尺寸 256*256,纯二维码):
样本2(图片尺寸 480*360,摄像头拍摄):
转自:https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=621053&highlight=Zbar
posted @ 2023-03-29 17:30  _浮尘  阅读(1479)  评论(0)    收藏  举报