java+opencv實(shí)現(xiàn)人臉識(shí)別功能
背景:最近需要用到人臉識(shí)別,但又不花錢使用現(xiàn)有的第三方人臉識(shí)別接口,為此使用opencv結(jié)合java進(jìn)行人臉識(shí)別(ps:opencv是開源的,使用它來做人臉識(shí)別存在一定的誤差,效果一般)。
1.安裝opencv
官網(wǎng)地址:https://opencv.org/ , 由于官網(wǎng)下載速度是真的慢
百度網(wǎng)盤:
鏈接: https://pan.baidu.com/s/1RpsP-I7v8pP2dkqALDw7FQ
提取碼: pq7v
如果是官網(wǎng)下載,就無腦安裝就行了,安裝完畢后。
將圖一的兩個(gè)文件復(fù)制到圖二中。
從我網(wǎng)盤下載的,忽略這些。
2.在項(xiàng)目中引入pom依賴
<!-- opencv + javacv + ffmpeg--> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>ffmpeg</artifactId> <version>4.1-1.4.4</version> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.4.4</version> </dependency> <!-- https://mvnrepository.com/artifact/org.bytedeco.javacpp-presets/ffmpeg-platform --> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>ffmpeg-platform</artifactId> <version>4.1-1.4.4</version> </dependency> <!-- 視頻攝像頭 --> <!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform --> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.4.4</version> </dependency> <!-- https://mvnrepository.com/artifact/org.bytedeco.javacpp-presets/opencv-platform --> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv-platform</artifactId> <version>4.0.1-1.4.4</version> </dependency>
1.導(dǎo)入庫依賴
File --> Project Structure,點(diǎn)擊Modules,選擇需要使用opencv.jar的項(xiàng)目。
選擇直接opencv安裝路徑
2.java代碼demo
package org.Litluecat.utils; import org.apache.commons.lang.StringUtils; import org.opencv.core.*; import org.opencv.highgui.HighGui; import org.opencv.highgui.ImageWindow; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.CascadeClassifier; import org.opencv.videoio.VideoCapture; import org.opencv.videoio.VideoWriter; import org.opencv.videoio.Videoio; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Arrays; /** * 人臉比對(duì)工具類 * @author Litluecat * @Title: Opencv 圖片人臉識(shí)別、實(shí)時(shí)攝像頭人臉識(shí)別 **/ public class FaceVideo { private static final Logger log = LoggerFactory.getLogger(FaceVideo.class); private static final String endImgUrl = "C:\\Users\\lenovo\\Desktop\\"; /** * opencv的人臉識(shí)別xml文件路徑 */ private static final String faceDetectorXML2URL = "D:\\Sofeware\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml"; /** * opencv的人眼識(shí)別xml文件路徑 */ private static final String eyeDetectorXML2URL = "D:\\Sofeware\\opencv\\sources\\data\\haarcascades\\haarcascade_eye.xml"; /** * 直方圖大小,越大精度越高,運(yùn)行越慢 */ private static int Matching_Accuracy = 100000; /** * 初始化人臉探測器 */ private static CascadeClassifier faceDetector; /** * 初始化人眼探測器 */ private static CascadeClassifier eyeDetector; private static int i=0; static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); faceDetector = new CascadeClassifier(faceDetectorXML2URL); eyeDetector = new CascadeClassifier(eyeDetectorXML2URL); } public static void main(String[] args) { log.info("開始人臉匹配"); long begin = System.currentTimeMillis(); // 1- 從攝像頭實(shí)時(shí)人臉識(shí)別,識(shí)別成功保存圖片到本地 try{ getVideoFromCamera(endImgUrl + "2.jpg"); //僅用于強(qiáng)制拋異常,從而關(guān)閉GUI界面 Thread.sleep(1000); int err = 1/0; // 2- 比對(duì)本地2張圖的人臉相似度 (越接近1越相似) // double compareHist = FaceVideo.compare_image(endImgUrl + "test1.jpg" , endImgUrl + "face.jpg"); // log.info("匹配度:{}",compareHist); // if (compareHist > 0.72) { // log.info("人臉匹配"); // } else { // log.info("人臉不匹配"); // } }catch (Exception e){ log.info("開始強(qiáng)制關(guān)閉"); log.info("人臉匹配結(jié)束,總耗時(shí):{}ms",(System.currentTimeMillis()-begin)); System.exit(0); } } /** * OpenCV-4.1.1 從攝像頭實(shí)時(shí)讀取 * @param targetImgUrl 比對(duì)身份證圖片 * @return: void * @date: 2019年8月19日 17:20:13 */ public static void getVideoFromCamera(String targetImgUrl) { //1 如果要從攝像頭獲取視頻 則要在 VideoCapture 的構(gòu)造方法寫 0 VideoCapture capture = new VideoCapture(0); Mat video = new Mat(); int index = 0; if (capture.isOpened()) { while(i<3) { // 匹配成功3次退出 capture.read(video); HighGui.imshow("實(shí)時(shí)人臉識(shí)別", getFace(video, targetImgUrl)); //窗口延遲等待100ms,返回退出按鍵 index = HighGui.waitKey(100); //當(dāng)退出按鍵為Esc時(shí),退出窗口 if (index == 27) { break; } } }else{ log.info("攝像頭未開啟"); } //該窗口銷毀不生效,該方法存在問題 HighGui.destroyAllWindows(); capture.release(); return; } /** * OpenCV-4.1.0 人臉識(shí)別 * @param image 待處理Mat圖片(視頻中的某一幀) * @param targetImgUrl 匹配身份證照片地址 * @return 處理后的圖片 */ public static Mat getFace(Mat image, String targetImgUrl) { MatOfRect face = new MatOfRect(); faceDetector.detectMultiScale(image, face); Rect[] rects=face.toArray(); log.info("匹配到 "+rects.length+" 個(gè)人臉"); if(rects != null && rects.length >= 1) { i++; if(i==3) { // 獲取匹配成功第3次的照片 Imgcodecs.imwrite(endImgUrl + "face.jpg", image); FaceVideoThread faceVideoThread = new FaceVideoThread(targetImgUrl , endImgUrl + "face.jpg"); new Thread(faceVideoThread,"人臉比對(duì)線程").start(); } } return image; } /** * 人臉截圖 * @param img * @return */ public static String face2Img(String img) { String faceImg = null; Mat image0 = Imgcodecs.imread(img); Mat image1 = new Mat(); // 灰度化 Imgproc.cvtColor(image0, image1, Imgproc.COLOR_BGR2GRAY); // 探測人臉 MatOfRect faceDetections = new MatOfRect(); faceDetector.detectMultiScale(image1, faceDetections); // rect中人臉圖片的范圍 for (Rect rect : faceDetections.toArray()) { faceImg = img+"_.jpg"; // 進(jìn)行圖片裁剪 imageCut(img, faceImg, rect.x, rect.y, rect.width, rect.height); } if(null == faceImg){ log.info("face2Img未識(shí)別出該圖像中的人臉,img={}",img); } return faceImg; } /** * 人臉比對(duì) * @param img_1 * @param img_2 * @return */ public static double compare_image(String img_1, String img_2) { Mat mat_1 = conv_Mat(img_1); Mat mat_2 = conv_Mat(img_2); Mat hist_1 = new Mat(); Mat hist_2 = new Mat(); //顏色范圍 MatOfFloat ranges = new MatOfFloat(0f, 256f); //直方圖大小, 越大匹配越精確 (越慢) MatOfInt histSize = new MatOfInt(Matching_Accuracy); 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); // CORREL 相關(guān)系數(shù) double res = Imgproc.compareHist(hist_1, hist_2, Imgproc.CV_COMP_CORREL); return res; } /** * 灰度化人臉 * @param img * @return */ public static Mat conv_Mat(String img) { if(StringUtils.isBlank(img)){ return null; } Mat image0 = Imgcodecs.imread(img); Mat image1 = new Mat(); //Mat image2 = new Mat(); // 灰度化 Imgproc.cvtColor(image0, image1, Imgproc.COLOR_BGR2GRAY); //直方均勻 //Imgproc.equalizeHist(image1, image2); // 探測人臉 MatOfRect faceDetections = new MatOfRect(); faceDetector.detectMultiScale(image1, faceDetections); //探測人眼 // MatOfRect eyeDetections = new MatOfRect(); // eyeDetector.detectMultiScale(image1, eyeDetections); // rect中人臉圖片的范圍 Mat face = null; for (Rect rect : faceDetections.toArray()) { //給圖片上畫框框 參數(shù)1是圖片 參數(shù)2是矩形 參數(shù)3是顏色 參數(shù)四是畫出來的線條大小 //Imgproc.rectangle(image0,rect,new Scalar(0,0,255),2); //輸出圖片 //Imgcodecs.imwrite(img+"_.jpg",image0); face = new Mat(image1, rect); } if(null == face){ log.info("conv_Mat未識(shí)別出該圖像中的人臉,img={}",img); } return face; } }
這邊的人臉識(shí)別是另外其線程進(jìn)行比對(duì),代碼如下。
package org.Litluecat.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FaceVideoThread implements Runnable{ private static final Logger log = LoggerFactory.getLogger(FaceVideoThread.class); private String oneImgUrl = null; private String otherImgUrl = null; public FaceVideoThread(String oneImgUrl, String otherImgUrl){ this.oneImgUrl = oneImgUrl; this.otherImgUrl = otherImgUrl; } @Override public void run() { try { double compareHist = FaceVideo.compare_image(oneImgUrl , otherImgUrl); log.info("匹配度:{}",compareHist); if (compareHist > 0.72) { log.info("人臉匹配"); } else { log.info("人臉不匹配"); } } catch (Exception e) { e.printStackTrace(); } } }
提醒:如果運(yùn)行異常,請(qǐng)?zhí)砑幽鉶pencv的安裝地址-Djava.library.path=D:\Sofeware\opencv\build\java\x64;
總結(jié):java+opencv做人臉識(shí)別的精度不夠,我也是有待學(xué)習(xí),如果大家有更好的方式,能將opencv更好的展現(xiàn)出來,并達(dá)到更精準(zhǔn)的人臉識(shí)別,請(qǐng)分享給我,謝謝。
到此這篇關(guān)于java+opencv實(shí)現(xiàn)人臉識(shí)別的文章就介紹到這了,更多相關(guān)java opencv人臉識(shí)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java web請(qǐng)求和響應(yīng)中出現(xiàn)中文亂碼問題的解析
這篇文章主要為大家解析了java web請(qǐng)求和響應(yīng)中出現(xiàn)中文亂碼問題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10Springboot中@RequestParam和@PathVariable的用法與區(qū)別詳解
這篇文章主要介紹了Springboot中@RequestParam和@PathVariable的用法與區(qū)別詳解,RESTful API設(shè)計(jì)的最佳實(shí)踐是使用路徑參數(shù)來標(biāo)識(shí)一個(gè)或多個(gè)特定資源,而使用查詢參數(shù)來對(duì)這些資源進(jìn)行排序/過濾,需要的朋友可以參考下2024-01-01SpringCloud持久層框架MyBatis Plus的使用與原理解析
MyBatisPlus為MyBatis的增強(qiáng)版,專注于簡化數(shù)據(jù)庫操作,提供自動(dòng)化CRUD、內(nèi)置分頁和樂觀鎖等功能,極大提升開發(fā)效率,在SpringCloud微服務(wù)架構(gòu)中,MyBatisPlus通過插件機(jī)制和自動(dòng)生成代碼功能,有效支持企業(yè)級(jí)應(yīng)用和分布式系統(tǒng)的開發(fā)2024-10-10idea環(huán)境下Maven無法正常下載pom中配置的包問題
這篇文章主要介紹了idea環(huán)境下Maven無法正常下載pom中配置的包的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06Spring Cloud Admin健康檢查 郵件、釘釘群通知的實(shí)現(xiàn)
這篇文章主要介紹了Spring Cloud Admin健康檢查 郵件、釘釘群通知的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08Spring?Data?JPA實(shí)現(xiàn)數(shù)據(jù)持久化過程詳解
Spring?Data?JPA是一個(gè)流行的Java持久化框架,它在Java應(yīng)用程序中提供了一種簡單、一致和易于使用的方式來訪問各種數(shù)據(jù)庫。本文將介紹Spring?Data?JPA的基本概念和用法并提供一個(gè)完整的實(shí)例,幫助您更好地理解它的使用方法和優(yōu)勢2023-05-05