海思3516 zbar识别二维码,并保存yuv图像代码


原文链接: 海思3516 zbar识别二维码,并保存yuv图像代码

海思3559平台移植二维码解码库zbar_嵌入式_重拾程序之路-CSDN博客

#include <stdio.h>
#include <stdlib.h>
#include <zbar.h>

zbar_image_scanner_t *scanner = NULL;


void get_yuv_data(const char *name, int *width, int *height, void **raw)
{
    FILE *pfile = fopen(name, "rb");
    if(!pfile) exit(2);
    *raw = malloc((*width) * (*height));
    fread(*raw,1,(*width)*(*height),pfile);
    fclose(pfile);
}

int main (int argc, char **argv)
{
    if(argc < 2) return(1);

    /* 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 */
    int width = 1920, height = 1080;
    void *raw = NULL;
    get_yuv_data(argv[1], &width, &height, &raw);

    /* wrap image data */
    zbar_image_t *image = zbar_image_create();
    zbar_image_set_format(image, *(int*)"Y800");
    zbar_image_set_size(image, width, height);
    zbar_image_set_data(image, raw, width * height, zbar_image_free_data);

    /* scan the image for barcodes */
    int n = zbar_scan_image(scanner, image);
    if(0==n||-1==n)
    {
      printf("no symbols were found or -1 if an error occurs\n");
    }
    /* 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);
    }

    /* clean up */
    zbar_image_destroy(image);
    zbar_image_scanner_destroy(scanner);

    return(0);
}

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

/******************************************************************************
  Some simple Hisilicon Hi35xx video input functions.

  Copyright (C), 2010-2011, Hisilicon Tech. Co., Ltd.
 ******************************************************************************
    Modification:  2011-2 Created
******************************************************************************/
#ifdef __cplusplus
#if __cplusplus
extern "C"
{
#endif
#endif /* End of #ifdef __cplusplus */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <math.h>
#include <unistd.h>
#include <signal.h>
#include "hi_comm_video.h"
#include "mpi_vi.h"
#include "zbar.h"
    //#include "test_images.h"

#include "sample_comm.h"
#define MAX_FRM_WIDTH 2048
    static HI_CHAR *pUserPageAddr[2] = {HI_NULL, HI_NULL};
    static HI_U32 u32Size = 0;

    static FILE *pfd = HI_NULL;

    HI_S32 SAMPLE_COMM_VPSS_GetImg(VPSS_GRP VpssGrp, VPSS_CHN VpssChn)
    {
        printf("grp:%d,chn:%d\n", VpssGrp, VpssChn);
        zbar_image_scanner_t *scanner = NULL;
        /* 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 */
        int width = 0, height = 0;
        HI_S32 s32ret;
        HI_VOID *yPtr;
        VIDEO_FRAME_INFO_S stFrame;
        HI_U32 u32Depth, i;
        char *pVBufVirt_Y;
        HI_CHAR *pUserPageAddr[2];
        HI_U32 u32UvHeight;
        char *pVBufVirt_C;
        HI_CHAR szYuvName[128];
        char *pMemContent;
        HI_CHAR szPixFrm[10];
        unsigned int w, h;
        static unsigned char TmpBuff[MAX_FRM_WIDTH];
        HI_U32 u32Cnt = 1;
        snprintf(szPixFrm, 10, "P420");
        /* set max depth */
        u32Depth = 3;
        HI_U32 len;
        snprintf(szYuvName, 128, "./vpss_grp%d_chn%d_w%d_h%d_%s_%d.yuv", VpssGrp, VpssChn,
                 stFrame.stVFrame.u32Width, stFrame.stVFrame.u32Height, szPixFrm, u32Cnt);
        printf("Dump YUV frame of vpss chn %d  to file: \"%s\"\n", VpssChn, szYuvName);
        fflush(stdout);
        pfd = fopen(szYuvName, "wb");
        s32ret = HI_MPI_VPSS_SetDepth(VpssGrp, VpssChn, u32Depth); //HI_MPI_VPSS_SetDepth
        if (HI_SUCCESS != s32ret)
        {
            printf("set max depth err:0x%x\n", s32ret);
            return s32ret;
        }

        while (1)
        {

            /* get video frame from vpss chn */
            s32ret = HI_MPI_VPSS_GetChnFrame(VpssGrp, VpssChn, &stFrame, -1);
            if (HI_SUCCESS != s32ret)
            {
                printf("get vpss frame err:0x%x\n", s32ret);
                return s32ret;
            }
            width = stFrame.stVFrame.u32Width;
            height = stFrame.stVFrame.u32Height;
            //raw=(void*)malloc(2*width*height);
            zbar_image_t *image = zbar_image_create();
            zbar_image_set_format(image, *(int *)"NV21");
            zbar_image_set_size(image, width, height);
            printf("get vpss frame u32Width: 0x%x\n", stFrame.stVFrame.u32Width);
            printf("get vpss frame u32Height: 0x%x\n", stFrame.stVFrame.u32Height);
            u32UvHeight = stFrame.stVFrame.u32Height / 2;
            //len = (stFrame.stVFrame.u32Stride[0])*(stFrame.stVFrame.u32Height)+(stFrame.stVFrame.u32Stride[1])*u32UvHeight;
            len = (stFrame.stVFrame.u32Stride[0]) * (stFrame.stVFrame.u32Height) * 3 / 2;
            //	yPtr= HI_MPI_SYS_Mmap(stFrame.stVFrame.u32PhyAddr[0], len);
            pUserPageAddr[0] = (HI_CHAR *)HI_MPI_SYS_Mmap(stFrame.stVFrame.u32PhyAddr[0], len);
            pVBufVirt_Y = pUserPageAddr[0];
            pVBufVirt_C = pVBufVirt_Y + (stFrame.stVFrame.u32Stride[0]) * (stFrame.stVFrame.u32Height);

            fprintf(stderr, "saving......Y......");
            fflush(stderr);
            for (h = 0; h < stFrame.stVFrame.u32Height; h++)
            {
                pMemContent = pVBufVirt_Y + h * stFrame.stVFrame.u32Stride[0];
                fwrite(pMemContent, stFrame.stVFrame.u32Width, 1, pfd);
            }

            fflush(pfd);
            /* save U ----------------------------------------------------------------*/
            fprintf(stderr, "U......");
            fflush(stderr);

            for (h = 0; h < u32UvHeight; h++)
            {
                pMemContent = pVBufVirt_C + h * stFrame.stVFrame.u32Stride[1];

                pMemContent += 1;

                for (w = 0; w < stFrame.stVFrame.u32Height / 2; w++)
                {
                    TmpBuff[w] = *pMemContent;
                    pMemContent += 2;
                }
                fwrite(TmpBuff, stFrame.stVFrame.u32Width / 2, 1, pfd);
            }
            fflush(pfd);

            /* save V ----------------------------------------------------------------*/
            fprintf(stderr, "V......");
            fflush(stderr);
            for (h = 0; h < u32UvHeight; h++)
            {
                pMemContent = pVBufVirt_C + h * stFrame.stVFrame.u32Stride[1];

                for (w = 0; w < stFrame.stVFrame.u32Width / 2; w++)
                {
                    TmpBuff[w] = *pMemContent;
                    pMemContent += 2;
                }
                fwrite(TmpBuff, stFrame.stVFrame.u32Width / 2, 1, pfd);
            }

            fflush(pfd);

            fprintf(stderr, "done %d, 0x%x!\n", stFrame.stVFrame.u32TimeRef, stFrame.stVFrame.u32PhyAddr[0]);
            fflush(stderr);

            zbar_image_set_data(image, pVBufVirt_Y, (stFrame.stVFrame.u32Stride[0]) * (stFrame.stVFrame.u32Height), NULL);

            zbar_image_t *test = zbar_image_convert(image, *(int *)"Y800");
            s32ret = HI_MPI_VPSS_ReleaseChnFrame(VpssGrp, VpssChn, &stFrame);

            if (HI_SUCCESS != s32ret)
            {
                printf("Release vi frame err:0x%x\n", s32ret);
                return s32ret;
            }

            /* scan the image for barcodes */

            int n = zbar_scan_image(scanner, test); //二维码扫描
            printf("n=%d\n", n);
            if (n == 0)
                continue;
            /* extract results */
            const zbar_symbol_t *symbol = zbar_image_first_symbol(test);
            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);
            }

            HI_MPI_SYS_Munmap(pUserPageAddr[0], len);
        }
        return s32ret;
    }
}

————————————————
版权声明:本文为CSDN博主「不吃胡萝卜smile」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wmdshhzsmile/article/details/85244417

`