ZBar是一種流行的二維碼掃描和解碼工具,它在嵌入式系統中擁有廣泛的應用。在嵌入式系統中,我們面臨著有限的資源和更嚴格的性能要求,因此,選擇適當的庫來完成特定的任務非常重要。 ZBar適用於各種嵌入式平臺,包括ARM、x86和MIPS等處理器架構。它可以輕鬆地整合到各種嵌入式系統中,如智能家居設備、 ...
ZBar是一種流行的二維碼掃描和解碼工具,它在嵌入式系統中擁有廣泛的應用。在嵌入式系統中,我們面臨著有限的資源和更嚴格的性能要求,因此,選擇適當的庫來完成特定的任務非常重要。
ZBar適用於各種嵌入式平臺,包括ARM、x86和MIPS等處理器架構。它可以輕鬆地整合到各種嵌入式系統中,如智能家居設備、智能手機、平板電腦、遠程式控制制設備、工業控制器等。
ZBar使用C/C++編寫,具有高度優化的演算法,能夠快速準確地讀取各種二維碼和條形碼,包括QR碼、Data Matrix碼、PDF417碼、EAN-13碼等等。同時,ZBar還支持自定義解碼器,開發者可以根據自己的需求配置掃描器以實現更好的解碼效果。
ZBar還具有非常靈活的API,可用於C/C++、Python、Java、Ruby等語言,開發人員可以根據自己的需求靈活選擇相應的API。此外,ZBar還支持多種操作系統和平臺,包括Linux、Windows、Mac OS X等。
總之,ZBar是一種非常有用的嵌入式二維碼和條形碼掃描庫,它提供了高效的解碼演算法、可定製的解碼器和靈活的API,能夠輕鬆地滿足嵌入式設備的掃描和解碼需求。
這裡感謝之前大佬移植zbar庫到stm32,具體鏈接如下:https://www.cnblogs.com/greyorbit/p/8456814.html
移植步驟也很簡單,按照博文把對應文件和頭文件路徑加入到工程中,然後使用圖片數組轉成灰度數據,在調用zbar既可以識別。
不過移植後會有一個問題,不能重覆調用識別二維碼,很容易記憶體就崩了。為瞭解決這個問題,讓這個zbar庫可以真正的用起來,不得不找到問題所在。
這裡直觀的看就是記憶體問題,奈何如果從源碼直接去查找malloc和free的匹配所需時間太大,只能動態調試查找原因,所以第一步,我移植了rt-thread系統,使用rt的記憶體管理api。
移植rt-thread很方便,現在stm32代碼生成工具cubemx可以直接添加rt-thread庫,所以移植rt-thread系統很快。具體如下圖:
移植完rt-thread後,就需要把zbar庫中用到的malloc、calloc、free等操作函數換成 rt-malloc、rt-calloc、rt-free等,直接用全局搜索和替換。
替換後打開rt的記憶體調試功能巨集定義:在rtdebug.h文件中
更改後既可以看到列印記憶體申請和釋放日誌,以下為日誌列印內容
malloc size 156 allocate memory at 0x2001008c, size: 168 malloc size 296 allocate memory at 0x20010134, size: 308 malloc size 32 allocate memory at 0x20010268, size: 44 malloc size 48 allocate memory at 0x20010294, size: 60 malloc size 2856 allocate memory at 0x200102d0, size: 2868 malloc size 52 allocate memory at 0x20010e04, size: 64 allocate memory at 0x20010e04, size: 64 malloc size 16 allocate memory at 0x20010e44, size: 28 malloc size 20 allocate memory at 0x20011388, size: 32 malloc size 60 allocate memory at 0x200113a8, size: 72 release memory 0x20011388, size: 32 malloc size 140 allocate memory at 0x200113f0, size: 152 release memory 0x200113a8, size: 72 malloc size 300 allocate memory at 0x20011488, size: 312 release memory 0x200113f0, size: 152 malloc size 620 allocate memory at 0x200115c0, size: 632 release memory 0x20011488, size: 312 malloc size 1260 allocate memory at 0x20011838, size: 1272 release memory 0x200115c0, size: 632 malloc size 2540 allocate memory at 0x20011d30, size: 2552 release memory 0x20011838, size: 1272 malloc size 20 allocate memory at 0x20011388, size: 32 malloc size 60 allocate memory at 0x200113a8, size: 72 release memory 0x20011388, size: 32 malloc size 140 allocate memory at 0x200113f0, size: 152 release memory 0x200113a8, size: 72 malloc size 300 allocate memory at 0x20011488, size: 312 release memory 0x200113f0, size: 152 malloc size 620 allocate memory at 0x200115c0, size: 632 release memory 0x20011488, size: 312 malloc size 1260 allocate memory at 0x20011838, size: 1272 release memory 0x200115c0, size: 632 malloc size 2540 allocate memory at 0x20012728, size: 2552 release memory 0x20011838, size: 1272 malloc size 352 allocate memory at 0x20011388, size: 364 malloc size 352 allocate memory at 0x200114f4, size: 364 malloc size 88 allocate memory at 0x20011660, size: 100 release memory 0x20011660, size: 100 malloc size 440 allocate memory at 0x20011660, size: 452 malloc size 440 allocate memory at 0x20011824, size: 452 malloc size 110, but align to 112 allocate memory at 0x200119e8, size: 124 release memory 0x200119e8, size: 124 malloc size 5792 allocate memory at 0x20013120, size: 5804 malloc size 80 allocate memory at 0x200119e8, size: 92 malloc size 20 allocate memory at 0x20011a44, size: 32 malloc size 32 allocate memory at 0x20011a64, size: 44 malloc size 5, but align to 8 allocate memory at 0x20011a90, size: 24 malloc size 8 allocate memory at 0x20011aa8, size: 24 release memory 0x20011aa8, size: 24 release memory 0x20011a90, size: 24 release memory 0x20011a64, size: 44 release memory 0x20011a44, size: 32 release memory 0x20011824, size: 452 release memory 0x20011660, size: 452 release memory 0x200114f4, size: 364 release memory 0x20011388, size: 364 malloc size 57600 allocate memory at 0x200147cc, size: 57612 malloc size 960 allocate memory at 0x20011388, size: 972 release memory 0x20011388, size: 972 malloc size 3, but align to 4 allocate memory at 0x20011388, size: 24 malloc size 360 allocate memory at 0x200113a0, size: 372 release memory 0x200113a0, size: 372 malloc size 360 allocate memory at 0x200113a0, size: 372 release memory 0x200113a0, size: 372 malloc size 176 allocate memory at 0x200113a0, size: 188 release memory 0x200113a0, size: 188 malloc size 176 allocate memory at 0x200113a0, size: 188 release memory 0x200113a0, size: 188 malloc size 552 allocate memory at 0x200113a0, size: 564 malloc size 552 allocate memory at 0x200115d4, size: 564 release memory 0x200113a0, size: 564 release memory 0x200115d4, size: 564 malloc size 52 allocate memory at 0x200113a0, size: 64 allocate memory at 0x200113a0, size: 64 malloc size 116 allocate memory at 0x200113e0, size: 128 malloc size 32 allocate memory at 0x20011460, size: 44 malloc size 32 allocate memory at 0x2001148c, size: 44 release memory 0x20011460, size: 44 release memory 0x2001148c, size: 44 malloc size 116 allocate memory at 0x20011460, size: 128 malloc size 8 allocate memory at 0x200114e0, size: 24 malloc size 70, but align to 72 allocate memory at 0x200114f8, size: 84 release memory 0x200113e0, size: 128 release memory 0x200113a0, size: 64 release memory 0x200114e0, size: 24 release memory 0x20011460, size: 128 malloc size 12 allocate memory at 0x200113a0, size: 24 malloc size 15, but align to 16 allocate memory at 0x200113b8, size: 28 release memory 0x200114f8, size: 84 malloc size 48 allocate memory at 0x200113d4, size: 60 release memory 0x20011388, size: 24 malloc size 4 allocate memory at 0x20011388, size: 24 malloc size 1, but align to 4 allocate memory at 0x20011410, size: 24 malloc size 31, but align to 32 allocate memory at 0x20011428, size: 44 malloc size 52 allocate memory at 0x20011454, size: 64 allocate memory at 0x20011454, size: 64 malloc size 8 allocate memory at 0x20011494, size: 24 malloc size 16 allocate memory at 0x200114ac, size: 28 release memory 0x20011494, size: 24 malloc size 24 allocate memory at 0x200114c8, size: 36 release memory 0x200114ac, size: 28 malloc size 32 allocate memory at 0x20011494, size: 52 release memory 0x200114c8, size: 36 malloc size 16 allocate memory at 0x200114c8, size: 28 release memory 0x20011428, size: 44 release memory 0x20011410, size: 24 release memory 0x200113b8, size: 28 release memory 0x200113a0, size: 24 release memory 0x200113d4, size: 60 release memory 0x200147cc, size: 57612 release memory 0x200119e8, size: 92 release memory 0x20013120, size: 5804 n = 1 decoded QR-Code symbol "EEWorld STM32H5" len = 15 release memory 0x20010e04, size: 64 release memory 0x20011494, size: 52 release memory 0x200114c8, size: 28 release memory 0x20011454, size: 64 release memory 0x20010e44, size: 28 release memory 0x20010294, size: 60 release memory 0x20010268, size: 44 release memory 0x20010134, size: 308 release memory 0x20011d30, size: 2552 release memory 0x20012728, size: 2552 release memory 0x200102d0, size: 2868 release memory 0x2001008c, size: 168 45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok zbar count;56
通過對申請和釋放的對應關係,我們可以分析得出問題所在,zbar庫在圖片識別後釋放了img->data指針,而這個指針是在zbar調用外部申請的空間,是不需要zbar內部釋放的,具體代碼如下:
int main(void) { /* USER CODE BEGIN 1 */ uint8_t test[]="start test\n"; uint16_t i,j; int qr_img_width = 240; uint16_t Color; uint16_t cnt = 0; unsigned char *pic_rgb = (unsigned char *)gImage_test; unsigned char *pic_hd = NULL; unsigned char *pic_data = NULL; void * ptr_start; /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ //HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ //SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_ADC1_Init(); MX_ETH_Init(); MX_ICACHE_Init(); MX_LPUART1_UART_Init(); //MX_USART3_UART_Init(); MX_UCPD1_Init(); MX_USB_PCD_Init(); /* USER CODE BEGIN 2 */ pic_data = rt_malloc(qr_img_width*qr_img_width); if(pic_data == NULL) { printf("malloc error\n"); return 0; } else { printf("pic_data:0x%x\n",pic_data); } //memset(pic_data,0,qr_img_width*qr_img_width); pic_hd = pic_data; for(i=0;i<qr_img_width;i++) { for(j=0;j<qr_img_width;j++) //將RGB565圖片轉成灰度 { Color = (*pic_rgb) | (*(pic_rgb+1)<<8); *pic_hd = (((Color&0xF800)>> 8)*77+((Color&0x7E0)>>3)*150+((Color&0x001F)<<3)*29)/256; pic_hd++; pic_rgb++; pic_rgb++; } } /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if( Zbar_Test((void* )pic_data,qr_img_width,qr_img_width) == 0 ) { printf("zbar failed \n"); //rt_free(pic_data); } else { cnt ++; printf("zbar ok \n"); //rt_free(pic_data); } printf("zbar count;%d\n",cnt); //list_thread(); rt_thread_mdelay(5000); } rt_free(pic_data); /* USER CODE END 3 */ }
即pic_data灰度圖片數據是不需要zbar釋放的,但是zbar庫中做了釋放操作,代碼如下:
inline void zbar_image_rt_free_data (zbar_image_t *img) { if(!img) return; if(img->src) { /* replace video image w/new copy */ assert(img->refcnt); /* FIXME needs lock */ zbar_image_t *newimg = zbar_image_create(); memcpy(newimg, img, sizeof(zbar_image_t)); /* recycle video image */ newimg->cleanup(newimg); /* detach old image from src */ img->cleanup = NULL; img->src = NULL; img->srcidx = -1; } else if(img->cleanup && img->data) { if(img->cleanup != zbar_image_rt_free_data) { /* using function address to detect this case is a bad idea; * windows link libraries add an extra layer of indirection... * this works around that problem (bug #2796277) */ zbar_image_cleanup_handler_t *cleanup = img->cleanup; img->cleanup = zbar_image_rt_free_data; cleanup(img); } //傳入圖片為外部指針,zbar內部不用free此指針 // else // rt_free((void*)img->data); } img->data = NULL; }
這裡把這一句屏蔽,則可以解決問題,經過我測試,現在已經連續運行上千次
decoded QR-Code symbol "EEWorld STM32H5" len = 15 45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok zbar count;4290 n = 1 decoded QR-Code symbol "EEWorld STM32H5" len = 15 45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok zbar count;4291 n = 1 decoded QR-Code symbol "EEWorld STM32H5" len = 15 45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok zbar count;4292 n = 1 decoded QR-Code symbol "EEWorld STM32H5" len = 15 45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok zbar count;4293 n = 1 decoded QR-Code symbol "EEWorld STM32H5" len = 15 45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok zbar count;4294
工程文件下載:http://bbs.eeworld.com.cn/thread-1244434-1-1.html