您好,登錄后才能下訂單哦!
這篇文章主要介紹springboot集成opencv如何實現人臉識別功能,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
項目中檢測人臉圖片是否合法的功能,之前用的是百度的人臉識別接口,由于成本高昂不得不尋求替代方案。
OpenCV是一個基于BSD許可(開源)發行的跨平臺計算機視覺和機器學習軟件庫,可以運行在Linux、Windows、Android和Mac OS操作系統上。輕量級而且高效——由一系列 C 函數和少量 C++ 類構成,同時提供了Python、Java、MATLAB等語言的接口,實現了圖像處理和計算機視覺方面的很多通用算法。
由于項目是放在Linux系統中跑的,開發環境是Windows10,所以項目中涉及到opencv的要分兩套。
Windows安裝opencv
opencv官網下載安裝包https://opencv.org/releases/
我這里選擇的是4.1.1版本
分別下載了Windows版本和源碼
Windows環境下集成
安裝opencv,沒什么說的,指定一個路徑安裝即可,注意安裝路徑不能是中文。
項目中集成的三個關鍵點。
引入jar依賴
讀取OpenCV自帶的人臉識別特征XML文件
配置opencv的庫文件地址
關鍵點1:引入jar包
jar包位置在安裝路徑下的java文件夾中
兩種方式引入
方式一:idea添加jar
或者直接在Libraries中添加二者皆可。
方式二:將jar上傳至私服,在maven中引入
我這里是將jar上傳至私服,然后引用的。
注意Windows版的jar和Linux中的jar不一樣,二者要區分開來
通過Maven配置在不同環境下加載不同的jar
<profiles> <profile> <id>dev</id> <dependencies> <!-- 本地引用--> <!-- <dependency>--> <!-- <groupId>op</groupId>--> <!-- <artifactId>opencv</artifactId>--> <!-- <version>411</version>--> <!-- <scope>system</scope>--> <!-- <systemPath>--> <!-- ${project.basedir}/src/main/resources/opencv/windows/opencv-411.jar--> <!-- </systemPath>--> <!-- </dependency>--> <!-- 倉庫引用--> <dependency> <!-- 這里改成自己的倉庫地址--> <groupId>com.***.cloud.resource</groupId> <artifactId>opencv-window</artifactId> <version>411</version> </dependency> </dependencies> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <id>test</id> <dependencies> <dependency> <!-- 這里改成自己的倉庫地址--> <groupId>com.***.cloud.resource</groupId> <artifactId>opencv-linux</artifactId> <version>411</version> </dependency> </dependencies> </profile> </profiles>
關鍵點2:配置人臉識別特征XML文件的地址
在bootstrap.yml添加如下參數
# 函數庫地址 在 vm optionis中 配置 # windows地址: -Djava.library.path=D:\software\opencv\build\java\x64 # linux地址: -Djava.library.path=/usr/local/opencv-4.1.1/build/lib/ opencv: lib: linuxxmlpath: /usr/local/share/opencv4/haarcascades/haarcascade_frontalface_alt.xml windowxmlpath: D:\software\opencv\sources\data\haarcascades\haarcascade_frontalface_alt.xml
測試的方法中就直接寫死了
/** * 初始化人臉探測器 */ static CascadeClassifier faceDetector; static { String systemProperties = String.valueOf(System.getProperties()); log.info(systemProperties); System.loadLibrary(Core.NATIVE_LIBRARY_NAME); faceDetector = new CascadeClassifier("D:\\software\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml"); }
注意路徑!!
關鍵點3:配置opencv的庫文件地址
-Djava.library.path=D:\software\opencv\build\java\x64
這里其實指向的就是 該目錄下的 opencv_java411.dll 文件
(linux的配置見下文)
測試方法
package com.example.opencvdemo.test; import lombok.extern.slf4j.Slf4j; import org.opencv.core.*; import org.opencv.highgui.HighGui; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.CascadeClassifier; /** * @author aaron * @since 2021-06-07 */ @Slf4j public class FaceVideo { /** * 初始化人臉探測器 */ static CascadeClassifier faceDetector; static { String systemProperties = String.valueOf(System.getProperties()); log.info(systemProperties); System.loadLibrary(Core.NATIVE_LIBRARY_NAME); faceDetector = new CascadeClassifier("D:\\software\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml"); } public static void main(String[] args){ // 3- 本地圖片人臉識別,識別成功并保存人臉圖片到本地 String imgPath = "C:\\Users\\Administrator\\Pictures\\wang.jpg"; face(imgPath); } /** * OpenCV-4.1.1 圖片人臉識別 * * @return: void * @date: 2019年5月7日12:16:55 */ public static void face(String imgPath) { /** * 讀取本地 */ Mat image = Imgcodecs.imread(imgPath); if (image.empty()) { System.out.println("image 內容不存在!"); return; } // 3 特征匹配 MatOfRect face = new MatOfRect(); faceDetector.detectMultiScale(image, face); // 4 匹配 Rect 矩陣 數組 Rect[] rects = face.toArray(); System.out.println("匹配到 " + rects.length + " 個人臉"); // 5 為每張識別到的人臉畫一個圈 int i = 1; for (Rect rect : face.toArray()) { Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0), 3); imageCut(imgPath, "D:\\pictures\\" + i + ".jpg", rect.x, rect.y, rect.width, rect.height);// 進行圖片裁剪 i++; } // 6 展示圖片 HighGui.imshow("人臉識別", image); HighGui.waitKey(0); } /** * 裁剪人臉 * * @param imagePath * @param outFile * @param posX * @param posY * @param width * @param height */ public static void imageCut(String imagePath, String outFile, int posX, int posY, int width, int height) { // 原始圖像 Mat image = Imgcodecs.imread(imagePath); // 截取的區域:參數,坐標X,坐標Y,截圖寬度,截圖長度 Rect rect = new Rect(posX, posY, width, height); // 兩句效果一樣 Mat sub = image.submat(rect); // Mat sub = new Mat(image,rect); Mat mat = new Mat(); Size size = new Size(width, height); Imgproc.resize(sub, mat, size);// 將人臉進行截圖并保存 Imgcodecs.imwrite(outFile, mat); System.out.println(String.format("圖片裁切成功,裁切后圖片文件為: %s", outFile)); } }
注意!Mat image = Imgcodecs.imread(imgPath);
imgPath中不能帶有中文! opencv安裝路徑中如果有中文的話就會報錯。
集成到Springboot
package com.example.opencvdemo.util; import com.example.opencvdemo.exception.PublicException; import com.example.opencvdemo.result.ErrorCode; import com.google.common.primitives.Bytes; import lombok.extern.slf4j.Slf4j; import org.opencv.core.*; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.objdetect.CascadeClassifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.List; /** * @author aaron * @since 2021-06-07 */ @Component @Slf4j public class OpenCvUtils implements CommandLineRunner { @Value("${opencv.lib.linuxxmlpath}") private String linuxXmlPath; @Value("${opencv.lib.windowxmlpath}") private String windowXmlPath; /** * 人臉探測器對象 */ static CascadeClassifier faceDetector; /** * 判斷是否是Windows系統 */ private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win"); /** * 監測圖片是否合法,是否只有一張臉 */ public static void checkFace(String pictureUrl) throws Exception { // //將在線圖片保存為本地圖片 // String imgPath = saveLocal(pictureUrl); // //本地圖片 // File file = new File(imgPath); // FileInputStream fileInputStream = new FileInputStream(file); // ByteArrayOutputStream out = new ByteArrayOutputStream(); // byte[] localBuff = new byte[fileInputStream.available()]; // fileInputStream.read(localBuff); // out.write(localBuff); // log.info("本地圖片:"+localBuff.length); //在線圖片 URL url = new URL(pictureUrl); URLConnection uc = url.openConnection(); InputStream inputStream = uc.getInputStream(); ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); byte[] buff = new byte[1024]; int rc; while ((rc = inputStream.read(buff, 0, 1024)) > 0) { swapStream.write(buff, 0, rc); } byte[] urlBuff = swapStream.toByteArray(); log.info("在線圖片:"+urlBuff.length); List<Byte> bs = new ArrayList<>(); bs.addAll(Bytes.asList(urlBuff)); log.info("buffer長度"+bs.size()); /** * 不好使 */ // Mat image = Converters.vector_char_to_Mat(bs); // Mat image = Converters.vector_uchar_to_Mat(bs); /** * 讀取本地 */ // Mat image = Imgcodecs.imread(imgPath); /** * 讀數據流 */ Mat image = Imgcodecs.imdecode(new MatOfByte(urlBuff), Imgcodecs.IMREAD_UNCHANGED); if (image.empty()) { log.error("image 內容不存在!"); return; } // 3 特征匹配 MatOfRect face = new MatOfRect(); faceDetector.detectMultiScale(image, face); // 4 匹配 Rect 矩陣 數組 Rect[] rects = face.toArray(); System.out.println("匹配到 " + rects.length + " 個人臉"); // delFile(imgPath); if (rects.length == 0) { throw new PublicException(ErrorCode.A0430.getCode(), "沒有監測到人臉"); } else if (rects.length > 1) { throw new PublicException(ErrorCode.A0430.getCode(), "檢測到圖片有多張人臉,請重新上傳"); } } public static String saveLocal(String pictureUrl) throws IOException { URL url = new URL(pictureUrl); URLConnection uc = url.openConnection(); InputStream inputStream = uc.getInputStream(); String[] value = pictureUrl.split("/"); String firstFilePath = "D:\\pictures\\"; if (!IS_WINDOWS) { firstFilePath = "/tmp/tmp-picture/"; } String fileName = firstFilePath + value[value.length - 1]; FileOutputStream out = new FileOutputStream(fileName); int j = 0; while ((j = inputStream.read()) != -1) { out.write(j); } inputStream.close(); return fileName; } /** * Callback used to run the bean. * * @param args incoming main method arguments * @throws Exception on error */ @Override public void run(String... args){ String systemProperties = String.valueOf(System.getProperties()); log.info(systemProperties); System.loadLibrary(Core.NATIVE_LIBRARY_NAME); String path = ""; //如果是window系統取出路徑開頭的/ if (IS_WINDOWS) { path = windowXmlPath; }else{ path = linuxXmlPath; } /** * 初始化人臉探測器 */ faceDetector = new CascadeClassifier(path); log.info("==========初始化人臉探測器成功==========="); } }
OpenCV 提供的 API 是直接根據路徑讀取圖片的,所以最開始的時候我是把圖片保存到本地在讀取才成功的,但是這種方式太憨了點,在實際生產環境中,大部分情況下都是直接讀取網絡圖片。在內存就完成圖片和 opencv 的 Mat 對象的轉換。這里代碼中已經解決了url地址圖片轉化的問題。
這里附上解決該問題的博客 傳送門
Linux平臺須要咱們手動編譯,下載opencv-4.1.1.zip,解壓到/user/local目錄下,而后編譯
yum install ant gcc gtk2-devel pkgconfig zlib-devel
安裝unzip命令
yum install -y unzip zip
解壓命令
unzip opencv-4.1.1.zip
yum groupinstall "Development Tools"
安裝cmake
查看cmake當前版本
cmake --version
yum -y install wget
下載獲得cmake-3.9.2源碼
wget https://cmake.org/files/v3.9/cmake-3.9.2.tar.gz
解壓、安裝新版本
tar -xvf cmake-3.9.2.tar.gz cd cmake-3.9.2 ./configure sudo make && make install
cd /usr/local/opencv-4.1.1 mkdir build cd build cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TESTS=OFF .. make -j8 sudo make install
對應的jar和.so文件在
/usr/local/share/java/opencv4/
人臉識別特征XML文件的地址
/usr/local/share/opencv4/haarcascades/haarcascade_frontalface_alt.xml
jar 啟動命令添加Vm options
nohup java -jar -Djava.library.path=/usr/local/opencv-4.1.1/build/lib/ opencv-demo-1.0.jar > logs/opencv-demo-1.0.log 2>&1 &
項目代碼已上傳至github,可通過web接口測試,也可用main方法測試。
以上是“springboot集成opencv如何實現人臉識別功能”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。