海思3559平台移植二维码解码库zbar
1. 下载并解压 zbar 源码包:
http://zbar.sourceforge.net/download.html
zbar-0.10.tar.bz2
解压缩:
tar -xvjf zbar-0.10.tar.bz2
2. 编译过程
./configure –prefix=/home/lie/3559_V30_KK_SY/references/thirdparty/zbar-0.10/lib_out/ –host=arm-hisiv600-linux –disable-video –without-imagemagick –without-gtk –without-qt –without-python –enable-static
make
make install
其中 /home/lie/3559_V30_KK_SY/references/thirdparty/zbar-0.10/lib_out/ 修改为要生成lib的绝对路径。
-host=arm-hisiv600-linux 指定编译链
3. 生成的库文件
在路径/home/lie/3559_V30_KK_SY/references/thirdparty/zbar-0.10/lib_out/lib下:
libzbar.a
include文件夹下面的头文件:
zbar.h
4. 应用程序添加库文件
将库加入到放库的路径
在Makefile中直接添加
VSS_LIB += -lzbar
5. 调用zbar算法 识别二维码
在代码包里,有个examples的文件夹,
嵌入式平台的调用可以参考scan_image.c
流程图如下
初始化以及参数配置:
zbar_image_scanner_t *scanner = NULL;
zbar_image_t *image= NULL;
int width = 1024, height = 576;
/* create a reader */
scanner = zbar_image_scanner_create();
/* configure the reader */
zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_ENABLE, 1);
/* obtain image data */
image = zbar_image_create();
zbar_image_set_format(image, *(int*)"Y800");
zbar_image_set_size(image, width, height);
上面设置的“Y800”的模式是只需要 YUV图像中的Y分量(灰阶)
从YUV420的数据中只取前面的Y数据即可。
载入图像以及识别的流程,我这里做了一个线程一直去处理,直到识别到二维码退出
static HI_S32 Service_Zbar_Start()
{
void *raw = NULL;
int width = 1024, height = 576;
pthread_detach(pthread_self());
raw = (void*)malloc(width*height);
if(NULL == raw)
{
printf("[Zbar_Start]:malloc memory failed \n");
return -1;
}
while(Zbar_Thread_Start)
{
usleep(100*1000);
if(s_video_valid == HI_FALSE)
continue;
pthread_mutex_lock(&s_video_mutex);
//只复制Y分量的数据内容
memcpy(raw, s_video_frame, width*height);
s_video_valid = HI_FALSE;
pthread_mutex_unlock(&s_video_mutex);
zbar_image_set_data(image, raw, width * height, NULL);
/* scan the image for barcodes */
int n = zbar_scan_image(scanner, image);
if(n==0)
continue;
/* extract results */
const zbar_symbol_t *symbol = zbar_image_first_symbol(image);
for(; symbol; symbol = zbar_symbol_next(symbol))
{
/* do something useful with results */
zbar_symbol_type_t typ = zbar_symbol_get_type(symbol);
const char *data = zbar_symbol_get_data(symbol);
printf("decoded %s symbol \"%s\"\n",
zbar_get_symbol_name(typ), data);
}
break;
}
free(raw);
return HI_SUCCESS;
}
6. 海思平台获取YUV420数据
hisi3559可以直接获取YUV420的数据,
获取到的是数据放在一个buffer中,供zbar的zbar_image_set_data函数使用。
HI_S32 VideoSaveFrame(HI_HANDLE VProcHdl, HI_HANDLE VPortHdl, HI_FRAME_DATA_S* pVPortYUV)
{
char* pFrame = s_video_frame;
char* pVBufVirt_Y;
HI_U32 u32FrameSize = 0;
HI_U8* pUserPageAddr = NULL;
HI_U32 phy_addr;
HI_MPP_PIXEL_FORMAT_E enPixelFormat = pVPortYUV->enPixelFormat;
if(pVPortYUV->enCompressMode != HI_COMPRESS_MODE_NONE)
{
printf("Frame is compressed:%d\n", pVPortYUV->enCompressMode);
return HI_FAILURE;
}
if (HI_MPP_PIXEL_FORMAT_420 == enPixelFormat)
{
u32FrameSize = (pVPortYUV->u32Stride[0]) * (pVPortYUV->u32Height) * 3 / 2;
}
else if(HI_MPP_PIXEL_FORMAT_422 == enPixelFormat)
{
u32FrameSize = (pVPortYUV->u32Stride[0]) * (pVPortYUV->u32Height) * 2;
}
else
{
printf("enPixelFormat error.\n");
return HI_FAILURE;
}
phy_addr = pVPortYUV->u32PhyAddr[0];
pUserPageAddr = (HI_U8*) Video_Mmap(phy_addr, u32FrameSize);
if (HI_NULL == pUserPageAddr)
{
printf("mmap error.\n");
return HI_FAILURE;
}
pVBufVirt_Y = (HI_CHAR*)pUserPageAddr;
// save Y ----------------------------------------------------------------
pthread_mutex_lock(&s_video_mutex);
memcpy(pFrame, pVBufVirt_Y, u32FrameSize);
s_video_valid = HI_TRUE;
pthread_mutex_unlock(&s_video_mutex);
Video_Munmap(pUserPageAddr, u32FrameSize);
return HI_SUCCESS;
}
HI_S32 VideoStart_Color()
{
HI_S32 s32Ret =0;
HI_HANDLE VProcHdl =VPROC_HDL_COLOR;
HI_HANDLE VPortHdl =VPORT_HDL_COLOR;
HI_VPORT_ATTR_S stVPortAttr;
stVPortAttr.s32FrameRate = VPROC_FRAME_RATE;
stVPortAttr.stResolution.u32Width = 1024;
stVPortAttr.stResolution.u32Height = 576;
stVPortAttr.enPixFormat = HI_MPP_PIXEL_FORMAT_420;
stVPortAttr.enCompressMode = HI_COMPRESS_MODE_NONE;
s32Ret = HI_MAPI_VProc_Port_SetAttr(VProcHdl, VPortHdl, &stVPortAttr);
if(s32Ret != HI_SUCCESS)
{
printf("HI_MAPI_VProc_Port_SetAttr( %d,%d) fail. error = %X\r\n",
VProcHdl, VPortHdl, s32Ret);
return s32Ret;
}
//dump YUV
s32Ret = HI_MAPI_VProc_EnableDumpYUV(VProcHdl, VPortHdl);
if(s32Ret != HI_SUCCESS)
{
printf("HI_MAPI_VProc_EnableDumpYUV( %d,%d) fail. error = %X\r\n",
VProcHdl, VPortHdl, s32Ret);
return s32Ret;
}
HI_MAPI_VProc_Port_Start(VProcHdl, VPortHdl);
s32Ret = HI_MAPI_VProc_DumpYUV(VProcHdl, VPortHdl, 0, VideoSaveFrame);
if(s32Ret != HI_SUCCESS)
{
printf("HI_MAPI_VProc_EnableDumpYUV( %d,%d) fail. error = %X\r\n",
VProcHdl, VPortHdl, s32Ret);
}
return s32Ret;
}
测试结果,
条码识别成功。
二维码QR code码识别成功。
识别速度还算可以。
推荐阅读