java 集成免费虹软人脸识别 SDK,实现人脸识别认证功能

news2024/10/12 14:20:04

系列文章目录

  1. 引入本地 jar 包教程: https://blog.csdn.net/demo_yo/article/details/132495029

文章目录

  • 系列文章目录
  • 前言
  • 一、SDK 下载
  • 二、SDK 集成
    • 1、jar 依赖包
    • 2、dll 链接文件
  • 三、API 集成
    • 1、yaml 配置
    • 2、Properties 配置类
    • 3、Factory 工厂类
    • 4、Service 服务类
    • 5、服务类响应实体
    • 6、API 方法类
    • 7、文件工具类


前言

本文详细介绍了 java 集成免费虹软人脸识别的详细流程,从 SDK 下载到 SDK 的集成,以及 API 的封装策略。


一、SDK 下载

  1. 进入虹软开发者中心:https://ai.arcsoft.com.cn/ucenter/resource/build/index.html#/index

  2. 选择免费SDK:
    在这里插入图片描述

  3. 创建应用:
    在这里插入图片描述

  4. 下载SDK:
    在这里插入图片描述

二、SDK 集成

1、jar 依赖包

将将压缩包中的 jar 包,放置在 resource 文件夹下的 lib 文件夹中。
在这里插入图片描述
在 pom.xml 中引入本地依赖:

<dependency>
	<groupId>com.arcsoft</groupId>
	<artifactId>json</artifactId>
	<version>1.0</version>
	<scope>system</scope>
	<systemPath>${project.basedir}/src/main/resources/lib/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
</dependency>

关于本地 jar 包的引用方式说明,请转 引入本地 jar 包教程 https://blog.csdn.net/demo_yo/article/details/132495029

2、dll 链接文件

将压缩包中的 WIN64 dll 动态链接文件,放置在项目根目录下创建的 lib 文件夹下。
在这里插入图片描述
将在人脸识别引擎工厂类中引用改路径,用于引擎加载。如下:

// 加载引擎
FaceEngine faceEngine = new FaceEngine(System.getProperty("user.dir") + File.separator + "lib" + File.separator + "WIN64");

三、API 集成

1、yaml 配置

# 人脸认证引擎配置
face-engine:
  # 应用id
  app-id: xxxxxxxxxxxxxxxxx
  # sdk密匙
  sdk-key: xxxxxxxxxxxxxxxxx
  # 人脸对比阀值(建议0.8)
  face-similar-score: 0.8
  # RGB活体检测阀值(建议0.5)
  rgb-threshold: 0.5
  # IR活体检测阀值(建议0.7)
  ir-threshold: 0.7

2、Properties 配置类

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * 人脸认证引擎配置
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "face-engine")
public class FaceEngineProperties {

	/**
	 * appId
	 */
	private String appId;

	/**
	 * sdkKey
	 */
	private String sdkKey;

	/**
	 * 人脸对比阀值
	 */
	private Float faceSimilarScore;

	/**
	 * RGB活体检测阀值
	 */
	private Float rgbThreshold;

	/**
	 * IR活体检测阀值
	 */
	private Float irThreshold;

}

3、Factory 工厂类

import com.arcsoft.face.ActiveFileInfo;
import com.arcsoft.face.EngineConfiguration;
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.FunctionConfiguration;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.enums.ErrorInfo;
import com.whitemeen.magic.modules.demo.faceengine.config.FaceEngineProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
@RequiredArgsConstructor
public class FaceEngineFactory {

	private static final String FACE_ENGINE_KEY = "face_engine_key";

	private static final String FUNCTION_CONFIGURATION_KEY = "function_configuration_key";

	private ConcurrentHashMap<String, FaceEngine> faceEngineMap = new ConcurrentHashMap<>(); // 引擎Bean

	private ConcurrentHashMap<String, FunctionConfiguration> functionConfigurationMap = new ConcurrentHashMap<>(); // 引擎配置

	private final FaceEngineProperties faceEngineProperties;

	/**
	 * 在bean初始化后进行引擎初始化
	 */
	@PostConstruct
	public void init() {
		log.info("进入人脸引擎初始化");
		// 加载引擎
		FaceEngine faceEngine = new FaceEngine(System.getProperty("user.dir") + File.separator + "lib" + File.separator + "WIN64");
		// 激活引擎
		int errorCode = faceEngine.activeOnline(faceEngineProperties.getAppId(), faceEngineProperties.getSdkKey());

		if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
			log.error("人脸引擎激活失败");
			return;
		}

		ActiveFileInfo activeFileInfo = new ActiveFileInfo();
		errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
		if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
			log.error("获取激活文件信息失败");
			return;
		}

		// 引擎配置
		EngineConfiguration engineConfiguration = new EngineConfiguration();
		engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
		engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
		engineConfiguration.setDetectFaceMaxNum(10);
		engineConfiguration.setDetectFaceScaleVal(16);
		// 功能配置
		FunctionConfiguration functionConfiguration = new FunctionConfiguration();
		functionConfiguration.setSupportAge(true);
		functionConfiguration.setSupportFace3dAngle(true);
		functionConfiguration.setSupportFaceDetect(true);
		functionConfiguration.setSupportFaceRecognition(true);
		functionConfiguration.setSupportGender(true);
		functionConfiguration.setSupportLiveness(true);
		functionConfiguration.setSupportIRLiveness(true);
		engineConfiguration.setFunctionConfiguration(functionConfiguration);

		// 初始化引擎
		errorCode = faceEngine.init(engineConfiguration);

		if (errorCode != ErrorInfo.MOK.getValue()) {
			log.error("初始化人脸引擎失败");
			return;
		}

		// 将引擎放入map
		faceEngineMap.put(FACE_ENGINE_KEY, faceEngine);
		// 将引擎配置放入map
		functionConfigurationMap.put(FUNCTION_CONFIGURATION_KEY, functionConfiguration);
		log.info("人脸引擎初始化完成");
	}

	/**
	 * 工厂方法
	 *
	 * @return 人脸引擎
	 */
	public FaceEngine getFaceEngine() {
		return faceEngineMap.get(FACE_ENGINE_KEY);
	}

	/**
	 * 工厂方法
	 *
	 * @return 引擎配置
	 */
	public FunctionConfiguration getFunctionConfiguration() {
		return functionConfigurationMap.get(FUNCTION_CONFIGURATION_KEY);
	}

}

4、Service 服务类

import com.arcsoft.face.*;
import com.arcsoft.face.enums.ErrorInfo;
import com.arcsoft.face.toolkit.ImageInfo;
import com.whitemeen.magic.modules.demo.faceengine.factory.FaceEngineFactory;
import com.whitemeen.magic.modules.demo.faceengine.model.FaceEngineR;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;

@Slf4j
@Component
@RequiredArgsConstructor
public class FaceEngineService {

	private final FaceEngineFactory faceEngineFactory;

	/**
	 * 人脸认证
	 * <p>
	 * 建议待检测的图像人脸角度上、下、左、右转向小于30度;
	 * 图片中人脸尺寸不小于50 x 50像素;
	 * 图片大小小于10MB;
	 *
	 * @param authImageBytes   认证的图片字节
	 * @param localImageBytes  人脸库的图片字节
	 * @param faceSimilarScore 人脸对比阀值(范围为[0~1],生活照推荐:0.80,证件照推荐:0.82)
	 * @param rgbThreshold     RGB活体检测阀值(范围为[0~1],推荐:0.5)
	 * @param irThreshold      IR活体检测阀值	(范围为[0~1],推荐:0.7)
	 * @return 认证结果
	 */
	public FaceEngineR compareFace(byte[] authImageBytes, byte[] localImageBytes, float faceSimilarScore, float rgbThreshold, float irThreshold) {
		// 获取引擎
		FaceEngine faceEngine = faceEngineFactory.getFaceEngine();

		int errorCode = 0; // 错误码

		//人脸检测
		ImageInfo imageInfo = getRGBData(authImageBytes);
		List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
		errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
		log.info("人脸检测数据:{}", faceInfoList);
		log.info("[errorCode] = {}", errorCode);
		if (errorCode == ErrorInfo.MERR_ASF_EX_INVALID_FACE_INFO.getValue()) {
			log.info("无效的脸部信息:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("未检测到人脸");
		} else if (errorCode != ErrorInfo.MOK.getValue()) {
			log.info("人脸检测异常:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("人脸检测异常:[errorCode] = " + errorCode);
		}

		//特征提取
		FaceFeature faceFeature = new FaceFeature();
		errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
		log.info("人脸特征值大小:{}", faceFeature.getFeatureData().length);
		if (errorCode != ErrorInfo.MOK.getValue()) {
			log.info("人脸特征提取异常:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("人脸特征提取异常:[errorCode] = " + errorCode);
		}

		//人脸检测2
		ImageInfo imageInfo2 = getRGBData(localImageBytes);
		List<FaceInfo> faceInfoList2 = new ArrayList<FaceInfo>();
		errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2);
		log.info("人脸库人脸检测数据:{}", faceInfoList2);
		log.info("[errorCode] = {}", errorCode);
		if (errorCode == ErrorInfo.MERR_ASF_EX_INVALID_FACE_INFO.getValue()) {
			log.info("人脸库无效的脸部信息:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("人脸库未检测到人脸");
		} else if (errorCode != ErrorInfo.MOK.getValue()) {
			log.info("人脸库人脸检测异常:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("人脸库人脸检测异常:[errorCode] = " + errorCode);
		}

		//特征提取2
		FaceFeature faceFeature2 = new FaceFeature();
		errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2.get(0), faceFeature2);
		log.info("人脸库特征值大小:{}", faceFeature2.getFeatureData().length);
		if (errorCode != ErrorInfo.MOK.getValue()) {
			log.info("人脸库人脸特征提取异常:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("人脸库人脸特征提取异常:[errorCode] = " + errorCode);
		}

		//特征比对
		FaceFeature targetFaceFeature = new FaceFeature();
		targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
		FaceFeature sourceFaceFeature = new FaceFeature();
		sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
		FaceSimilar faceSimilar = new FaceSimilar();

		errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
		log.info("相似度:{}", faceSimilar.getScore());
		if (errorCode != ErrorInfo.MOK.getValue()) {
			log.info("人脸特征对比异常:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("人脸特征对比异常:[errorCode] = " + errorCode);
		}
		//相识度分数对比
		if (faceSimilar.getScore() < faceSimilarScore) {
			return FaceEngineR.failed("人脸对比未通过");
		}

		//设置活体测试
		errorCode = faceEngine.setLivenessParam(rgbThreshold, irThreshold);
		if (errorCode != ErrorInfo.MOK.getValue()) {
			log.info("活体测试异常:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("活体测试异常:[errorCode] = " + errorCode);
		}
		//人脸属性检测
		FunctionConfiguration configuration = new FunctionConfiguration();
		configuration.setSupportAge(true);
		configuration.setSupportFace3dAngle(true);
		configuration.setSupportGender(true);
		configuration.setSupportLiveness(true);
		errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, configuration);
		if (errorCode != ErrorInfo.MOK.getValue()) {
			log.info("人脸属性检测异常:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("人脸属性检测异常:[errorCode] = " + errorCode);
		}

		//3D信息检测
		List<Face3DAngle> face3DAngleList = new ArrayList<Face3DAngle>();
		errorCode = faceEngine.getFace3DAngle(face3DAngleList);
		log.info("3D角度:{}", face3DAngleList.get(0).getPitch() + ",{}", face3DAngleList.get(0).getRoll() + ",{}", face3DAngleList.get(0).getYaw());
		if (errorCode != ErrorInfo.MOK.getValue()) {
			log.info("3D信息检测异常:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("3D信息检测异常:[errorCode] = " + errorCode);
		}

		//活体检测
		List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
		errorCode = faceEngine.getLiveness(livenessInfoList);
		if (errorCode != ErrorInfo.MOK.getValue()) {
			log.info("活体检测异常:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("活体检测异常:[errorCode] = " + errorCode);
		}
		log.info("活体:{}", livenessInfoList.get(0).getLiveness());
		if (livenessInfoList.get(0).getLiveness() != 1) {
			return FaceEngineR.failed("未检测到活体");
		}

		return FaceEngineR.ok("人脸认证通过");
	}

	/**
	 * 人脸认证
	 *
	 * @param authImageBytes 认证的图片字节
	 */
	public FaceEngineR detectFace(byte[] authImageBytes) {
		// 获取引擎
		FaceEngine faceEngine = faceEngineFactory.getFaceEngine();

		int errorCode = 0; // 错误码

		//人脸检测
		ImageInfo imageInfo = getRGBData(authImageBytes);
		List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
		errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
		log.info("人脸检测数据:{}", faceInfoList);
		if (errorCode != ErrorInfo.MERR_ASF_EX_INVALID_FACE_INFO.getValue()) {
			log.info("无效的脸部信息:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("未检测到人脸");
		} else if (errorCode != ErrorInfo.MOK.getValue()) {
			log.info("人脸检测异常:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("人脸检测异常:[errorCode] = " + errorCode);
		}

		//特征提取
		FaceFeature faceFeature = new FaceFeature();
		errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
		log.info("特征值大小:{}", faceFeature.getFeatureData().length);
		if (errorCode != ErrorInfo.MOK.getValue()) {
			log.info("人脸特征提取异常:[errorCode] = {}", errorCode);
			return FaceEngineR.failed("人脸特征提取异常:[errorCode] = " + errorCode);
		}
		return FaceEngineR.ok(faceFeature.getFeatureData().length, "人脸检测通过");
	}

}

5、服务类响应实体

import lombok.Data;

import java.io.Serializable;

@Data
public class FaceEngineR<T> implements Serializable {

	private static final long serialVersionUID = 1L;

	/**
	 * 成功标记
	 */
	private static Integer SUCCESS = 0;

	/**
	 * 失败标记
	 */
	private static Integer FAIL = 1;

	/**
	 * 返回标记:成功标记=0,失败标记=1
	 */
	private int code;

	/**
	 * 返回信息
	 */
	private String msg;

	/**
	 * 数据
	 */
	private T data;

	public static <T> FaceEngineR<T> ok() {
		return restResult(null, SUCCESS, "成功");
	}

	public static <T> FaceEngineR<T> ok(T data) {
		return restResult(data, SUCCESS, "成功");
	}

	public static <T> FaceEngineR<T> ok(T data, String msg) {
		return restResult(data, SUCCESS, msg);
	}

	public static <T> FaceEngineR<T> failed() {
		return restResult(null, FAIL, "失败");
	}

	public static <T> FaceEngineR<T> failed(String msg) {
		return restResult(null, FAIL, msg);
	}

	public static <T> FaceEngineR<T> failed(T data) {
		return restResult(data, FAIL, "失败");
	}

	public static <T> FaceEngineR<T> failed(T data, String msg) {
		return restResult(data, FAIL, msg);
	}

	static <T> FaceEngineR<T> restResult(T data, int code, String msg) {
		FaceEngineR<T> apiResult = new FaceEngineR<>();
		apiResult.setCode(code);
		apiResult.setData(data);
		apiResult.setMsg(msg);
		return apiResult;
	}
}

6、API 方法类

import com.whiemeen.magic.common.core.exception.FcApiException;
import com.whiemeen.magic.common.core.fc.kit.FcFileKit;
import com.whiemeen.magic.modules.dome.faceengine.config.FaceEngineProperties;
import com.whiemeen.magic.modules.dome.faceengine.model.FaceEngineR;
import com.whiemeen.magic.modules.dome.faceengine.service.FaceEngineService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Optional;

/**
 * 人脸认证api
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class FaceEngineApi {

	private final FaceEngineService faceEngineService;

	private final FaceEngineProperties faceEngineProperties;

	/**
	 * 本地人脸检测
	 */
	public boolean detectLocalFace(String imagePath) {
		log.info("检测人脸:{}", imagePath);
		// 将图片url转换为文件字节
		byte[] authImageBytes = FcFileKit.imagePathToBytes(imagePath);
		Optional.ofNullable(authImageBytes).orElseThrow(() -> new FcApiException("文件读取异常"));

		// 人脸检测
		FaceEngineR faceEngineR = faceEngineService.detectFace(authImageBytes);
		if (faceEngineR.getCode() != 0) {
			log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());
			throw new FcApiException(faceEngineR.getMsg());
		
		log.info("检测通过");
		return true;
	}

	/**
	 * 人脸检测
	 */
	public boolean detectFace(String imageUrl) {
		log.info("检测人脸:{}", imageUrl);
		// 将图片url转换为文件字节
		byte[] authImageBytes = FcFileKit.imageUrlToBytes(imageUrl);
		Optional.ofNullable(authImageBytes).orElseThrow(() -> new FcApiException("文件读取异常"));

		// 人脸检测
		FaceEngineR faceEngineR = faceEngineService.detectFace(authImageBytes);
		if (faceEngineR.getCode() != 0) {
			log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());
			throw new FcApiException(faceEngineR.getMsg());
		}
		log.info("检测通过");
		return true;
	}

	/**
	 * 本地人脸对比认证
	 *
	 * @param authImagePath  待认证的人脸
	 * @param localImagePath 人脸库中的人脸
	 * @return 认证结果
	 */
	public boolean compareLocalFace(String authImagePath, String localImagePath) {
		log.info("认证人脸:{}", authImagePath);
		log.info("人脸库人脸:{}", localImagePath);
		// 将图片path转换为文件字节
		byte[] authImageBytes = FcFileKit.imagePathToBytes(authImagePath);
		Optional.ofNullable(authImageBytes).orElseThrow(() -> new FcApiException("文件读取异常"));
		byte[] localImageBytes = FcFileKit.imagePathToBytes(localImagePath);
		Optional.ofNullable(localImageBytes).orElseThrow(() -> new FcApiException("人脸库文件读取异常"));

		log.info("相识度阀值:{}", faceEngineProperties.getFaceSimilarScore());
		log.info("RGB活体检测阀值:{}", faceEngineProperties.getRgbThreshold());
		log.info("IR活体检测阀值:{}", faceEngineProperties.getIrThreshold());

		FaceEngineR faceEngineR = faceEngineService.compareFace(authImageBytes, localImageBytes,
				faceEngineProperties.getFaceSimilarScore(),
				faceEngineProperties.getRgbThreshold(),
				faceEngineProperties.getIrThreshold());
		if (faceEngineR.getCode() != 0) {
			log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());
			throw new FcApiException(faceEngineR.getMsg());
		}
		log.info("认证通过");
		return true;
	}

	/**
	 * 人脸对比认证
	 *
	 * @param authImageUrl  待认证的人脸
	 * @param localImageUrl 人脸库中的人脸
	 * @return 认证结果
	 */
	public boolean compareFace(String authImageUrl, String localImageUrl) {
		log.info("认证人脸:{}", authImageUrl);
		log.info("人脸库人脸:{}", localImageUrl);
		// 将图片url转换为文件字节
		byte[] authImageBytes = FcFileKit.imageUrlToBytes(authImageUrl);
		Optional.ofNullable(authImageBytes).orElseThrow(() -> new FcApiException("文件读取异常"));
		byte[] localImageBytes = FcFileKit.imageUrlToBytes(localImageUrl);
		Optional.ofNullable(localImageBytes).orElseThrow(() -> new FcApiException("人脸库文件读取异常"));

		log.info("相识度阀值:{}", faceEngineProperties.getFaceSimilarScore());
		log.info("RGB活体检测阀值:{}", faceEngineProperties.getRgbThreshold());
		log.info("IR活体检测阀值:{}", faceEngineProperties.getIrThreshold());

		FaceEngineR faceEngineR = faceEngineService.compareFace(authImageBytes, localImageBytes,
				faceEngineProperties.getFaceSimilarScore(),
				faceEngineProperties.getRgbThreshold(),
				faceEngineProperties.getIrThreshold());
		if (faceEngineR.getCode() != 0) {
			log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());
			throw new FcApiException(faceEngineR.getMsg());
		}
		log.info("认证通过");
		return true;
	}

}

7、文件工具类

import cn.hutool.core.img.Img;
import cn.hutool.core.io.FileUtil;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;

public class FcFileKit {

	/**
	 * 本地文件path转化为二进制文件
	 *
	 * @param imagePath 本地文件path
	 * @return 二进制文件
	 */
	public static byte[] imagePathToBytes(String imagePath) {
		try {
			return return FileUtil.readBytes(imagePath);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 远程文件Url转化为二进制文件
	 *
	 * @param imageUrl 文件Url
	 * @return 二进制文件
	 */
	public static byte[] imageUrlToBytes(String imageUrl) {
		try {
			URL url = new URL(imageUrl);
			try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
				Img.from(url).write(outputStream); // 写文件
				return outputStream.toByteArray();
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
		}catch (Exception e){
			e.printStackTrace();
			return null;
		}
	}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/992892.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

类加载流程

文档链接&#xff1a; https://www.processon.com/view/link/64fc101a00a5c32bca7fe12e 访问密码&#xff1a;e3x8

亚马逊测评工作室怎么赚钱?

测评工作室的盈利方式主要来自于以下几种&#xff1a; 佣金&#xff1a;市场价基本上做免评单一单30、留评50单&#xff0c;会根据市场价实施波动&#xff0c;如果一个人今天做30单的留评单就是30单*501500元汇率差&#xff1a;即使用实时汇率进行结算时的差额&#xff0c;假设…

性能测试系列专题集合

下方查看历史精选文章 重磅发布 - 自动化框架基础指南pdfv1.1大数据测试过程、策略及挑战 测试框架原理&#xff0c;构建成功的基石 在自动化测试工作之前&#xff0c;你应该知道的10条建议 在自动化测试中&#xff0c;重要的不是工具 从终端用户感受来体验性能指标度量如何建立…

3000字详解!什么是护网行动?什么是红蓝对抗?

一、什么是护网行动&#xff1f; 护网行动是以公安部牵头的&#xff0c;用以评估企事业单位的网络安全的活动。 具体实践中。公安部会组织攻防两方&#xff0c;进攻方会在一个月内对防守方发动网络攻击&#xff0c;检测出防守方&#xff08;企事业单位&#xff09;存在的安全…

04_瑞萨GUI(LVGL)移植实战教程之驱动LCD屏(SPI)

本系列教程配套出有视频教程&#xff0c;观看地址&#xff1a;https://www.bilibili.com/video/BV1gV4y1e7Sg 4. 驱动LCD屏(SPI) 本次实验我们在上一次实验的基础上驱动 LCD屏(SPI)。 上次实验我们已经能驱动触摸屏(I2C)并打印触摸点坐标&#xff0c;这次实验我们的目标是点…

无涯教程-JavaScript - IMSINH函数

描述 MSINH函数以x yi或x yj文本格式返回复数的双曲正弦值。复数的双曲正弦通过以下公式计算- $$\sinh(x yi) \sinh(x)\cos(y)-\cosh(x)\sin(y)i $$ 语法 IMSINH (inumber)争论 Argument描述Required/OptionalInumberA complex number for which you want the hyperbol…

渗透测试流程是什么?7个步骤给你讲清楚!

在学习渗透测试之初&#xff0c;有必要先系统了解一下它的流程&#xff0c;静下心来阅读一下&#xff0c;树立一个全局观&#xff0c;一步一步去建设并完善自己的专业领域&#xff0c;最终实现从懵逼到牛逼的华丽转变。渗透测试是通过模拟恶意黑客的攻击方法&#xff0c;同时也…

python实现读取并显示图片的两种方法

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 在 python 中除了用 opencv&#xff0c;也可以用 matplotlib 和 PIL 这两个库操作图片。 本人偏爱 matpoltlib&#xff0c;因为它的语法更像 matlab。 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&…

智能语音血压计:NV040DS芯片呵护您的健康

随着科技的发展。血压计已告别传统的水银血压计&#xff0c;迈向电子血压计时代。电子血压计往往体积小。携带方便。智能血压计能自动检测人体的血压值&#xff0c;并给予语音提示与科学指导、帮助人们更好地了解自己的身体状况。 一、产品介绍 深耕语音芯片的九芯电子科技带…

SpringBoot+MP操作DM8

1. 达梦数据库介绍 达梦数据库管理系统是达梦公司推出的具有完全自主知识产权的国产高性能数据库管理系统&#xff0c;简称DM。当前最新版本是8.0版本&#xff0c;简称DM8。&#xff08;同时也是一款RDBMS&#xff0c;关系型数据库管理系统&#xff0c;和oracle比较像&#xff…

CLIP | 打破文本图像次元壁

1 贡献 CLIP是文字图片的多模态工作 CLIP的迁移效果非常好。不同风格数据集的ZeroShot推理能力超强 在分类 &#xff0c;物体检测和分割&#xff0c;视频检索都很多视觉下游任务都可以用CLIP取得有监督学习的效果 采用利用自然语音信号的监督信号来进行训练 提出了高质量的…

抖店开通后,新手必须要知道的几个做店技巧,建议认真看完

我是王路飞。 抖店的运营&#xff0c;无非就是围绕【产品】【流量】展开的。 你要是能把这两个点给搞明白&#xff0c;新店快速出单、真是爆单就不再是问题了。 今天就给你们说一下&#xff0c;抖店开通后&#xff0c;作为一个新手商家&#xff0c;你必须要知道的几个做店技…

Java中如何进行加锁??

笔者在上篇文章介绍了线程安全的问题&#xff0c;接下来本篇文章就是来讲解如何避免线程安全问题~~ 前言&#xff1a;创建两个线程&#xff0c;每个线程都实现对同一个变量count各自自增5W次&#xff0c;我们来看一下代码&#xff1a; class Counter{private int count0;publi…

玩转宝塔,持续更新

用了下宝塔是真的比较爽&#xff0c;这里介绍下安装 1.linux安装宝塔 linux服务器直接安装输入就好 yum install -y wget && wget -O install.sh https://download.bt.cn/install/install_6.0.sh && sh install.sh ed8484bec2.部署项目 2.1安装套件 这里直…

datax工具介绍及简单使用

介绍 Datax是一个异构数据源离线同步工具&#xff0c;致力于实现包括关系数据库、HDFS、Hive、ODPS、Hbase等各种异构数据源之间稳定高效的数据同步功能 设计理念 为了解决异构数据源同步问题&#xff0c;DataX将复杂的网状的同步链路变成了星型数据链路&#xff0c;DataX作为…

Java转网络安全渗透测试,挖漏洞真香啊

最近&#xff0c;一个做运维的朋友在学渗透测试。他说&#xff0c;他公司请别人做渗透测试的费用是 2w/人天&#xff0c;一共2周。2周 10w 的收入&#xff0c;好香~ 于是&#xff0c;我也对渗透测试产生了兴趣。开始了探索之路~ 什么是渗透测试 渗透测试这名字听起来有一种…

Java实现自动玩王铲铲的致富之路小程序游戏

文章目录 前言1.调用adb命令截屏并读取到电脑2.打开游戏&#xff0c;提前截几个图&#xff0c;准备好相应的按钮位置颜色3.根据图片路径和x,y坐标&#xff0c;读取图片相应位置的颜色值4.根据颜色值判断如何进行触摸操作5.程序效果分析5.存在的问题6.改进思路7.改进版本&#x…

vue3中通过ref获取子组件实例,取值为undefined

也就是Vue3如何通过 ref 获取子组件实例(子组件中的DOM结构、数据、及方法)&#xff0c;今天写index.vue(父组件&#xff09;时想获取子组件的数据和方法&#xff0c;通过给子组件绑定ref&#xff0c;打印子组件的数据为undefined&#xff1b;百度搜索常用方法为&#xff1a; …

小白参加红队,需要做好哪些准备?

在本文中&#xff0c;我们将为读者介绍要想加入红队&#xff0c;需要掌握哪些方面的技能。 CSDN大礼包&#xff1a;《黑客&网络安全入门&进阶学习资源包》免费分享 护网的定义是以国家组织组织事业单位、国企单位、名企单位等开展攻防两方的网络安全演习。进攻方一个…

【多线程】Thread 类 详解

Thread 类 详解 一. 创建线程1. 继承 Thread 类2. 实现 Runnable 接口3. 其他变形4. 多线程的优势-增加运行速度 二. Thread 类1. 构造方法2. 常见属性3. 启动线程-start()4. 中断线程-interrupt()5. 线程等待-join()6. 线程休眠-sleep()7. 获取当前线程引用 三. 线程的状态1. …