海思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