223 lines
7.8 KiB
C#
223 lines
7.8 KiB
C#
![]() |
using AlibabaCloud.SDK.Facebody20191230.Models;
|
|||
|
using AlibabaCloud.TeaUtil.Models;
|
|||
|
using AutoMapper;
|
|||
|
using Confluent.Kafka;
|
|||
|
using DlibDotNet;
|
|||
|
using Microsoft.AspNetCore.Components.Forms;
|
|||
|
using Microsoft.AspNetCore.Hosting;
|
|||
|
using Microsoft.AspNetCore.Http;
|
|||
|
using Microsoft.EntityFrameworkCore;
|
|||
|
using Microsoft.Extensions.DependencyInjection;
|
|||
|
using Microsoft.ML;
|
|||
|
using Microsoft.ML.Data;
|
|||
|
using Microsoft.ML.Transforms.Onnx;
|
|||
|
using Tea;
|
|||
|
using VOL.Business.IServices.School;
|
|||
|
using VOL.Core.CacheManager;
|
|||
|
using VOL.Core.Configuration;
|
|||
|
using VOL.Core.Extensions.AutofacManager;
|
|||
|
using VOL.Model;
|
|||
|
using VOL.System.IRepositories;
|
|||
|
|
|||
|
namespace VOL.Business.Services.School
|
|||
|
{
|
|||
|
public class FaceDetectService : IFaceDetectService, IDependency
|
|||
|
{
|
|||
|
#region 初始化
|
|||
|
private readonly IMapper _mapper;
|
|||
|
private readonly ICacheService _cacheService;
|
|||
|
private readonly IS_StudentRepository _studentRepository;
|
|||
|
private readonly IWebHostEnvironment _environment;
|
|||
|
|
|||
|
[ActivatorUtilitiesConstructor]
|
|||
|
public FaceDetectService(IMapper mapper,
|
|||
|
ICacheService cacheService,
|
|||
|
IS_StudentRepository studentRepository, IWebHostEnvironment environment)
|
|||
|
{
|
|||
|
_mapper = mapper;
|
|||
|
_cacheService = cacheService;
|
|||
|
_studentRepository = studentRepository;
|
|||
|
_environment = environment;
|
|||
|
}
|
|||
|
|
|||
|
public async Task<StudentPageListModel> Face(string base64)
|
|||
|
{
|
|||
|
if (string.IsNullOrWhiteSpace(base64))
|
|||
|
throw new FileNotFoundException("base64为空");
|
|||
|
|
|||
|
var res = new StudentPageListModel();
|
|||
|
|
|||
|
var students = await _studentRepository.FindAsIQueryable(x => x.ClassId == 1).Select(x => new StudentPageListModel()
|
|||
|
{
|
|||
|
GradeId = 1,
|
|||
|
GradeName = "一年级",
|
|||
|
ClassName = "一班",
|
|||
|
ClassId = x.ClassId,
|
|||
|
Age = x.Age,
|
|||
|
HeartRateId = x.HeartRateId,
|
|||
|
HeartRateFrontNo = x.HeartRateFrontNo,
|
|||
|
Photo = x.Photo,
|
|||
|
RopeSkipQRCode = x.RopeSkipQRCode,
|
|||
|
SchoolRollNo = x.SchoolRollNo,
|
|||
|
Sex = x.Sex,
|
|||
|
StudentName = x.StudentName,
|
|||
|
StudentStatus = x.StudentStatus,
|
|||
|
StudentNo = x.StudentNo
|
|||
|
}).ToListAsync();
|
|||
|
|
|||
|
foreach (var student in students)
|
|||
|
{
|
|||
|
string imagePath = Path.Combine(_environment.WebRootPath, student.Photo);
|
|||
|
string imageDataB = ConvertImageToBase64(imagePath);
|
|||
|
|
|||
|
if (string.IsNullOrWhiteSpace(imageDataB))
|
|||
|
continue;
|
|||
|
|
|||
|
var result = await FaceDetect(base64, imageDataB);
|
|||
|
|
|||
|
if (result)
|
|||
|
{
|
|||
|
res = student;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return res;
|
|||
|
}
|
|||
|
#endregion
|
|||
|
public async Task<StudentPageListModel> GetStudentDetails(IFormFile file, int classId)
|
|||
|
{
|
|||
|
var res = new StudentPageListModel();
|
|||
|
string imageDataA = await ConvertFileToBase64Async(file);
|
|||
|
|
|||
|
var students = await _studentRepository.FindAsIQueryable(x => x.ClassId == classId).Select(x => new StudentPageListModel()
|
|||
|
{
|
|||
|
ClassId = x.ClassId,
|
|||
|
Age = x.Age,
|
|||
|
HeartRateId = x.HeartRateId,
|
|||
|
HeartRateFrontNo = x.HeartRateFrontNo,
|
|||
|
Photo = x.Photo,
|
|||
|
RopeSkipQRCode = x.RopeSkipQRCode,
|
|||
|
SchoolRollNo = x.SchoolRollNo,
|
|||
|
Sex = x.Sex,
|
|||
|
StudentName = x.StudentName,
|
|||
|
StudentStatus = x.StudentStatus,
|
|||
|
StudentNo = x.StudentNo
|
|||
|
}).ToListAsync();
|
|||
|
|
|||
|
var tasks = new List<Task>();
|
|||
|
|
|||
|
using (var semaphore = new SemaphoreSlim(5)) // 限制并发数为5
|
|||
|
{
|
|||
|
foreach (var student in students)
|
|||
|
{
|
|||
|
await semaphore.WaitAsync();
|
|||
|
|
|||
|
if (res.StudentNo != null)
|
|||
|
{
|
|||
|
semaphore.Release();
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
tasks.Add(Task.Run(async () =>
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string imagePath = Path.Combine(_environment.WebRootPath, student.Photo);
|
|||
|
string imageDataB = _cacheService.Get(imagePath); // 从缓存中获取图片数据
|
|||
|
|
|||
|
if (imageDataB == null) // 如果缓存中没有图片数据,则从文件中读取
|
|||
|
{
|
|||
|
imageDataB = ConvertImageToBase64(imagePath);
|
|||
|
_cacheService.Add(imagePath, imageDataB); // 将图片数据写入缓存
|
|||
|
}
|
|||
|
|
|||
|
if (imageDataB != null)
|
|||
|
{
|
|||
|
var result = await FaceDetect(imageDataA, imageDataB);
|
|||
|
if (result)
|
|||
|
{
|
|||
|
lock (res)
|
|||
|
{
|
|||
|
if (res.StudentNo == null) // 双重检查
|
|||
|
{
|
|||
|
res = student;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
semaphore.Release();
|
|||
|
}
|
|||
|
}));
|
|||
|
}
|
|||
|
|
|||
|
await Task.WhenAny(tasks);
|
|||
|
}
|
|||
|
|
|||
|
return res;
|
|||
|
}
|
|||
|
|
|||
|
private async Task<string> ConvertFileToBase64Async(IFormFile file)
|
|||
|
{
|
|||
|
if (file == null || file.Length == 0)
|
|||
|
{
|
|||
|
throw new ArgumentNullException("上传文件为空");
|
|||
|
}
|
|||
|
|
|||
|
using (var memoryStream = new MemoryStream())
|
|||
|
{
|
|||
|
await file.CopyToAsync(memoryStream);
|
|||
|
byte[] fileBytes = memoryStream.ToArray();
|
|||
|
string base64String = Convert.ToBase64String(fileBytes);
|
|||
|
return base64String;
|
|||
|
}
|
|||
|
}
|
|||
|
private string ConvertImageToBase64(string imagePath)
|
|||
|
{
|
|||
|
if (File.Exists(imagePath))
|
|||
|
{
|
|||
|
byte[] imageBytes = File.ReadAllBytes(imagePath);
|
|||
|
return Convert.ToBase64String(imageBytes);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return null; // 文件未找到,返回 null
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private async Task<bool> FaceDetect(string imageDataA, string imageDataB)
|
|||
|
{
|
|||
|
AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config
|
|||
|
{
|
|||
|
AccessKeyId = AppSetting.ALiYunFaceDetect.AccessKeyId,
|
|||
|
AccessKeySecret = AppSetting.ALiYunFaceDetect.SecretAccessKey,
|
|||
|
Endpoint = AppSetting.ALiYunFaceDetect.Endpoint
|
|||
|
};
|
|||
|
|
|||
|
var client = new AlibabaCloud.SDK.Facebody20191230.Client(config);
|
|||
|
|
|||
|
CompareFaceRequest compareFaceRequest = new CompareFaceRequest()
|
|||
|
{
|
|||
|
QualityScoreThreshold = (float)98.5,
|
|||
|
ImageDataA = imageDataA,
|
|||
|
ImageDataB = imageDataB
|
|||
|
};
|
|||
|
|
|||
|
RuntimeOptions runtime = new RuntimeOptions();
|
|||
|
try
|
|||
|
{
|
|||
|
CompareFaceResponse resp = await client.CompareFaceWithOptionsAsync(compareFaceRequest, runtime);
|
|||
|
|
|||
|
return resp.Body.Data.Confidence > 61;
|
|||
|
}
|
|||
|
catch (TeaException error)
|
|||
|
{
|
|||
|
throw new FileNotFoundException("识别图片出错", error);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|