欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

海思3559平台移植二维码解码库zbar

程序员文章站 2022-05-22 19:54:03
...

1. 下载并解压 zbar 源码包:

http://zbar.sourceforge.net/download.html
海思3559平台移植二维码解码库zbar
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

流程图如下
海思3559平台移植二维码解码库zbar

初始化以及参数配置:

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码识别成功。
识别速度还算可以。