update:对InsightScrfd不能正常识别的图像进行补边操作再识别

This commit is contained in:
divenswu 2023-07-13 11:47:06 +08:00
parent 44d07346c7
commit 667e14cd7e
3 changed files with 155 additions and 0 deletions

View File

@ -137,6 +137,18 @@ public class FaceInfo implements Comparable<FaceInfo>, Serializable {
public float distance(Point that){
return (float) Math.sqrt(Math.pow((this.x-that.x), 2)+Math.pow((this.y-that.y), 2));
}
/**
* 将点进行平移
* @param top 向上移动的像素点数
* @param bottom 向下移动的像素点数
* @param left 向左移动的像素点数
* @param right 向右移动的像素点数
* @return 平移后的点
*/
public Point move(int left, int right, int top, int bottom){
return new Point(x - left + right, y - top + bottom);
}
}
/**
@ -246,6 +258,22 @@ public class FaceInfo implements Comparable<FaceInfo>, Serializable {
}
return points;
}
/**
* 将点进行平移
* @param top 向上移动的像素点数
* @param bottom 向下移动的像素点数
* @param left 向左移动的像素点数
* @param right 向右移动的像素点数
* @return 平移后的点
*/
public Points move(int left, int right, int top, int bottom){
Points points = build();
for(Point item : this){
points.add(item.move(left, right, top, bottom));
}
return points;
}
}
/**
@ -419,6 +447,23 @@ public class FaceInfo implements Comparable<FaceInfo>, Serializable {
new Point(leftBottom.x + change_x_p2_p4, leftBottom.y + change_y_p2_p4)
);
}
/**
* 将框进行平移
* @param top 向上移动的像素点数
* @param bottom 向下移动的像素点数
* @param left 向左移动的像素点数
* @param right 向右移动的像素点数
* @return 平移后的框
*/
public FaceBox move(int left, int right, int top, int bottom){
return new FaceBox(
new Point(leftTop.x - left + right, leftTop.y - top + bottom),
new Point(rightTop.x - left + right, rightTop.y - top + bottom),
new Point(rightBottom.x - left + right, rightBottom.y - top + bottom),
new Point(leftBottom.x - left + right, leftBottom.y - top + bottom)
);
}
}
/**

View File

@ -252,6 +252,55 @@ public class ImageMat implements Serializable {
}
}
/**
* 对图像进行补边操作不释放原始的图片
* @param top 向上扩展的高度
* @param bottom 向下扩展的高度
* @param left 向左扩展的宽度
* @param right 向右扩展的宽度
* @param borderType 补边的类型
* @return 补边后的图像
*/
public ImageMat copyMakeBorderAndNotReleaseMat(int top, int bottom, int left, int right, int borderType){
return this.copyMakeBorder(top, bottom, left, right, borderType, false);
}
/**
* 对图像进行补边操作并且释放原始的图片
* @param top 向上扩展的高度
* @param bottom 向下扩展的高度
* @param left 向左扩展的宽度
* @param right 向右扩展的宽度
* @param borderType 补边的类型
* @return 补边后的图像
*/
public ImageMat copyMakeBorderAndDoReleaseMat(int top, int bottom, int left, int right, int borderType){
return this.copyMakeBorder(top, bottom, left, right, borderType, true);
}
/**
* 对图像进行补边操作
* @param top 向上扩展的高度
* @param bottom 向下扩展的高度
* @param left 向左扩展的宽度
* @param right 向右扩展的宽度
* @param borderType 补边的类型
* @param release 是否释放原始的图片
* @return 补边后的图像
*/
private ImageMat copyMakeBorder(int top, int bottom, int left, int right, int borderType, boolean release){
try {
Mat tempMat = new Mat();
Core.copyMakeBorder(mat, tempMat, top, bottom, left, right, borderType);
return new ImageMat(tempMat);
}finally {
if(release){
this.release();
}
}
}
/**
* 对图像进行预处理,不释放原始图片数据
* @param scale 图像各通道数值的缩放比例

View File

@ -7,6 +7,9 @@ import com.visual.face.search.core.base.BaseOnnxInfer;
import com.visual.face.search.core.base.FaceDetection;
import com.visual.face.search.core.domain.FaceInfo;
import com.visual.face.search.core.domain.ImageMat;
import com.visual.face.search.core.utils.ReleaseUtil;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import java.util.*;
@ -32,6 +35,10 @@ public class InsightScrfdFaceDetection extends BaseOnnxInfer implements FaceDete
public final static boolean defNeedCheckFaceAngle = true;
//是否需要进行角度检测的参数KEY
public final static String scrfdFaceNeedCheckFaceAngleParamKey = "scrfdFaceNeedCheckFaceAngle";
//人脸框默认需要进行角度检测
public final static boolean defNoFaceImageNeedMakeBorder = true;
//是否需要进行角度检测的参数KEY
public final static String scrfdNoFaceImageNeedMakeBorderParamKey = "scrfdNoFaceImageNeedMakeBorder";
/**
* 构造函数
@ -51,6 +58,40 @@ public class InsightScrfdFaceDetection extends BaseOnnxInfer implements FaceDete
*/
@Override
public List<FaceInfo> inference(ImageMat image, float scoreTh, float iouTh, Map<String, Object> params) {
List<FaceInfo> faceInfos = this.modelInference(image, scoreTh,iouTh, params);
//对图像进行补边操作进行二次识别
if(this.getNoFaceImageNeedMakeBorder(params) && faceInfos.isEmpty()){
//防止由于人脸占用大导致检测模型识别失败
int t = Double.valueOf(image.toCvMat().height() * 0.2).intValue();
int b = Double.valueOf(image.toCvMat().height() * 0.2).intValue();
int l = Double.valueOf(image.toCvMat().width() * 0.2).intValue();
int r = Double.valueOf(image.toCvMat().width() * 0.2).intValue();
ImageMat tempMat = null;
try {
//补边识别
tempMat=image.copyMakeBorderAndNotReleaseMat(t, b, l, r, Core.BORDER_CONSTANT);
faceInfos = this.modelInference(tempMat, scoreTh,iouTh, params);
for(FaceInfo faceInfo : faceInfos){
//还原原始的坐标
faceInfo.box = faceInfo.box.move(l, 0, t, 0);
faceInfo.points = faceInfo.points.move(l, 0, t, 0);
}
}finally {
ReleaseUtil.release(tempMat);
}
}
return faceInfos;
}
/**
* 模型推理获取人脸信息
* @param image 图像信息
* @param scoreTh 人脸人数阈值
* @param iouTh 人脸iou阈值
* @return 人脸模型
*/
public List<FaceInfo> modelInference(ImageMat image, float scoreTh, float iouTh, Map<String, Object> params) {
OnnxTensor tensor = null;
OrtSession.Result output = null;
ImageMat imageMat = image.clone();
@ -252,4 +293,24 @@ public class InsightScrfdFaceDetection extends BaseOnnxInfer implements FaceDete
}
return needCheckFaceAngle;
}
/**获取是否需要对没有检测到人脸的图像进行补边二次识别**/
private boolean getNoFaceImageNeedMakeBorder(Map<String, Object> params){
boolean noFaceImageNeedMakeBorder = defNoFaceImageNeedMakeBorder;
try {
if(null != params && params.containsKey(scrfdNoFaceImageNeedMakeBorderParamKey)){
Object value = params.get(scrfdNoFaceImageNeedMakeBorderParamKey);
if(null != value){
if (value instanceof Boolean){
noFaceImageNeedMakeBorder = (boolean) value;
}else{
noFaceImageNeedMakeBorder = Boolean.parseBoolean(value.toString());
}
}
}
}catch (Exception e){
e.printStackTrace();
}
return noFaceImageNeedMakeBorder;
}
}