OpenCV -2 -人臉識別

OpenCV -2 -人臉識別

使用語言:Java 1.8
操作系統:windows x64
OpenCV:4.1.1


人臉識別的介紹

人臉識別是一個平常很經常看到,卻又很不瞭解的技術。各種手機的攝像頭,自拍或者監控上面經常會出現這個東東,但是關於如何實現的,可能瞭解的並不多,只是覺得挺高級的。

這裏需要一個小抄:

人臉識別(Face Recognition)是一種依據人的面部特徵(如統計或幾何特徵等),自動進行身份識別的一種生物識別技術,又稱爲面像識別、人像識別、相貌識別、面孔識別、面部識別等。通常我們所說的人臉識別是基於光學人臉圖像的身份識別與驗證的簡稱。

人臉識別基本步驟:圖像採集、圖像預處理、特徵提取、降維、特徵匹配。

實現人臉識別【理論】

  • 這裏爲了完成人臉識別,使用的是OpenCV中的目標檢測模塊:opencv_objdetect ;

就是一個依據輸入圖片,和分類器模型,然後進行檢查匹配的東西

  • OpenCV有自帶的人臉Haar特徵分類器:\data\ haarcascades目錄下的haarcascade_frontalface_alt.xml;

這個haarcascades目錄下還有人的全身,眼睛,嘴脣的Haar分類器。

  • 實現的過程就是:在對應的圖片中,按照訓練好的人臉識別特徵分類器,使用OpenCV的檢測模塊功能賽選出來。

這裏說明一下,特徵分類器並不是深度學習或者機器學習、神經網絡之類的東西,還是有一點區別的。後者那些高級多了。

使用OpenCV來實現人臉識別【直接上代碼實現】

代碼如下:

public class faceTest extends JPanel {
  /** 參數爲需要進行識別的圖像 **/
public static Mat detectFace(Mat img) {
		
        System.out.println("Running DetectFace ... ");
        // 從配置文件lbpcascade_frontalface.xml中創建一個人臉識別器,該文件位於opencv安裝目錄中
        CascadeClassifier faceDetector = new CascadeClassifier("D:\\OpenCV\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");

        // 在圖片中檢測人臉
        MatOfRect faceDetections = new MatOfRect();
        // 灰度化 只是爲了加快識別數據和準確性
        Mat imgTmp = new Mat();
        Imgproc.cvtColor(img, imgTmp, Imgproc.COLOR_BGR2GRAY);
		//進行識別分類
        faceDetector.detectMultiScale(imgTmp, faceDetections);

        System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));
		//遍歷特徵分類器 的結構 【這裏就是每一個的臉了】
        Rect[] rects = faceDetections.toArray();
        Random r = new Random();
        int i =0;  //只是個記數用的
        if (rects != null && rects.length >= 1) {
            for (Rect rect : rects) {
                System.out.println(i++);
                //畫矩形
                Imgproc.rectangle(img, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0), 1);
                //保存一下識別到的臉
                 save(img, rect, "D:\\ijworkspace\\meaen_test\\data\\" + r.nextInt(2000) + ".jpg");

                //年齡性別識別  並 畫在圖片上
                String age = OpenCVTools.predict_age(img.submat(rect));
                System.out.println(age);
                Imgproc.putText(img, "age:"+age, new Point(rect.x, rect.y), Imgproc.FONT_HERSHEY_PLAIN,0.8, new Scalar(0, 255, 0), 1);
                String sex = OpenCVTools.predict_gender(img.submat(rect));
                System.out.println(sex);
                Imgproc.putText(img, "sex:"+sex, new Point(rect.x, rect.y+10), Imgproc.FONT_HERSHEY_PLAIN,0.8, new Scalar(0, 255, 0), 1);

                //圖像對比
                Mat faceImg = Imgcodecs.imread("D:\\ijworkspace\\meaen_test\\data\\1625.jpg");
                if(OpenCVTools.compare_image(faceImg,img.submat(rect)) > 0.9 ){
                    Imgproc.putText(img, "匹配:"+"WuBinHong", new Point(rect.x, rect.y+20), Imgproc.FONT_HERSHEY_PLAIN,0.8, new Scalar(0, 255, 0), 1);
                }
            }
        }
        return img;
    }
    
     /**
     * opencv將人臉進行截圖並保存
     * @param img
     */
    private static void save(Mat img, Rect rect, String outFile) {
        Mat sub = img.submat(rect);
        Mat mat = new Mat();
        Size size = new Size(300, 300);
        Imgproc.resize(sub, mat, size);
        Imgcodecs.imwrite(outFile, mat);
    }

 public static void main(String[] args) {
        try {
            //加載opencv庫  地址爲我本地上下文環境
            System.load("D:\\OpenCV\\opencv\\build\\java\\x64\\opencv_java411.dll");
            Mat img = Imgcodecs.imread("D:\\ijworkspace\\meaen_test\\data\\test6.jpg");
            Imgcodecs.imwrite("D:\\ijworkspace\\meaen_test\\data\\result.jpg",detectFace(img));
            img.release();
        } catch (Exception e) {
            System.out.println("有問題");
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            System.out.println(sw.toString());
        } finally {
            System.out.println("Exit");
        }
    }
}

以上的代碼中的年齡性別預測的代碼塊可以直接註釋,這個在後一個章節的時候會介紹。

圖像對比

上面代碼中有部分圖像對比的代碼,這裏提出來說明一下

這個是使用了基於直方圖的圖片相似度計算函數,這個對比的識別度條件限制很高。

是直接圖片對比,並不是預測。

/**
     *  基於直方圖的圖片相似度計算函數
     * CV_COMP_CORREL 相關性比較
     * CV_COMP_CHISQR  卡方比較
     * CV_COMP_BHATTACHARYYA 巴氏距離
     * CV_COMP_INTERSECT 十字交叉性
     * @param img_1
     * @param img_2
     * @return
     */
    public static double compare_image(Mat img_1, Mat img_2) {
        // 灰度化
        Mat mat_1 = new Mat();
        Imgproc.cvtColor(img_1, mat_1, Imgproc.COLOR_BGR2GRAY);
        Mat mat_2 = new Mat();
        Imgproc.cvtColor(img_2, mat_2, Imgproc.COLOR_BGR2GRAY);
        Mat hist_1 = new Mat();
        Mat hist_2 = new Mat();

        //顏色範圍
        MatOfFloat ranges = new MatOfFloat(0f, 256f);
        //直方圖大小, 越大匹配越精確 (越慢)
        MatOfInt histSize = new MatOfInt(1000);

        Imgproc.calcHist(Arrays.asList(mat_1), new MatOfInt(0), new Mat(), hist_1, histSize, ranges);
        Imgproc.calcHist(Arrays.asList(mat_2), new MatOfInt(0), new Mat(), hist_2, histSize, ranges);
// 這裏的輸出也是爲了更好的在玩的時候,看出對比的情況。反正跟我們靠感覺對比不一樣,我是看不懂了╮(╯_╰)╭
//        Imgcodecs.imwrite("D:\\ijworkspace\\meaen_test\\data\\1.jpg", hist_1);
//        Imgcodecs.imwrite("D:\\ijworkspace\\meaen_test\\data\\2.jpg", hist_2);
        // CORREL 相關係數
        double res = Imgproc.compareHist(hist_1, hist_2, Imgproc.CV_COMP_CORREL);

        return res;
    }

小結

這裏簡單試了一下,使用OpenCV的人臉分類器,進行人臉識別,然後再臉上畫個框框顯示出來。並保存操作後的圖像信息到本地進行查看。

其中有一小段,圖片對比的,可以截取人臉作爲對比圖像進行測試。【相差一點就對比不出來了的 ╮(╯_╰)╭】


2019-11-01 小杭

目前識別只是人臉簡單識別,不涉及預測。識別率也就那樣子,還行的吧!

之後學習的就是,年齡性別預測,以及深度學習訓練之類的。最後可能還是需要慢慢研究一下對應的識別算法和模型學習算法,雖然肯定是看不懂的。ε=(´ο`*)))唉


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章