你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
国际哥不是国际歌 发布时间:2019-6-29 11:07
       目前能在网上找到的二维码资料,都是编码居多,也就是从一串字符串生成二维码(常用算法如 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 操作系统
    . L+ z4 @- D. c2 `. L9 d
实现过程
        这里说明一下,Zbar 库要求输入的是灰度图像数据(也就是黑白照),每个像素用一个字节表示灰度,从 0x00 全白到 0xff 全黑,有了图像数据,再传入图像的宽高便能解码了。
通过 Zbar 库识别二维码,大致可以分为下面 3 个过程:
  • 创建配置 image_scanner、zbar_image 对象,并设置图像信息
  • 扫描图像并识别
  • 提取解码结果+ x: x8 K1 |! C, U' j6 E! @+ ~
        我写了一个函数,能够直接读取 bmp 8 位灰度图片(因为 bmp 文件包含了图像数据便于处理),并打印输出其中的二维码识别结果:
  _. h2 D' n0 ~2 f$ r, E# W7 M
  1. #include <rtthread.h>
    " t% x" }! C3 _; g% P
  2. #include <rtdevice.h>- A: d1 o5 C, m1 v/ k7 `. A

  3. " j+ ]: w- Y# G0 t
  4. #include "zbar.h"
    & G1 P0 q9 y& j- ]

  5. 1 C' U3 e0 e; j2 K6 M8 ^! O& P. T
  6. #define BITMAP_IMG_OFFSET               0x0A* }- ]! U. E# w
  7. #define BITMAP_IMG_WIDTH_OFFSET         0x126 l, p5 |3 X; o3 t; G- C
  8. #define BITMAP_IMG_HEIGHT_OFFSET        0x16
    8 ?0 j; k' m# t) N
  9. #define BITMAP_IMG_FILE_SIZE_OFFSET     0x02
    . [( P2 _, j- u$ }8 \/ b& E

  10. & B8 s3 h! p( Q( b/ X
  11. zbar_image_scanner_t *rt_scanner = NULL;5 r* t3 B( X: l+ }
  12. 7 M) V9 Y& \; \$ w, {. ]- f
  13. void qr_bitmap_decoder(const rt_uint8_t *img_buffer)
    1 h& t- b7 c9 U' u
  14. {0 i/ A8 O2 ^* S6 o$ M9 ^
  15.     /* create a reader */
    8 T, |7 b4 t4 ?% S, t9 B3 j, T
  16.     rt_scanner = zbar_image_scanner_create();
    * O" [3 t( X6 s+ [/ G

  17. $ x, ]& ^: R& B* b/ ?4 d- g6 S
  18.     /* configure the reader */9 h0 H- }2 X( [' y9 H- ^( r2 a# p8 z) q
  19.     zbar_image_scanner_set_config(rt_scanner, 0, ZBAR_CFG_ENABLE, 1);3 H3 w' ~, \1 k5 k9 f0 U
  20. ( l' |' b1 Q2 p, G- l3 M: A1 V
  21.     /* obtain image data */7 O' |: ^. x$ r& F- z
  22.     void *raw = (void *)img_buffer;
      o( D$ ^' j: o/ b. W7 _% U# G

  23. " P1 H' }+ v& x
  24.     int img_width = *(int *)(&img_buffer[BITMAP_IMG_WIDTH_OFFSET]);- L# F! I' `2 M+ v
  25.     int img_height = *(int *)(&img_buffer[BITMAP_IMG_HEIGHT_OFFSET]);* ]9 _7 i& W/ |
  26.     int img_offset = *(int *)(&img_buffer[BITMAP_IMG_OFFSET]);4 s) V* a( L. u- `) W; X
  27.     int file_size = *(int *)(&img_buffer[BITMAP_IMG_FILE_SIZE_OFFSET]);
    + U% |7 Q# {9 B

  28. ; k- X2 G' B/ v
  29.     rt_kprintf("img_info: width=%d, height=%d, file_size=%d\n", img_width, img_height, file_size);
    : v) w; ~- @; x) p! `

  30.   R/ d5 C+ |8 T  i6 e/ D
  31.     /* wrap image data *// \& O/ [0 B# l! _  \+ C
  32.     zbar_image_t *image = zbar_image_create();+ s2 N9 R* r& h4 X$ D4 l+ S
  33.     zbar_image_set_format(image, *(int*)"Y800");
    0 O8 Q0 i) l" w: M1 u9 e2 y' a0 _
  34.     zbar_image_set_size(image, img_width, img_height);% `0 v: }$ M% n8 [3 {: `0 I
  35.     zbar_image_set_data(image, (void *)(&img_buffer[img_offset]), img_width * img_height, zbar_image_free_data);. {/ [) {+ m& X5 a: _
  36. 3 G) A  D: z" N; Z
  37.     /* scan the image for barcodes */% w: `: A/ L+ }  \# b/ [" W3 H0 s
  38.     int n = zbar_scan_image(rt_scanner, image);
    . t+ G2 p& T0 O4 \2 a# n6 B

  39. 5 _1 m) y! w4 X! ^. N. L
  40.     /* extract results */
    4 P, a& P1 i3 \4 u6 }7 v
  41.     const zbar_symbol_t *symbol = zbar_image_first_symbol(image);
    ( x% G7 t) a9 w) H0 V
  42.     for(; symbol; symbol = zbar_symbol_next(symbol)) {  x7 d3 \0 [! R" F7 w
  43.         /* do something useful with results */7 |* `8 e: {  ^" T: b( p
  44.         zbar_symbol_type_t typ = zbar_symbol_get_type(symbol);
    6 n4 o% u& ]" o. ]1 T; b* i- W) l. M
  45.         const char *data = zbar_symbol_get_data(symbol);
    / ?: b3 }  t6 m+ [+ B
  46.         rt_kprintf("decoded %s symbol "%s"\n",2 [1 z8 l7 U( V# J0 s2 V
  47.                zbar_get_symbol_name(typ), data);
    # T: q# }. O4 w& z' _/ z
  48.     }
    $ Q0 i' C9 I3 j$ k. j
  49. $ F3 b( b8 g: p  `. M( G1 T& Y& D
  50.     /* clean up */
    9 ?( b! Q3 N6 J( v
  51.     zbar_image_destroy(image);
    1 ?% K, j7 |: h- P+ c3 O) r/ D
  52.     zbar_image_scanner_destroy(rt_scanner);$ e4 B. V! o3 ], L
  53. }
复制代码

5 ~' P: {7 K9 T; u6 E+ B* c& p# u2 N, h( M" ?+ O
7 G+ n2 d# A8 @2 O
运行结果
        来看下实测的识别效果,RT-Thread 提供了 finsh Shell,可以很方便地使用命令行的方式运行写好的测试例程:
样本1(图片尺寸 256*256,纯二维码):
样本2(图片尺寸 480*360,摄像头拍摄):
赞 1 收藏 3 评论6 发布时间:2019-6-29 11:07

举报

6个回答
lwg8458 回答时间:2019-6-29 11:24:25
强!!!!!
STMWoodData 回答时间:2019-6-29 11:27:37
提示: 作者被禁止或删除 内容自动屏蔽
andey 回答时间:2019-6-29 14:09:52
提示: 作者被禁止或删除 内容自动屏蔽
TLLED 回答时间:2019-6-30 07:44:26
厉害8 q6 S* `% d& I/ ?% v6 R' U
搞个大新闻 回答时间:2019-6-30 15:14:00
赞一个,谢谢分享
yipan 回答时间:2020-9-24 22:19:18
大神您好,能否帮忙把您用来做测试的灰度图发到我的邮箱 ypan@senecasense.com' i2 J5 A8 [& q+ y. K% F& W; {
我移植zbar到arm上,找不到啥问题但就是扫不到码zbar_scan_image始终返回08 O' n6 S/ q' J$ ]4 n% [& p

: t- R6 H# Z2 j谢谢
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版