java利用opencv截取人脸, 控制最终大小在10k之内
-
到官网下载对应版本的Windows版本,我这里下载的是4.5.3版本,下载后可以得到名为opencv的文件夹
-
在opencv\build\java\opencv-453.jar中找到需要引入的jar包
在项目新建lib文件夹把该jar包放到该文件夹下
添加maven依赖
<dependency> <groupId>org.opencv</groupId> <artifactId>opencv</artifactId> <version>4.5.3</version> <scope>system</scope> <systemPath>${basedir}/lib/opencv-453.jar</systemPath> </dependency> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!--在打包插件中设置该值为true,会将本地jar也一起打包--> <includeSystemScope>true</includeSystemScope> </configuration> </plugin>
-
在resources下新建opencv文件夹,将opencv\build\java\x64\opencv_java453.dll和opencv\sources\data\haarcascades\haarcascade_frontalface_alt.xml文件放到该文件夹下
opencv_java453.dll是调用opencv的动态库文件,需要在使用前加载到jvm中
haarcascade_frontalface_alt.xml是opencv的一个人脸识别器
-
初始化---加载dll文件到jvm中
这里会将resources中的opencv_java453.dll和haarcascade_frontalface_alt.xml新建一个新的文件,避免打包后在resources找不到资源导致初始失败问题
@PostConstruct public void init(){ try{ String dirPath = "./opencv/"; File dir = new File(dirPath); dir.mkdir(); File dllFile = new File("./opencv/"+Core.NATIVE_LIBRARY_NAME + ".dll"); if( !dllFile.exists() ){ dllFile.createNewFile(); InputStream inputStream = this.getClass().getResourceAsStream("/opencv/" + Core.NATIVE_LIBRARY_NAME + ".dll"); BufferedInputStream bi = new BufferedInputStream(inputStream); FileOutputStream fos = new FileOutputStream("./opencv/"+Core.NATIVE_LIBRARY_NAME + ".dll"); byte[] by = new byte[1024]; int len = 0; while((len=bi.read(by))!=-1){ fos.write(by,0,len); } fos.close(); bi.close(); inputStream.close(); dllFile = new File("./opencv/"+Core.NATIVE_LIBRARY_NAME + ".dll"); } if (!dllFile.exists()) { log.error("找不到动态库 ".concat(dllFile.getCanonicalPath())); return; } System.load(dllFile.getCanonicalPath()); log.info("openCV load success"); }catch (Exception e){ e.printStackTrace(); log.error("openCV load fail"); } }
-
人脸识别并截取,控制最终图片大小在10k以内
/** * opencv实现人脸识别 * @param imagePath * @param outFile */ public boolean detectFace(String imagePath, String outFile) { try{ log.info("Running DetectFace ... "); File xmlFile = new File("./opencv/haarcascade_frontalface_alt.xml"); if( !xmlFile.exists() ){ InputStream inputStream = this.getClass().getResourceAsStream("/opencv/haarcascade_frontalface_alt.xml"); BufferedInputStream bi = new BufferedInputStream(inputStream); FileOutputStream fos = new FileOutputStream("./opencv/haarcascade_frontalface_alt.xml"); byte[] by = new byte[1024]; int len = 0; while((len=bi.read(by))!=-1){ fos.write(by,0,len); } fos.close(); bi.close(); inputStream.close(); xmlFile = new File("./opencv/haarcascade_frontalface_alt.xml"); } CascadeClassifier faceDetector = new CascadeClassifier(xmlFile.getCanonicalPath()); Mat image = Imgcodecs.imread(imagePath); // 在图片中检测人脸 MatOfRect faceDetections = new MatOfRect(); faceDetector.detectMultiScale(image, faceDetections); Rect[] rects = faceDetections.toArray(); if(rects != null && rects.length > 1){ log.error("超过一个脸"); return false; } // 在每一个识别出来的人脸周围画出一个方框 Rect rect = rects[0]; //上y和下y为总高度的百分之15 imageCut(imagePath, outFile, rect.x-2, (int)(rect.y-rect.height*0.15), rect.width, (int)(rect.height+rect.height*0.15)); log.info("人脸截取成功"); return true; }catch (Exception e){ log.error("人脸截取失败"); e.printStackTrace(); return false; } } /** * 裁剪图片并重新装换大小 * @param imagePath * @param posX * @param posY * @param width * @param height * @param outFile */ public 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 mat = new Mat(); Size size = new Size(100, (float)height/width*100); Imgproc.resize(sub, mat, size); //将人脸进行截图并保存 //灰度处理,灰度处理后可在最终大小上减少4-5k //Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY); Imgcodecs.imwrite(outFile, mat); }
-
测试
public static void main(String[] args) throws Exception { String sourceFile = "E:\\1.jpg"; String outputFile = "E:\\2.jpg"; OpenCVUtil.detectFace(sourceFile, outputFile); }
-
注意点
devtools依赖会和该jar包冲突,报出java.lang.UnsatisfiedLinkError的异常,删掉devtools依赖就不会报错
若打包后直接引用resources的文件会报错,引用绝对路径则不会