package com.cnsugar.ai.face;
import com.cnsugar.ai.face.bean.FaceIndex;
import com.cnsugar.ai.face.bean.Result;
import com.cnsugar.ai.face.dao.FaceDao;
import com.cnsugar.ai.face.utils.ImageUtils;
import com.seetaface2.SeetaFace2JNI;
import com.seetaface2.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
/**
* @Author Sugar
* @Version 2019/4/22 15:56
*/
public class FaceHelper {
private static Logger logger = LoggerFactory.getLogger(FaceHelper.class);
private static int CROP_SIZE = 256 * 256 * 3;
private final static SeetaFace2JNI seeta = SeetafaceBuilder.build();
static {
ImageIO.setUseCache(false);
}
/**
* 人脸比对
*
* @param img1
* @param img2
* @return 相似度
* @throws IOException
*/
public static float compare(File img1, File img2) throws IOException {
BufferedImage image1 = null;
BufferedImage image2 = null;
try {
image1 = ImageIO.read(img1);
image2 = ImageIO.read(img2);
return compare(image1, image2);
} finally {
if (image1 != null) {
image1.getGraphics().dispose();
}
if (image2 != null) {
image2.getGraphics().dispose();
}
}
}
/**
* 人脸比对
*
* @param img1
* @param img2
* @return 相似度
*/
public static float compare(byte[] img1, byte[] img2) throws IOException {
BufferedImage image1 = null;
BufferedImage image2 = null;
try {
image1 = ImageIO.read(new ByteArrayInputStream(img1));
image2 = ImageIO.read(new ByteArrayInputStream(img2));
return compare(image1, image2);
} finally {
if (image1 != null) {
image1.getGraphics().dispose();
}
if (image2 != null) {
image2.getGraphics().dispose();
}
}
}
/**
* `
* 人脸比对
*
* @param image1
* @param image2
* @return 相似度
*/
public static float compare(BufferedImage image1, BufferedImage image2) {
if (image1 == null || image2 == null) {
return 0;
}
SeetaImageData imageData1 = new SeetaImageData(image1.getWidth(), image1.getHeight(), 3);
imageData1.data = ImageUtils.getMatrixBGR(image1);
SeetaImageData imageData2 = new SeetaImageData(image2.getWidth(), image2.getHeight(), 3);
imageData2.data = ImageUtils.getMatrixBGR(image2);
return seeta.compare(imageData1, imageData2);
}
/**
* 注册人脸(会对人脸进行裁剪)
*
* @param key 人脸照片唯一标识
* @param img 人脸照片
* @return
* @throws IOException
*/
public static boolean register(String key, byte[] img) throws IOException {
BufferedImage image = null;
try (InputStream in = new ByteArrayInputStream(img)){
image = ImageIO.read(in);
//先对人脸进行裁剪
SeetaImageData imageData = new SeetaImageData(image.getWidth(), image.getHeight(), 3);
imageData.data = ImageUtils.getMatrixBGR(image);
byte[] bytes = seeta.crop(imageData);
if (bytes == null || bytes.length != CROP_SIZE) {
logger.info("register face fail: key={}, error=no valid face", key);
return false;
}
imageData = new SeetaImageData(256, 256, 3);
imageData.data = bytes;
int index = seeta.register(imageData);
if (index < 0) {
logger.info("register face fail: key={}, index={}", key, index);
return false;
}
FaceIndex face = new FaceIndex();
face.setKey(key);
face.setImgData(imageData.data);
face.setWidth(imageData.width);
face.setHeight(imageData.height);
face.setChannel(imageData.channels);
face.setIndex(index);
FaceDao.saveOrUpdate(face);
logger.info("Register face success: key={}, index={}", key, index);
} finally {
if (image != null) {
image.getGraphics().dispose();
}
}
return true;
}
/**
* 注册人脸(不裁剪图片)
*
* @param key 人脸照片唯一标识
* @param image 人脸照片
* @return
* @throws IOException
*/
public static boolean register(String key, BufferedImage image) throws IOException {
SeetaImageData imageData = new SeetaImageData(image.getWidth(), image.getHeight(), 3);
imageData.data = ImageUtils.getMatrixBGR(image);
int index = seeta.register(imageData);
if (index < 0) {
logger.info("register face fail: key={}, index={}", key, index);
return false;
}
FaceIndex face = new FaceIndex();
face.setKey(key);
face.setImgData(imageData.data);
face.setWidth(imageData.width);
face.setHeight(imageData.height);
face.setChannel(imageData.channels);
FaceDao.saveOrUpdate(face);
face.setIndex(index);
logger.info("Register face success: key={}, index={}", key, index);
return true;
}
/**
* 搜索人脸
*
* @param img 人脸照片
* @return
* @throws IOException
*/
public static Result search(byte[] img) throws IOException {
BufferedImage image = null;
try (InputStream in = new ByteArrayInputStream(img)){
image = ImageIO.read(in);
return search(image);
} finally {
if (image != null) {
image.getGraphics().dispose();
}
}
}
/**
* 搜索人脸
*
* @param image 人脸照片
* @return
* @throws IOException
*/
public static Result search(BufferedImage image) {
if (image == null) {
return null;
}
SeetaImageData imageData = new SeetaImageData(image.getWidth(), image.getHeight(), 3);
imageData.data = ImageUtils.getMatrixBGR(image);
RecognizeResult rr = seeta.recognize(imageData);
if (rr == null || rr.index == -1) {
return null;
}
Result result = new Result(rr);
result.setKey(FaceDao.findKeyByIndex(rr.index));
return result;
}
/**
* 人脸提取(裁剪)
*
* @param img
* @return return cropped face
*/
public static BufferedImage crop(byte[] img) throws IOException {
BufferedImage image = null;
try (InputStream in = new ByteArrayInputStream(img)){
image = ImageIO.read(in);
return crop(image);
} finally {
if (image != null) {
image.getGraphics().dispose();
}
}
}
/**
* 人脸提取(裁剪)
*
* @param image
* @return return cropped face
*/
public static BufferedImage crop(BufferedImage image) {
if (image == null) {
return null;
}
SeetaImageData imageData = new SeetaImageData(image.getWidth(), image.getHeight(), 3);
imageData.data = ImageUtils.getMatrixBGR(image);
byte[] bytes = seeta.crop(imageData);
if (bytes == null || bytes.length != CROP_SIZE) {
return null;
}
return ImageUtils.bgrToBufferedImage(bytes, 256, 256);
}
/**
* 人脸识别
*
* @param img
* @return
*/
public static SeetaRect[] detect(byte[] img) throws IOException {
BufferedImage image = null;
try (InputStream in = new ByteArrayInputStream(img)){
Java程序员-张凯
- 粉丝: 1w+
- 资源: 7364
最新资源
- CardExpiredException解决方案(亲测可用).md
- python《Hybrid-SORT-多目标跟踪器(弱线索对在线多目标跟踪)》+项目源码+文档说明
- aspose:word,pdf,ppt
- 个人信用报告690428.zip
- 植物大战僵尸射击版v.0.3 双端安装程序
- 【重磅,更新!】中国各省水资源分类统计数据(2003-2022年)
- 富士施乐打印机驱动下载 适用机型:FujiXerox DocuPrint M375 df、M378 d、M378 df
- python-图片批量保存脚本
- aspose:word,pdf,ppt
- 中国2005-2021年大气污染物和二氧化碳排放趋势数据集【重磅,更新!】
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈