准备工作

Linux生成libopencv_java460.so\opencv-460.jar\lbpcascade_frontalface.xml文件

opencv源码地址:https://github.com/opencv/opencv

下载4.6.0版本:Releases · opencv/opencv · GitHub

从git上找到对应版本号下载zip文件

 上传到Linux中并解压

unzip opencv-4.6.0.zip

mv opencv-4.6.0 /cloud/

cd /cloud/opencv-4.6.0/

mkdir build && cd build

接下来就是需要编译源码,这时候需要cmake命令,如果Linux自带的cmake版本低不好使或者是本机并没有装cmake那需要提前准备一下

wget https://cmake.org/files/v3.9/cmake-3.9.2.tar.gz

tar zxvf cmake-3.9.2.tar.gz

mv cmake-3.9.2 /cloud/

cd /cloud/cmake-3.9.2/

./configure

make

make install

cmake -version

# 检查一下版本,如果报错,可能是本机原来的cmake还有缓存,没替换过来需要执行以下 hash -r命令
# hash -r

# 这时候如果显示版本号为3.9.2就对了

cmake执行编译源码过程中会用到java环境和ant,没有的话也需要提前准备

yum -y install ant

ant -version

接下来编译源码

cd /cloud/opencv-4.6.0/build

cmake -D BUILD_SHARED_LIBS=OFF -D BUILD_TEST=OFF ..

 出现下面的ant: /bin/ant (ver 1.9.4)和java的信息说明命令执行成功过

--   Java:                          
--     ant:                         /bin/ant (ver 1.9.4)
--     JNI:                         /usr/java/jdk1.8.0_121/include /usr/java/jdk1.8.0_121/include/linux /usr/java/jdk1.8.0_121/include
--     Java wrappers:               YES
--     Java tests:                  YES
-- 
--   Install to:                    /usr/local
-- -----------------------------------------------------------------
-- 

接下来执行make命令,执行完成后会出现对应的so包和jar包

# 8核cpu 就写 j8
make -j8 & make

生成的libopencv_java460.so包位置

cd /cloud/opencv-4.6.0/build/lib

生成的opencv-460.jar包位置

cd /cloud/opencv-4.6.0/build/bin

生成的lbpcascade_frontalface.xml文件位置

cd /cloud/opencv-4.6.0/build/java_test/res/raw

准备工作完成

spring集成

把上一步的三个文件放到项目中,

因为我是maven管理的多模块项目,

人脸识别模块

在人脸识别模块添加jar包,把jar放到

人脸识别模块/src/main/resources/lib下

如果没有lib那就新建一个lib文件夹

pom引入jar依赖

<dependency>
    <groupId>com.opencv</groupId>
    <artifactId>opencv_java460</artifactId>
    <version>1</version>
    <scope>system</scope>
    <systemPath>${basedir}/src/main/resources/lib/opencv-460.jar</systemPath>
</dependency>

在build 的resources下忽略掉这个包,因为在war项目包中会引用,人脸识别模块就不要引用了

<resource>    
    <directory>src/main/resources</directory>
    <includes>
        <include>**/*.*</include>
    </includes>
    <excludes>
        <exclude>lib/*.jar</exclude>
    </excludes>
</resource>

Java代码


import java.util.Arrays;

import org.opencv.core.Mat;
import org.opencv.core.MatOfFloat;
import org.opencv.core.MatOfInt;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 人脸对比处理
 */
@Controller
public class FaceDetectorController {

	// 初始化人脸探测器
	static CascadeClassifier faceDetector;

	static {
		boolean isWin = false;
		if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
			isWin = true;
		}
		if (!isWin) {
			//路径不能包含中文  linux使用libopencv_java410.so
			String opencvDllName = null;
			try {
				opencvDllName = FaceDetectorController.class.getResource("/opencv/libopencv_java460.so").toURI().getRawPath();
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.load(opencvDllName);
			// xml路径不能包含中文
			String faceXml = null;
			try {
				faceXml = FaceDetectorController.class.getResource("/opencv/lbpcascade_frontalface.xml").toURI().getRawPath();
			} catch (Exception e) {
				e.printStackTrace();
			}
			faceDetector = new CascadeClassifier(faceXml);
		}
	}

	// 灰度化人脸
	private Mat conv_Mat(String img) {
		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()) {
			Mat face = new Mat(image1, rect);
			return face;
		}
		return null;
	}

	private 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(10000000);

		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 相关系数
		return Imgproc.compareHist(hist_1, hist_2, Imgproc.CV_COMP_CORREL);
	}

	/**
	 * 人脸对比
	 * @return
	 */
	@RequestMapping("faceDetector")
	@ResponseBody
	public String faceDetector() {
		try {
			//图片路径不能包含中文
			double compareHist = compare_image("1.jpg", "2.jpg");
			if (compareHist > 0.6) {
				return "人脸对比成功";
			} else {
				return "人脸不匹配";
			}
		} catch (Exception e) {
			return "人脸对比失败";
		}
	}
}

war模块

在war模块的resources下新建opencv文件夹并把so文件和xml文件放进去

plugin修改

<!--使用maven-war-plugin插件在编译时指定第三方jar包目录并引入-->
<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>3.2.0</version>
    <configuration>
        <webResources>
            <resource>
                <!-- 引入人脸识别模块的jar -->
                <directory>../face-service/src/main/resources/lib/</directory>
                <targetPath>WEB-INF/lib</targetPath>
                <includes>
                    <include>**/*.jar</include>
                </includes>
            </resource>
        </webResources>
    </configuration>
</plugin>

resource修改,避免maven打包对so文件的修改,需要配两个resources,分别配置filtering

<resource>
    <directory>src/main/${package.environment}</directory>
    <includes>
        <include>**/*.*</include>
    </includes>
    <targetPath>${project.basedir}/target/classes</targetPath>
    <filtering>true</filtering>
    <excludes>
        <exclude>opencv/*.*</exclude>
    </excludes>
</resource>
<resource>
    <directory>src/main/${package.environment}</directory>
    <includes>
        <include>opencv/*.*</include>
    </includes>
    <targetPath>${project.basedir}/target/classes</targetPath>
    <filtering>false</filtering>
</resource>

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐