zoukankan      html  css  js  c++  java
  • 虹软人脸识别-Java实现人脸查找及跟踪

    一、前言

    ​ 人工智能时代的到来,相信大家已耳濡目染,虹软免费离线开放的人脸识别 SDK,正推动着全行业进入刷脸时代,为了方便开发者接入,虹软提供了多种语言,多种平台的人脸识别SDK的支持,使用场景广泛。产品主要功能有:人脸检测、追踪、特征提取、特征比对、属性检测,活体检测,图像质量检测等,此外,虹软提供的是基于本地算法特征的离线识别SDK,提供全平台的离线支持。

    ​ 现如今,人脸查找及跟踪这例Demo非常火,之前我的大学室友也曾用python调opencv库函数来实现过类似的功能,包括很多比赛,也会在此基础上构造赛题,而虹软也正是提供了这方面的技术支持。因此作为初学者的我,也想尝试基于虹软的SDK来写个人脸查找及跟踪的样例,并写此文章进行记录,向广大初学开发者作分享。

    ​ 此Demo采用Maven作为项目管理工具,并基于Windows x64,Java 8,SDK是基于虹软人脸识别SDK3.0

    二、项目结构

    SDK依赖Jar包 可从虹软官网获取 点击“免费获取” ”登录“后 选择 “具体平台/版本/语言”进行获取

    在这里插入图片描述

    三、项目依赖

    pom.xml 依赖包括

    • Javacv,Lombok,Guava,Apache Common系列工具类,Logback日志相关依赖
    • 虹软人脸识别SDK依赖Jar包
        <dependencies>
            <dependency>
                <groupId>org.bytedeco</groupId>
                <artifactId>javacv-platform</artifactId>
                <version>1.5.2</version>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.8</version>
            </dependency>
            
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.2.3</version>
            </dependency>
            
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-access</artifactId>
                <version>1.2.3</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.2.3</version>
            </dependency>
    
            <dependency>
                <groupId>com.arcsoft.face</groupId>
                <artifactId>arcsoft-sdk-face</artifactId>
                <version>1.0.0</version>
                <scope>system</scope>
                <systemPath>${basedir}/libs/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
            </dependency>
    
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>26.0-jre</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.8.1</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
                <version>2.6.0</version>
            </dependency>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.6</version>
            </dependency>
        </dependencies>
    

    四、项目流程

    在这里插入图片描述

    五、效果展示

    在这里插入图片描述

    六、核心代码说明

    1.FaceEngineFactory类 源码说明

    此类继承BasePooledObjectFactory抽象类,为FaceEngine对象池

    1)成员变量说明

    //人脸识别引擎库路径
    private String libPath;
    //SDK的APP_ID
    private String appId;
    //SDK的SDK_KEY
    private String sdkKey;
    //引擎配置类
    private EngineConfiguration engineConfiguration;
    

    其中 人脸识别引擎库,APP_ID,SDK_KEY 可通过虹软官网”开发者中心“ 进行 “登录”后 在“我的应用“中进行获取

    2)create()方法

    public FaceEngine create() throws Exception {
        FaceEngine faceEngine = new FaceEngine(libPath);
        int activeCode = faceEngine.activeOnline(appId, sdkKey);
        log.info("faceEngineActiveCode:" + activeCode);
        int initCode = faceEngine.init(engineConfiguration);
        log.info("faceEngineInitCode:" + initCode);
        return faceEngine;
    }
    
    1. 参数说明:无

    2. 返回结果:FaceEngine人脸识别引擎

    3. 代码流程解读:

      此方法,通过libPath(SDK引擎库的路径)实例化FaceEngine对象,再根据APP_ID,SDK_KEY调用activeOnline()方法激活引擎(联网状态下)

      成功激活引擎后,根据EngineConfiguration引擎配置类 调用init()方法初始化引擎

    3)wrap()方法

    public PooledObject<FaceEngine> wrap(FaceEngine faceEngine) {
        return new DefaultPooledObject<>(faceEngine);
    }
    
    1. 参数说明:FaceEngine人脸识别引擎

    2. 返回结果:PooledObject包装类

    3. 代码流程解读:

      此方法,通过PooledObject包装器对象 将faceEngine进行包装,便于维护引擎的状态

    4)destroyObject()方法

    public void destroyObject(PooledObject<FaceEngine> p) throws Exception {
        FaceEngine faceEngine = p.getObject();
        int result = faceEngine.unInit();
        super.destroyObject(p);
    }
    
    1. 参数说明:PooledObject包装类

    2. 返回结果:无

    3. 代码流程解读:

      此方法,从PooledObject包装器对象中获取faceEngine引擎,随后卸载引擎

    2.FaceRecognize类 源码说明

    1)成员变量说明

    //VIDEO模式人脸检测引擎,用于预览帧人脸追踪
    private FaceEngine ftEngine;
    //人脸注册引擎
    private FaceEngine regEngine;
    //用于人脸识别的引擎池
    private GenericObjectPool<FaceEngine> frEnginePool;
    //存放视频中识别到的人脸信息(faceId为key,FaceResult为Value) (FaceId用来标记一张人脸,从进入画面到离开画面这个值不变,可以使用FaceId判断用户)
    //ConcurrentHashMap:在多线程运行情况下,增/删faceResultRegistry中的键值对时,保证其线程安全
    //volatile关键字:在多线程运行情况下,增/删faceResultRegistry中的键值对后,保证其线程之间的可见性
    private volatile ConcurrentHashMap<Integer, FaceResult> faceResultRegistry = new ConcurrentHashMap<>();
    //线程池
    private ExecutorService frService = Executors.newFixedThreadPool(20);
    //存放 注册照与注册照人脸特征值 的映射
    public ConcurrentHashMap<String, byte[]> faceFeatureRegistry = new ConcurrentHashMap<>();
    //记录上次清理过时人脸时间
    private long lastClearTime = System.currentTimeMillis();
    //封装 视频中检测到的人脸与注册照人脸 比对结果
    @Data
        public class FaceResult {
            private boolean flag = false;
            private String name;
            private float score;
        }
    //封装 视频中检测到的人脸信息
        @Data
        public class FacePreviewInfo {
            private FaceInfo faceInfo;
            private int age;
            private boolean liveness;
        }
    

    2)init()方法

    public void initEngine(String libPath,String appId,String sdkKey) {
    
        //引擎配置
        ftEngine = new FaceEngine(libPath);
        int activeCode = ftEngine.activeOnline(appId, sdkKey);
        EngineConfiguration ftEngineCfg = new EngineConfiguration();
        ftEngineCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_VIDEO);
        ftEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceDetect(true).build());
        int ftInitCode = ftEngine.init(ftEngineCfg);
    
        //引擎配置
        regEngine = new FaceEngine(libPath);
        EngineConfiguration regEngineCfg = new EngineConfiguration();
        regEngineCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
        regEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceDetect(true).supportFaceRecognition(true).build());
        int regInitCode = regEngine.init(regEngineCfg);
    
    
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxIdle(5);
        poolConfig.setMaxTotal(5);
        poolConfig.setMinIdle(5);
        poolConfig.setLifo(false);
        EngineConfiguration frEngineCfg = new EngineConfiguration();
        frEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceRecognition(true).build());
        frEnginePool = new GenericObjectPool(new FaceEngineFactory(libPath, appId, sdkKey, frEngineCfg), poolConfig);//底层库算法对象池
    
    
        if (!(activeCode == ErrorInfo.MOK.getValue() || activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue())) {
            log.error("activeCode: " + activeCode);
            throw new RuntimeException("activeCode: " + activeCode);
        }
        if (ftInitCode != ErrorInfo.MOK.getValue()) {
            log.error("ftInitEngine: " + ftInitCode);
            throw new RuntimeException("ftInitEngine: " + ftInitCode);
        }
    
        if (regInitCode != ErrorInfo.MOK.getValue()) {
            log.error("regInitEngine: " + regInitCode);
            throw new RuntimeException("regInitEngine: " + regInitCode);
        }
    
    }
    
    1. 参数说明:人脸识别引擎库路径,APP_ID,SDK_KEY

    2. 返回结果:无

    3. 代码流程解读:

      此方法,根据传入的libPath,APP_ID,SDK_KEY去初始化用于人脸检测跟踪引擎(VIDEO模式,开启人脸检测功能) 以及用于人脸注册的引擎(IMAGE模式,开启人脸识别功能),然后再去实例化人脸识别引擎池,设置引擎池对应属性后,实例化EngineConfiguration对象(开启人脸识别功能),最后通过FaceEngineFactory的构造方法去初始化引擎并获取对象池。

    3)registerFace()方法 注册人脸

    public void registerFace(String imagePath) {
        log.info("正在注册人脸");
        int count = 0;
        if (regEngine != null) {
            File file = new File(imagePath);
            File[] files = file.listFiles();
            for (File file1 : files) {
                ImageInfo imageInfo = ImageFactory.getRGBData(file1);
                if (imageInfo != null) {
                    List<FaceInfo> faceInfoList = new ArrayList<>();
                    int code = regEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(),
                            imageInfo.getImageFormat(), faceInfoList);
    
                    if (code == 0 && faceInfoList.size() > 0) {
                        FaceFeature faceFeature = new FaceFeature();
                        int resCode = regEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(),imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
                        if (resCode == 0) {
                            int lastIndexOf = file1.getName().lastIndexOf(".");
                            String name = file1.getName().substring(0, lastIndexOf);
                            faceFeatureRegistry.put(name, faceFeature.getFeatureData());
                            log.info("成功注册人脸:" + name);
                            count++;
                        }
                    }
                }
            }
            log.info("人脸注册完成,共注册:" + count + "张人脸");
        } else {
            throw new RuntimeException("注册失败,引擎未初始化或初始化失败");
        }
    }
    
    1. 参数说明:注册人脸照的目录路径

    2. 返回结果:无

    3. 代码流程解读:

      此方法,将参数目录下的每个文件解析为ImageInfo类型的RGB图像信息数据,再调用FaceEngineService对象的detectFaces()方法检测并获取人脸信息数据(其所需参数有 图像数据 ,图像宽度(4的倍数),图片高度,图像的颜色格式,存放检测到的人脸信息List)。成功检测到人脸后,再通过extractFaceFeature()方法提取人脸特征值(其所需参数有图像数据,图像宽度(4的倍数),图像高度,图像的颜色格式,人脸信息,存放提取到的人脸特征信息)。成功获取到人脸特征值后,将图片文件名和人脸特征值以key-value的形式存放于ConcurrentHashMap中。

    4)detectFaces()方法 人脸检测

    public List<FacePreviewInfo> detectFaces(ImageInfo imageInfo) {
        if (ftEngine != null) {
            List<FaceInfo> faceInfoList = new ArrayList<>();
            int code = ftEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(),
                    imageInfo.getImageFormat(), faceInfoList);
    
            List<FacePreviewInfo> previewInfoList = new LinkedList<>();
            for (FaceInfo faceInfo : faceInfoList) {
                FacePreviewInfo facePreviewInfo = new FacePreviewInfo();
                facePreviewInfo.setFaceInfo(faceInfo);
                previewInfoList.add(facePreviewInfo);
            }
    
            clearFaceResultRegistry(faceInfoList);
            return previewInfoList;
    
        }
        return null;
    }
    
    1. 参数说明:每一帧的ImageInfo图像信息

    2. 返回结果:FacePreviewInfo列表信息

    3. 代码流程解读:

      此方法,根据传入的ImageInfo类型的RGB图像信息数据,调用ftEngine引擎的detectFaces()方法 获取人脸信息,遍历获取到的人脸信息列表设置于FacePreviewInfo类型对象中,随后将faceInfoList列表 传入clearFaceResultRegistry()方法,清理过时的人脸,并返回FacePreviewInfo列表。

    5)clearFaceResultRegistry()方法 清理过时人脸

    private void clearFaceResultRegistry(List<FaceInfo> faceInfoList) {
        if (System.currentTimeMillis() - lastClearTime > 5000) {
            Iterator<Integer> iterator = faceResultRegistry.keySet().iterator();
            for (; iterator.hasNext(); ) {
                Integer next = iterator.next();
                boolean flag = false;
                for (FaceInfo faceInfo : faceInfoList) {
                    if (next.equals(faceInfo.getFaceId())) {
                        flag = true;
                    }
                }
                if (!flag) {
                    iterator.remove();
                }
    
            }
        }
    }
    
    1. 参数说明:在视频中新识别到的人脸信息列表

    2. 返回结果:FacePreviewInfo列表信息

    3. 代码流程解读:

      此方法,若当前时间距离上次清理过时人脸已有5s(用户可根据需要自行设置),则遍历faceResultRegistry的key,判断faceResultRegistryfaceInfoList(即之前识别到的与新识别到的人脸)是否存在相同FaceId的人脸,是,则删除faceResultRegistry中此过时的人脸信息。

    6)getFaceResult() 方法

    public FaceResult getFaceResult(FaceInfo faceInfo, ImageInfo imageInfo) {
        FaceResult faceResult = faceResultRegistry.get(faceInfo.getFaceId());
        if (faceResult == null) {
            faceResult = new FaceResult();
            faceResultRegistry.put(faceInfo.getFaceId(), faceResult);
            frService.submit(new FaceInfoRunnable(faceInfo, imageInfo, faceResult));
        } else if (faceResult.isFlag()) {
            return faceResult;
        }
        return null;
    }
    
    1. 参数说明: 在视频中识别到的人脸信息,ImageInfo图像信息

    2. 返回结果:FaceResult结果

    3. 代码流程解读:

      此方法,先尝试根据faceIdfaceResultRegistry中获取 FaceResult(即之前是否比对过相同人脸),若不存在则实例化一个faceResult并将其以faceId为Key,faceResult为value 存放到faceResultRegistry中,同时新建一个FaceInfoRunnable线程并将faceInfo, imageInfo, faceResult三者传入线程中 运行;若存在,则判断 faceResult的flag是否为true(即是否可从注册照找到相似人脸), 若为true 直接返回即可 。

    7)FaceInfoRunnable

    此类为一个实现 Runnable 接口的线程实现类

    成员变量说明

    //传入 视频中识别到的人脸信息
    private FaceInfo faceInfo;
    //传入 ImageInfo图像信息
    private ImageInfo imageInfo;
    //人脸比对结果封装
    private FaceResult faceResult;
    

    run()方法

    @Override
    public void run() {
        FaceEngine frEngine = null;
        try {
            frEngine = frEnginePool.borrowObject();
            if (frEngine != null) {
                FaceFeature faceFeature = new FaceFeature();
                int resCode = frEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(),
                        imageInfo.getImageFormat(), faceInfo, faceFeature);
                if (resCode == 0) {
                    float score = 0.0F;
                    Iterator<Map.Entry<String, byte[]>> iterator = faceFeatureRegistry.entrySet().iterator();
                    for (; iterator.hasNext(); ) {
                        Map.Entry<String, byte[]> next = iterator.next();
                        FaceFeature faceFeatureTarget = new FaceFeature();
                        faceFeatureTarget.setFeatureData(next.getValue());
    
                        FaceSimilar faceSimilar = new FaceSimilar();
                        frEngine.compareFaceFeature(faceFeatureTarget, faceFeature, faceSimilar);
                        if (faceSimilar.getScore() > score) {
                            score = faceSimilar.getScore();
                            faceResult.setName(next.getKey());
                        }
                    }
    
                    log.info("相似度:" + score);
                    if (score >= 0.8f) {
                        faceResult.setScore(score);
                        faceResult.setFlag(true);
                        faceResultRegistry.put(faceInfo.getFaceId(), faceResult);
                    } else {
                        faceResultRegistry.remove(faceInfo.getFaceId());
                    }
                }
            }
        } catch (Exception e) {
        } finally {
            if (frEngine != null) {
                frEnginePool.returnObject(frEngine);
            }
        }
    }
    
    1. 参数说明:无

    2. 返回结果:无

    3. 代码流程解读:

      run()方法,根据成员变量FaceInfoImageInfo 调用frEngine的extractFaceFeature()方法获取人脸特征值。成功获取特征值后,遍历faceFeatureRegistry(注册照人脸)中的特征值,结合刚获取到的特征值通过compareFaceFeature()方法比对 俩人脸相似度(其所需参数有人脸特征值1,人脸特征值2,比对模型,存放比对相似值结果),并以相似度最高的注册照命名faceResult的Name,最终,若相似度大于等于0.8(用户可根据需要自行设置) 则将相似度值设置于faceResult对象并将其flag设为true(即注册照中找到相似人脸),并以faceId为key 再次put到faceResultRegistry中,否则remove此faceIdfaceResult,最后释放引擎。

    3.VideoPlayer类 源码说明

    此类是视频播放类

    1)成员变量说明

    //视频帧抓取器
    private FFmpegFrameGrabber fFmpegFrameGrabber;
    //视频播放监听器
    private VideoListener videoListener;
    //管理定时任务(true表示其关联的线程设为守护线程)
    private Timer timer = new Timer(true);
    

    2)start()方法

    public void start() {
            try {
                fFmpegFrameGrabber.setPixelFormat(AV_PIX_FMT_BGR24 );
                fFmpegFrameGrabber.start();
                videoListener.onStart();
            } catch (FrameGrabber.Exception e) {
                videoListener.onError(e);
            }
            final int[] lengthInVideoFrames = {fFmpegFrameGrabber.getLengthInVideoFrames()};
            OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();//转换器
            TimerTask task = new TimerTask() {
                @Override
                public void run() {
                    try {
                        Frame grab = fFmpegFrameGrabber.grabImage();
                        lengthInVideoFrames[0]--;
                        if (grab != null) {
                            IplImage iplImage = converter.convert(grab);
                            if (iplImage != null) {
                                videoListener.onPreview(iplImage);
                            }
                        }
                        if (lengthInVideoFrames[0] <= 0) {
                            stop();
                        }
                    } catch (Exception e) {
                        videoListener.onError(e);
                    }
                }
            };
            timer.schedule(task, 0, 40);
        }
    
    1. 参数说明:无

    2. 返回结果:无

    3. 代码流程解读:

      此方法,用于开始播放视频,首先为帧抓取器设置 要转换成的图像数据格式,随后启动帧抓取器和视频播放监听器。lengthInVideoFrames数组中存放视频的帧数,而converter变量为帧与图片之间的转换器。通过TimerTask生成一个线程,在线程run()方法中去抓取视频中的每一帧并将其转换为图像,获取到的图像交给videoListeneronPreview()回调方法进行处理,若帧数已处理完则停止运行。另外,TimerTask线程将由timer进行管理,每40毫秒执行一次。

    4.MainApplication类 源码说明

    此类为包含main()方法的主类,右击 执行 Run ‘MainApplication.main()’ 即可运行此Demo

    main() 主方法

    //虹软引擎库存放路径
    String libPath = "D:\arcsoft_lib";
    //sdk的APP_ID
    String appId = "9iSfMeAhjA52N**************iW1aKes2TpSrd";
    //sdk的SDK_KEY
    String sdkKey = "BuRTH3hGs91m**************dxEgyP9xu6fiFG7G";
    //视频文件路径(从视频中查找并跟踪人脸)
    String videoPath="D:icon-man.mp4";
    //需要识别人的注册照目录路径
    String imagePath="D:\photo";
    
    Loader.load(opencv_imgproc.class);
    Loader.load(CvPoint.class);
    Loader.load(CvFont.class);
    CanvasFrame canvas = new CanvasFrame("预览");
    canvas.setDefaultCloseOperation(EXIT_ON_CLOSE);
    VideoPlayer videoPlayer = new VideoPlayer(videoPath);
    

    首先,加载opencv_imgprocCvPointCvFont等程序所需类,并实例化预览窗口(设置程序退出即窗口关闭)

    同时向VideoPlayer的构造方法传入视频路径(为FFmpegFrameGrabber成员变量 指定具体视频) 实例化VideoPlayer

    FaceRecognize faceRecognize = new FaceRecognize();
    faceRecognize.initEngine(libPath,appId,sdkKey);
    faceRecognize.registerFace(imagePath);
    OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
    

    之后,实例化FaceRecognize 并根据LibPath,APP_ID,SDK_KEY调用initEngine()方法初始化FaceRecognize 各引擎,同时实例化转换器

    videoPlayer.setListener(new VideoListener() {
    
        CvScalar color = cvScalar(0, 0, 255, 0);       // blue [green] [red]
        CvFont cvFont = cvFont(opencv_imgproc.FONT_HERSHEY_DUPLEX);
    
        @Override
        public void onStart() {
        }
    
        @Override
        public void onPreview(IplImage iplImage) {
            ImageInfo imageInfo = new ImageInfo();
            imageInfo.setWidth(iplImage.width());
            imageInfo.setHeight(iplImage.height());
            imageInfo.setImageFormat(ImageFormat.CP_PAF_BGR24);
            byte[] imageData = new byte[iplImage.imageSize()];
            iplImage.imageData().get(imageData);
            imageInfo.setImageData(imageData);
            List<FaceRecognize.FacePreviewInfo> previewInfoList = faceRecognize.detectFaces(imageInfo);
    
            for (FaceRecognize.FacePreviewInfo facePreviewInfo : previewInfoList) {
                int x = facePreviewInfo.getFaceInfo().getRect().getLeft();
                int y = facePreviewInfo.getFaceInfo().getRect().getTop();
                int xMax = facePreviewInfo.getFaceInfo().getRect().getRight();
                int yMax = facePreviewInfo.getFaceInfo().getRect().getBottom();
    
                CvPoint pt1 = cvPoint(x, y);
                CvPoint pt2 = cvPoint(xMax, yMax);
                opencv_imgproc.cvRectangle(iplImage, pt1, pt2, color, 1, 4, 0);
    
                FaceRecognize.FaceResult faceResult = faceRecognize.getFaceResult(facePreviewInfo.getFaceInfo(), imageInfo);
                if (faceResult != null) {
                    try {
                        CvPoint pt3 = cvPoint(x, y - 2);
                        opencv_imgproc.cvPutText(iplImage, faceResult.getName(), pt3, cvFont, color);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            Frame frame = converter.convert(iplImage);
            canvas.showImage(frame);
        }
        @Override
        public void onCancel() {
        }
        @Override
        public void onError(Exception e) {
        }
    });
    
    videoPlayer.start();
    

    ​ 上述代码 ,首先为VideoPlayer设置监听器,再启动VideoPlayer。而监听器VideoListeneronPreview()方法中,先将传入的IplImage类型图像信息数据(即由帧抓取器获取到的图片)设置到ImageInfo类型对象中,之后调用faceRecognizedetectFaces()方法获取人脸信息。成功获取到人脸后,根据人脸信息确定人脸方位坐标,调用opencv_imgproc绘制方形矩阵。再根据识别到的人脸信息和图像信息数据 调用faceRecognizegetFaceResult()方法获取FaceResult(即注册照中是否拥有与视频中相似的人脸)。若FaceResult不为空,则调用 opencv_imgproc将对应图片文件名写于人脸框上方,最后将图片转化为视频帧作用于canvas上进行展示。

    六、源码下载

    若有想一起学习虹软SDK,感受人脸识别奥秘的同学,可通过点击此链接获取Demo源码
    了解更多人脸识别产品相关内容请到虹软视觉开放平台

  • 相关阅读:
    python模块导入
    linux总结shell
    linux和shell关系
    gdb调试工具
    C语言.c和.h
    CSS cursor 属性
    html dom SetInterVal()
    css hover伪类选择器与JQuery hover()方法
    CSS 清除浮动 clear 属性
    block,inline和inline-block概念和区别
  • 原文地址:https://www.cnblogs.com/ccLqqy/p/13754897.html
Copyright © 2011-2022 走看看