java+opencv實現人臉識別程序記錄


結果

基本實現了識別的功能。基本的界面如下

 

界面長得比較丑,主要是JavaSwing寫界面比較麻煩,寫個菜單欄都要那么多代碼。目前不打算改了。

實現的思路是:使用opencv中自帶的OpenCVFrameGrabber獲取攝像頭的數據,CanvasFrame來顯示攝像頭捕獲的畫面。

 

 

 

 

點擊注冊和識別都會在捕獲的視頻流自動抓取一幀圖片,點下面的按鈕可以查看拍攝效果

 

 

 當輸入想要比對的身份,點擊識別之后,會與注冊保存的數據進行比對

 

准確率還行。

附上部分代碼

public static void OpenCamera()throws Exception, InterruptedException{
        OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);//0表示本機攝像頭  當然這里也可以換成網絡攝像頭地址
        grabber.start();   //開始獲取攝像頭數據
        CanvasFrame canvas = new CanvasFrame("倒計時5秒自動拍照注冊");//新建一個窗口
        canvas.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);//窗口關閉時程序運行結束
        canvas.setAlwaysOnTop(true);
        int i=0;
        while(true){
            if(i==30){//窗口是否關閉
                System.out.println("已關閉");
                grabber.stop();//停止抓取
                canvas.dispose();
                //System.exit(2);//退出
            }
            canvas.showImage(grabber.grab());//獲取攝像頭圖像並放到窗口上顯示, 這里的Frame frame=grabber.grab(); frame表示一幀視頻圖像
            //調用doExecuteFrame()方法,將截取的圖片保存在本地
            if(i==1)CatchPhoto(grabber.grabFrame(),"./register"+"/"+ MainWindow.ID +".jpg");
            Thread.sleep(50);//50毫秒刷新一次圖像
            i++;
        }
    }

 

 

 //人臉檢測
        ImageInfo imageInfo = getRGBData(new File(register));
        List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
        errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
        System.out.println(faceInfoList);

        //特征提取
        FaceFeature faceFeature = new FaceFeature();
        errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
        System.out.println("特征值大小:" + faceFeature.getFeatureData().length);

        //人臉檢測2
        ImageInfo imageInfo2 = getRGBData(new File(discern));
        List<FaceInfo> faceInfoList2 = new ArrayList<FaceInfo>();
        errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(),imageInfo.getImageFormat(), faceInfoList2);
        System.out.println(faceInfoList);

        //特征提取2
        FaceFeature faceFeature2 = new FaceFeature();
        errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo.getImageFormat(), faceInfoList2.get(0), faceFeature2);
        System.out.println("特征值大小:" + faceFeature.getFeatureData().length);

        //特征比對
        FaceFeature targetFaceFeature = new FaceFeature();
        targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
        FaceFeature sourceFaceFeature = new FaceFeature();
        sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
        FaceSimilar faceSimilar = new FaceSimilar();

        errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);

        //System.out.println("相似度:" + faceSimilar.getScore());
        MainWindow.Similarity.setText("相似度:" + faceSimilar.getScore());

        //設置活體測試
        errorCode = faceEngine.setLivenessParam(0.5f, 0.7f);
        //人臉屬性檢測
        FunctionConfiguration configuration = new FunctionConfiguration();
        configuration.setSupportAge(true);
        configuration.setSupportFace3dAngle(true);
        configuration.setSupportGender(true);
        configuration.setSupportLiveness(true);
        errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, configuration);


        //性別檢測
        List<GenderInfo> genderInfoList = new ArrayList<GenderInfo>();
        errorCode = faceEngine.getGender(genderInfoList);
        //System.out.println("性別:" + genderInfoList.get(0).getGender());
        if(genderInfoList.get(0).getGender()==0){
            MainWindow.Sex.setText("性別:男" );
        }
        else if(genderInfoList.get(0).getGender()==1){
            MainWindow.Sex.setText("性別:女" );
        }
        else{
            MainWindow.Sex.setText("性別:未知" );
        }
        //MainWindow.Sex.setText("性別:" + genderInfoList.get(0).getGender());

        //年齡檢測
        List<AgeInfo> ageInfoList = new ArrayList<AgeInfo>();
        errorCode = faceEngine.getAge(ageInfoList);
        //System.out.println("年齡:" + ageInfoList.get(0).getAge());
        MainWindow.Age.setText("年齡:" + ageInfoList.get(0).getAge());



        //3D信息檢測
        List<Face3DAngle> face3DAngleList = new ArrayList<Face3DAngle>();
        errorCode = faceEngine.getFace3DAngle(face3DAngleList);
        System.out.println("3D角度:" + face3DAngleList.get(0).getPitch() + "," + face3DAngleList.get(0).getRoll() + "," + face3DAngleList.get(0).getYaw());
        MainWindow.Angle.setText("3D角度:" + face3DAngleList.get(0).getPitch() + "," + face3DAngleList.get(0).getRoll() + "," + face3DAngleList.get(0).getYaw());

        //活體檢測
        List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
        errorCode = faceEngine.getLiveness(livenessInfoList);
        //System.out.println("活體:" + livenessInfoList.get(0).getLiveness());
        MainWindow.LiVing.setText("活體:" + livenessInfoList.get(0).getLiveness());

        //IR屬性處理
        ImageInfo imageInfoGray = getGrayData(new File("C:\\Users\\user\\Desktop\\test\\photo\\1.jpg"));
        List<FaceInfo> faceInfoListGray = new ArrayList<FaceInfo>();
        errorCode = faceEngine.detectFaces(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray);

        FunctionConfiguration configuration2 = new FunctionConfiguration();
        configuration2.setSupportIRLiveness(true);
        errorCode = faceEngine.processIr(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray, configuration2);
        //IR活體檢測
        List<IrLivenessInfo> irLivenessInfo = new ArrayList<>();
        errorCode = faceEngine.getLivenessIr(irLivenessInfo);
        System.out.println("IR活體:" + irLivenessInfo.get(0).getLiveness());

        ImageInfoEx imageInfoEx = new ImageInfoEx();
        imageInfoEx.setHeight(imageInfo.getHeight());
        imageInfoEx.setWidth(imageInfo.getWidth());
        imageInfoEx.setImageFormat(imageInfo.getImageFormat());
        imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()});
        imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3});
        List<FaceInfo> faceInfoList1 = new ArrayList<>();
        errorCode = faceEngine.detectFaces(imageInfoEx, DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList1);

        FunctionConfiguration fun = new FunctionConfiguration();
        fun.setSupportAge(true);
        errorCode = faceEngine.process(imageInfoEx, faceInfoList1, functionConfiguration);
        List<AgeInfo> ageInfoList1 = new ArrayList<>();
        int age = faceEngine.getAge(ageInfoList1);
        System.out.println("年齡:" + ageInfoList1.get(0).getAge());

        FaceFeature feature = new FaceFeature();
        errorCode = faceEngine.extractFaceFeature(imageInfoEx, faceInfoList1.get(0), feature);

 

 

 

 

問題記錄

1.捕獲視頻流

網上找到了很多方法,比如JMF、ffmpeg等。JMF以前用過,過於老舊了,而且只支持32位系統,想用的話還得用32位的IDE,所以忽略。然后發現用opencv集成了ffmpeg,通過grabber.grab()方法就可以獲取。很簡單。

2.視頻顯示

一開始的想法,grabber.grab()獲取的是一幀一幀的圖片,那么可以再frame里加一個顯示圖片的label,每過十毫秒刷新一次圖片,這樣就起到了播放視頻的效果。但是遇到了問題

 

 

 

使用java.awt.Image 中的方法無法獲取grabber.grab()中的數據,強制類型轉換無效。后來查看OpenCVFrameGrabber的源碼。最后在Frame.Class里發現image的類型

 

 

 NIO與IO之間是有一些區別的,NIO要更優秀一點,可惜Java界面沒有

 

所以轉換思路,沒辦法在主窗口播放,那就在新建一個窗口,看起來有點別扭,但受限於技術水平,還是先把功能實現了。

javacv里有一個簡單的新建窗口方式

CanvasFrame canvas = new CanvasFrame("Camera");//新建一個窗口

通過源碼可以看到CanvasFrame是繼承了javax.swing.JFrame類的。使用這個類主要是它里面的showimage方法

 

 里面有適合的數據類型。

3.窗口問題

 使用新建窗口顯示視頻時,關閉視頻播放窗口,主窗口也會關閉。

原來關閉窗口使用的是System.exit(0);這個方法直接終止了虛擬機。后來改成了dispose()方法(需要.setDefaultCloseOperation設置為JFrame.DISPOSE_ON_CLOSE)

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM