虹软人脸识别SDK在网络摄像头中的实际应用

目前在人脸识别领域中,网络摄像头的使用很普遍,但接入网络摄像头和人脸识别SDK有一定门槛,在此文章中有介绍过虹软人脸识别SDK的接入流程,本文着重介绍网络摄像头获取视频流并处理的流程(红色框内),以下内容仅供参考。

1.海康SDK接入基本流程

a.初始化并登录验证

        NET_DVR_Init();
        NET_DVR_DEVICEINFO_V30 struDeviceInfo = { 0 };
        long lUserID = NET_DVR_Login_V30(m_cameraIp, m_cameraPort,
            m_cameraUser, m_cameraPwd, &struDeviceInfo);
        if (lUserID < 0)
        {
            NET_DVR_Cleanup();
            return false;
        }

b.创建线程并注册回调函数

        thread videoThread(&HCNetCamera::getCameraPreview, this);
        videoThread.detach();

        bool HCNetCamera::getCameraPreview()
        {
            NET_DVR_CLIENTINFO ClientInfo;
            ClientInfo.lChannel = 1; //Channel number 设备通道号
            ClientInfo.hPlayWnd = NULL;  //窗口为空,设备SDK不解码只取流
            ClientInfo.lLinkMode = 0;    //Main Stream
            ClientInfo.sMultiCastIP = NULL;
            //预览取流
            g_realHandle = NET_DVR_RealPlay_V30(g_cameraUserId, &ClientInfo, fRealDataCallBack, NULL, TRUE);
            if (g_realHandle < 0)
            {
                qDebug() << "NET_DVR_RealPlay_V30 failed! Error number: " << NET_DVR_GetLastError();
                return false;
            }
            return true;
        }

c.使用回调接口,获取实时的视频帧数据

        void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void *pUser)
        {
            UNREFERENCED_PARAMETER(lRealHandle);
            UNREFERENCED_PARAMETER(pUser);

            DWORD dRet = 0;
            BOOL inData = FALSE;

            switch (dwDataType)
            {
            case NET_DVR_SYSHEAD:
                if (g_cameraPort >= 0)
                {
                    break; //同一路码流不需要多次调用开流接口
                }
                if (!PlayM4_GetPort(&g_cameraPort))
                {
                    break;
                }
                if (!PlayM4_OpenStream(g_cameraPort, pBuffer, dwBufSize, 1024 * 1024))
                {
                    dRet = PlayM4_GetLastError(g_cameraPort);
                    break;
                }
                //设置解码回调函数
                if (!PlayM4_SetDecCallBack(g_cameraPort, DecCBFun))
                {
                    dRet = PlayM4_GetLastError(g_cameraPort);
                    break;
                }
                //打开视频解码
                if (!PlayM4_Play(g_cameraPort, NULL))
                {
                    dRet = PlayM4_GetLastError(g_cameraPort);
                    break;
                }
                dRet = PlayM4_GetLastError(g_cameraPort);
                break;

            case NET_DVR_STREAMDATA:       //视频流数据
            default:
                inData = PlayM4_InputData(g_cameraPort, pBuffer, dwBufSize);
                while (!inData)
                {
                    Sleep(10);
                    inData = PlayM4_InputData(g_cameraPort, pBuffer, dwBufSize);
                    dRet = PlayM4_GetLastError(g_cameraPort);
                    OutputDebugString(L"PlayM4_InputData failed \n");
                }
                break;
            }
        }
        //解码回调 视频为YUV数据(YV12)
        void CALLBACK DecCBFun(long port, char * pBuf, long nSize, FRAME_INFO * pFrameInfo, long nReserved1, long nReserved2)
        {
            UNREFERENCED_PARAMETER(nReserved1);
            UNREFERENCED_PARAMETER(nReserved2);
            UNREFERENCED_PARAMETER(nSize);
            UNREFERENCED_PARAMETER(port);

            //图像格式转换
            if (pFrameInfo->nType == T_YV12)
            {
                {
                    lock_guard<mutex> locker(g_CameraMutex);

                    Utils_ns::ImageUtils_ns::YV12ToBGR24_FFMPEG((unsigned char*)pBuf, (unsigned char*)g_curRGBImage->imageData,
                        pFrameInfo->nWidth, pFrameInfo->nHeight);//得到全部RGB图像
                }
            }
        }

d.应用层获取视频帧,这里为了简化操作,只获取了当前帧;大家也可以使用线程安全队列来处理

        int HCNetCamera::getFrame(Mat& image)
        {
            lock_guard<mutex> locker(g_CameraMutex);
            if (g_curRGBImage && g_curRGBImage->imageData)
            {
                image = g_curRGBImage;
                return 0;
            }
            return -1;
        }

        //以下是线程函数的一部分,主要是取帧,然后进行人脸检测
        {
            lock_guard<std::mutex> locker(g_CameraMutex);
            int ret = m_camera->getFrame(curFrame);
            if (ret == -1)
            {
                continue;
            }
        }

        ftProcessor->faceDetect(curFrame);

2.基本图像格式转换

目前虹软SDK支持以下几种图像数据格式:

在实际开发过程中一般使用opencv,opencv默认的图像数据格式是BGR24,而我使用的海康摄像头视频编码格式是H264,视频帧数据格式是YV12,因此需要将YV12转换为BGR24 ,同时也会说明下怎么转换为虹软SDK支持的其它格式,主要参考了[2],以下的代码仅供参考。

a.YV12 To BGR24

void yv12ToBGR24(unsigned char* yv12, unsigned  char* bgr24, int width, int height)
{
    unsigned char* y_yv12 = yv12;
    unsigned char* v_yv12 = yv12 + width*height;
    unsigned char* u_yv12 = yv12 + width*height + width*height / 4;

    unsigned char* b = bgr24;
    unsigned char* g = bgr24 + 1;
    unsigned char* r = bgr24 + 2;

    int yIndex, uIndex, vIndex;
    for (int i = 0; i < height; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            yIndex = i * width + j;
            vIndex = (i / 2) * (width / 2) + (j / 2);
            uIndex = vIndex;

            *b = (unsigned char)(y_yv12[yIndex] + 1.732446 * (u_yv12[vIndex] - 128));
            *g = (unsigned char)(y_yv12[yIndex] - 0.698001 * (u_yv12[uIndex] - 128) - 0.703125 * (v_yv12[vIndex] - 128));
            *r = (unsigned char)(y_yv12[yIndex] + 1.370705 * (v_yv12[uIndex] - 128));

            b += 3;
            g += 3;
            r += 3;
        }
    }
}

b.YV12 To I420

void yv12ToI420(unsigned char* yv12, unsigned char* i420, int width, int height)
{
    unsigned char* y_yv12 = yv12;
    unsigned char* v_yv12 = yv12 + width*height;
    unsigned char* u_yv12 = yv12 + width*height + width*height / 4;

    unsigned char* y_i420 = i420;
    unsigned char* u_i420 = i420 + width*height;
    unsigned char* v_i420 = i420 + width*height + width*height / 4;

    memcpy(i420, yv12, width*height);
    memcpy(v_i420, v_yv12, width*height / 4);
    memcpy(u_i420, u_yv12, width*height / 4);

}

c.YV12 To NV21

void yv12ToNV21(unsigned char* yv12, unsigned char* nv21, int width, int height)
{
    unsigned char* y_yv12 = yv12;
    unsigned char* v_yv12 = yv12 + width*height;
    unsigned char* u_yv12 = yv12 + width*height + width*height / 4;

    unsigned char* y_nv21 = nv21;
    unsigned char* v_nv21 = nv21 + width*height;
    unsigned char* u_nv21 = nv21 + width*height + 1;

    memcpy(nv21, yv12, width*height);

    for (int i = 0; i < width*height / 4; ++i)
    {
        *v_nv21 = *v_yv12;
        *u_nv21 = *u_yv12;

        v_nv21 += 2;
        u_nv21 += 2;

        ++v_yv12;
        ++u_yv12;
    }
}

d.YV12 To NV12

void yv12ToNV12(unsigned char* yv12, unsigned  char* nv12, int width, int height)
{
    unsigned char* y_yv12 = yv12;
    unsigned char* v_yv12 = yv12 + width*height;
    unsigned char* u_yv12 = yv12 + width*height + width*height / 4;

    unsigned char* y_nv12 = nv12;
    unsigned char* u_nv12 = nv12 + width*height;
    unsigned char* v_nv12 = nv12 + width*height + 1;

    memcpy(nv12, yv12, width*height);

    for (int i = 0; i < width*height / 4; ++i)
    {
        *v_nv12 = *v_yv12;
        *u_nv12 = *u_yv12;

        v_nv12 += 2;
        u_nv12 += 2;

        ++v_yv12;
        ++u_yv12;
    }
}

e.YV12 To YUYV

void yv12ToYUYV(unsigned char* yv12, unsigned char* yuyv, int width, int height)
{
    unsigned char* y_yv12 = yv12;
    unsigned char* v_yv12 = yv12 + width*height;
    unsigned char* u_yv12 = yv12 + width*height + width*height / 4;

    unsigned char* y_yuyv = yuyv;
    unsigned char* u_yuyv = yuyv + 1;
    unsigned char* v_yuyv = yuyv + 3;

    for (int i = 0; i < width; ++i)
    {
        for (int j = 0; j < height; ++j)
        {
            *y_yuyv = *y_yv12;

            y_yuyv += 2;
            ++y_yv12;
        }
    }

    for (int j = 0; j < height / 2; ++j)
    {
        for (int i = 0; i < width / 2; ++i)
        {
            *u_yuyv = *u_yv12;
            *(u_yuyv + width * 2) = *u_yv12;
            u_yuyv += 4;
            ++u_yv12;

            *v_yuyv = *v_yv12;
            *(v_yuyv + width * 2) = *v_yv12;
            v_yuyv += 4;
            ++v_yv12;
        }
        u_yuyv += width * 2;
        v_yuyv += width * 2;
    }
} 

虹软免费的sdk下载:https://ai.arcsoft.com.cn/product/arcface.html

原文地址:https://blog.51cto.com/14633836/2460833

时间: 2024-10-01 05:59:45

虹软人脸识别SDK在网络摄像头中的实际应用的相关文章

Android 实现人脸识别教程[运用虹软人脸识别SDK]

基于虹软人脸识别引擎,在Android平台上实现人脸识别功能,即使在离线的情况下依旧运行,不被人采集个人照片的感觉,还是爽爽的.经过整个测试过来,虹软的人脸识别还是很强大的,人脸检测可以控制在20ms之内,人脸识别大概在200ms左右.今天就来分享一下开发经验 项目的目标 我们需要实现一个人脸识别功能.简单来说,就是机的后置摄像头,识别摄像头中实时拍到的人脸信息,如果人库注册过,则显示识别后的人脸信息,如登记的名字:如果不在,提示未注册. 这个功能具有多个应用场景,比如,火车站或者打卡和门禁系统

虹软人脸识别SDK的接入方法

背景: 虹软的人脸识别还是不错的,在官方注册一个账号,成为开发者,下载SDK的jar包,在开发者中心,找一个demo就可以开始做了,安装里边的逻辑,先看理解代码,然后就可以控制代码,完成自己想要的功能 一:准备工作 注意: 1 sdk的下载,会给你4个jar包和4个秘钥以及1个appid,这个appid是用来绑定你的jar包,使用别人的会造成识别引擎启动失败, 下载文件如下: 这里需要把文件解压并整理,每个引擎的so文件和jar是分开的,所以需要一一解压,然后整理一下 如下: 在项目里建立如下文

怎么接入虹软人脸识别SDK

背景: 虹软的人脸识别还是不错的,在官方注册一个账号,成为开发者,下载SDK的jar包,在开发者中心,找一个demo就可以开始做了,安装里边的逻辑,先看理解代码,然后就可以控制代码,完成自己想要的功能 一:准备工作 注意: 1 sdk的下载,会给你4个jar包和4个秘钥以及1个appid,这个appid是用来绑定你的jar包,使用别人的会造成识别引擎启动失败, 下载文件如下: 这里需要把文件解压并整理,每个引擎的so文件和jar是分开的,所以需要一一解压,然后整理一下如下: 在项目里建立如下文件

虹软人脸识别SDK(java+linux/window)

虹软官网:http://www.arcsoft.com.cn/ 登录后要实名认证才可以使用sdk. 下图这两个是我选择的,window版本地开发测试,linux版是生产环境使用. 1. 保存激活码,下载sdk包. 2. 将动态链接库.dll或.so放在java.libary.path目录(否则执行时会报错) (不知道可以打印出目录:System.out.println(System.getProperty("java.library.path")); ) 3.sdk包中有一个demo可

【下载】推荐一款免费的人脸识别SDK

现已进入刷脸的时代,例如,人脸支付.人脸识别的门禁.人流监控等等.如何在Firefly开源板上快速搭建DEMO,并快速产品化?为了让更多产品可以用上人脸识别技术,Firefly推出了一款高性能人脸识别SDK.此SDK的人脸识别的算法,运行效率高,识别精确度高,性能优异,可以直接应用于商业产品. 下文主要讲述如何在Firefly RK3399平台部署并测试OpenFace SDK,Let's GO!      一.Firefly RK3399开源板安装Ubuntu 16.04系统固件      系

虹软人脸识别应用开发过程

趁空闲的一点点时间向大家分享一个好用的人脸识别的应用--来自虹软公司的人脸识别推荐这家的产品主要有以下几个理由~1.免费!免费!免费!它家比较良心.人脸识别.人证核验.活体检测等等一切的sdk都是免费下载使用的- -即使商用也可以~非常适合我这种小穷人2.根据不同操作平台提供不同的SDK目前可下载Windows x86,x64平台(c++/Java语言).Linux x64平台(c++/Java语言).iOS平台(Objective-C语言)与Android arm32平台(Java语言)3.官

百度人脸识别SDK学习

之前看到同事说人脸识别多么高大上之类的, 我就好奇搜索了一下, 本人是小白级别,喜欢用百度多一点,所以就使用了百度的人脸识别SDK进行研究.不得不说百度提供的完档很详细,在学习过程中很少出现不能解决的问题, 所以本人也偷个懒,把sdk文档复制下来. 注:貌似有个bug,我在百度语音中菜单下创建的人脸识别,然后获取API_key和Secret_key, 在学习尝试过程中, 或多或少有请求量, 但是报表中却没有任何记录, 难道是bug吗? 我在想是不是可以无限制的调用了,作为尝试, 没去批量去测试,

记C# 调用虹软人脸识别 那些坑

上一个东家是从事安防行业的,致力于人工智能领域,有自主人脸识别.步态识别的算法.C++同事比较称职有什么问题都可以第一时间反馈,并得到合理的处理,封装的DLL 是基于更高性能的GPU算法,可支持更多线路的运算,接口调用简单,只需要传入图片即可得到特征特征值.对于公司的项目,更多的是与各类接口进行交互.包括建立任务.上传视频.截取片段,抽取特征,学习特征,步态比对等对接接口的复杂业务逻辑.由于长期和C++接口对接,包括Kafka消息队列传输等,对于公司项目支撑的业务流程比较了解.至于底层算法,只是

虹软人脸识别3.0 - 图像数据结构介绍(Android)

从虹软开放了2.0版本SDK以来,由于具有免费.离线使用的特点,我们公司在人脸识别门禁应用中使用了虹软SDK,识别效果还不错,因此比较关注虹软SDK的官方动态.近期上线了ArcFace 3.0 SDK版本,确实做了比较大的更新.首先本篇介绍一下关于Android平台算法的更新内容,下一篇将针对Windows平台的算法更新展开介绍. 特征比对支持比对模型选择,有生活照比对模型和人证比对模型 识别率.防***效果显著提升 特征值更新,升级后人脸库需重新注册 Android平台新增64位的SDK 图像