利用课余时间写了一个基于的django图像处理例子,数据库是mysql,很多代码还不成熟,关于django的使用主要是在视频:2022 B站最详细django3教程(django从入门到实践)_哔哩哔哩_bilibili 上进行的。我认为这是最好的django学习视频了。

一、项目简介

1、项目包括:

(1)用户登录,注册

(2)上传npz数据集

(3)对数据集基于sklearn交叉验证或数据集分割后验证

(4)上传符合数据集标准的样本进行识别

(5)利用摄像头采集人脸信息

(6)利用dlib进行人脸识别(比较慢,有待优化)

2、例子涉及知识:

  1. django
  2. bootstrap
  3. dlib人脸识别
  4. sklearn
  5. 摄像头视频采集
  6. echarts (这个对项目没什么用,纯练习)

3、参考文档:

[1] js开启摄像头_安和同学的博客-CSDN博客_js开启摄像头

[2] Python 3 利用 Dlib 实现摄像头实时人脸识别 - coneypo - 博客园

[3] web调用摄像头拍照并上传到服务器_淋雨一直走~的博客-CSDN博客_摄像头拍照上传服务器

[4] Detecting Face Features with Python

参考了很多文档,这里未一一列出,感谢各位大佬的辛苦付出。

本文源码:https://github.com/huangzhiyu2018/OnlineAiPicture

4、项目截图:

为了总结过去的经验,列出主要操作

二、html模板嵌套

1、首先定义一个母版,在里面留出适当的block,例如:

{% load static %}

<!DOCTYPE html>

<html lang="zh-CN">

<head>

<meta charset="UTF-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1-dist/css/bootstrap.css' %}">

<!--额外css填入位置-->

{% block css %} {% endblock %}

<title>

{% block title %} {% endblock %}

</title>

</head>

<body>

<div class="container">

<!--内容填入位置-->

{% block contain %} {% endblock %}

</div>

<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->

<script src="{%static 'js/jquery-3.6.0.min.js' %}"></script>

<!-- 最新的 Bootstrap4 核心 JavaScript 文件 -->

<script src="{%static 'plugins/bootstrap-3.4.1-dist/js/bootstrap.js'%}"></script>

<!--额外js填入位置-->

{% block js %} {% endblock %}

</body>

</html>

2、其它模板可以引用这个母版,达到所有模板都具有相同的布局:

{% extends 'master.html' %}

{% block contain %}

写入当前模板需要的内容

{% endblock %}

3、继续继承

更有意思的是还可以上(2)基础上进一步进行嵌套,再次嵌套时需要在(2)的文档中也设定响应的block,其过程与第一次嵌套一样。

三、人脸采集

人脸采集时控制摄像头,并把摄像头采集到的图片上传到服务器,基本思路,先打开摄像头,然后拍照,最后ajax提交到后台进行保存。页面布局以及功能如下:

正在上传…重新上传取消

1、打开摄像头

前台有<video id="video" ></video>标签,利用javascript打开,这是参考的博客:https://blog.csdn.net/amdd9582/article/details/95501402

function playfunction(){

// 开启摄像

document.getElementById('play').onclick = () => {

let constraints = {

// video属性设置

video: {

width: 300,

height: 300

},

// audio属性设置,无声

audio: false

}

navigator.mediaDevices.getUserMedia(constraints)

.then(mediaStream => {

// 成功返回promise对象,接收一个mediaStream参数与video标签进行对接

document.getElementById('video').srcObject = mediaStream

document.getElementById('video').play()

mediaStreamTrack = typeof mediaStream.stop === 'function' ? mediaStream : mediaStream.getTracks()[0];

click_start_vedio=1;//记录开启视频

})

// 失败就失败了

}

}

为了能够关闭摄像头,我定义了一个全局变量:mediaStreamTrack

2、拍照

点击id为take的按钮,进行拍照,

function photofunction(){

// 拍照、canvas绘制

document.getElementById('take').onclick = () => {

if (click_start_vedio==1){

let ctx = document.getElementById("canvas").getContext('2d')

ctx.drawImage(document.getElementById("video"), 0, 0, 300, 300)

click_scrap=1;

$("#img_result").removeAttr("src");//每次拍照后页面识别结果都清空

}else{

alert("请点击开始摄像按钮");

}

}

}

3、关闭摄像头

利用全局变量mediaStreamTrack进行关闭摄像头

function closevideofunction(){

$("#close").on({

"click":function(){

if(mediaStreamTrack){

mediaStreamTrack.stop();

mediaStreamTrack=[];

console.log("stop");

click_start_vedio=0;

}else{

console.log("mediaStreamTrack is empty")

}

}

})

}

4、异步上传

需要把canvas的内容先转成字符流,再把字符流转成文件进行上传,两个函数:

function dataURItoBlob(base64Data) {

var byteString;

if (base64Data.split(',')[0].indexOf('base64') >= 0)

byteString = atob(base64Data.split(',')[1]);

else

byteString = unescape(base64Data.split(',')[1]);

var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];

var ia = new Uint8Array(byteString.length);

for (var i = 0; i < byteString.length; i++) {

ia[i] = byteString.charCodeAt(i);

}

return new Blob([ia], {type: mimeString});

};

//将blob转换为file

function blobToFile(theBlob, fileName) {

theBlob.lastModifiedDate = new Date();

theBlob.name = fileName;

return theBlob;

};

由于后台是利用modelform进行处理的,上传的图片和姓名信息直接存入到了mysql数据库,这里异步时把相关信息都携带了,代码中为防止无视频直接上传,用标志变量来确定是否已经点击了拍照按钮。代码如下:

function uploadfunction(){

$("#upload").on({

"click":function(){

if(click_start_vedio==0){

alert("首先点击开启摄像,然后点击拍照");

return;

}

var personName=$("#person_name").val();

if (personName){

if(click_scrap==1){

click_scrap=0

canvas = document.getElementById('canvas');

//生成图片格式base64包括:jpg、png格式

var base64Data = canvas.toDataURL("image/jpeg", 1.0);

//封装blob对象

var blob = dataURItoBlob(base64Data);

var file = blobToFile(blob, personName);

//利用FormData进行传值

var form = document.getElementById("controlform");

// 用表单来初始化

var formdata = new FormData(form);

formdata.append("person_name",personName);

//必须是file字段的添加,防止汉语名称不识别,这里用英文名称

formdata.append("file",blob,"person.jpg");

$.ajax({

url: ajaxurl,

type:"post",

data:formdata,

processData: false,//用于对data参数进行序列化处理 这里必须false

contentType: false, //必须

success:function(res){

if(res.status){

var valide="图片中没有脸部信息"

if (res.valide){

valide="图片有效"

}

$("#pic_result").html("文件:"+res.path+"上传成功!<br>"+valide)

$("#img_result").attr("src","/media/"+res.path)

if (show_result_alert){//这是为了图像识别显示对话框用的

if(res.valide)

{

alert("当前人物为:"+res.person+"\n 可能人物:"+res.min_person)

}else{

alert(valide);

}

}

}else{

console.log(res.errors)

}

}

}

)

}else{

alert("必须点击拍照!");

}

}else{

alert("必须输入姓名")

}

},

})

}

5、采集人脸和人脸识别的模板

整个模板仍然是人脸采集和人脸识别模板的母版,里面包括了被人脸识别的两个block

{% block table %}    {% endblock %} 和 {% block exjs%}{% endblock %}

文件名为:scrapture.html其完整代码如下:

{% extends 'master.html' %}

{% block css %}

<style>

video, canvas {

width: 300px;

height: 300px;

border: 5px solid #000;

border-radius: 10px;

margin-left: 5px;

}

</style>

{% endblock %}

{% block contain %}

<div class="container">

<div class="panel panel-primary">

<div class="panel-heading">

<h3 class="panel-title">采集人脸图像</h3>

</div>

<div class="panel-body" >

<div class="panel panel-default" style="margin:10px 10px">

<div class="panel-heading">

<h3 class="panel-title">采集面部</h3>

</div>

<div class="panel-body">

<div class="col-md-6">

<video id="video" ></video>

</div>

<!-- 尽量在canvas标签上设置宽高 -->

<div class="col-md-6">

<canvas id="canvas" width="300px" height="300px"></canvas>

</div>

</div>

</div>

<div class="col-md-6">

<div class="panel panel-default" >

<div class="panel-heading">

<h3 class="panel-title">控制面板</h3>

</div>

<div class="panel-body" style="margin:10px 10px">

<button id="play" class="btn btn-success" >开启摄像</button>

<button id="close" class="btn btn-danger " >关闭视频</button>

<form method="post" novalidate id="controlform" enctype="multipart/form-data">

<div class="form-group" id="input_person">

<label class="col-sm-2" for="person_name">人物姓名:</label>

<input type="text" class="col-sm-2"  id="person_name" placeholder="Tom" value="第一人" >

</div>

<div class="form-group">

<input id="take" class="btn btn-success col-sm-2" value="拍照"></input>

<input id="upload" class="btn btn-info col-sm-2" value="采集"></input>

</div>

</form>

</div>

</div>

</div>

<!--加上一个处理结果显示情况-->

<div class="col-md-6" id="result_panel">

<div class="panel panel-default" style="margin:10px 10px">

<div class="panel-heading">

<h3 class="panel-title">采集结果</h3>

</div>

<div class="panel-body" style="margin:10px 10px">

<img style="height:300px" id="img_result"></img>

</div>

</div>

</div>

</div>

</div>

<div class="panel-footer" id="footer">

<p class="list-group-item-text" id="pic_result"></p>

<a href="/facerecon/list/" style="align:right">采集结果列表 </a>

</div>

</div>

{% block table %}

{% endblock %}

</div>

{% endblock %}

{% block js %}

<script type="text/javascript">

var click_start_vedio=0;

var click_scrap=0;

var ajaxurl;

var show_result_alert=0;

var  mediaStreamTrack;

// 获取媒体方法(旧方法)

function closevideofunction(){

$("#close").on({

"click":function(){

if(mediaStreamTrack){

mediaStreamTrack.stop();

mediaStreamTrack=[];

console.log("stop");

click_start_vedio=0;

}else{

console.log("mediaStreamTrack is empty")

}

}

})

}

function playfunction(){

// 开启摄像

document.getElementById('play').onclick = () => {

let constraints = {

// video属性设置

video: {

width: 300,

height: 300

},

// audio属性设置,无声

audio: false

}

navigator.mediaDevices.getUserMedia(constraints)

.then(mediaStream => {

// 成功返回promise对象,接收一个mediaStream参数与video标签进行对接

document.getElementById('video').srcObject = mediaStream

document.getElementById('video').play()

mediaStreamTrack = typeof mediaStream.stop === 'function' ? mediaStream : mediaStream.getTracks()[0];

click_start_vedio=1;//记录开启视频

})

// 失败就失败了

}

}

function photofunction(){

// 拍照、canvas绘制

document.getElementById('take').onclick = () => {

if (click_start_vedio==1){

let ctx = document.getElementById("canvas").getContext('2d')

ctx.drawImage(document.getElementById("video"), 0, 0, 300, 300)

click_scrap=1;

$("#img_result").removeAttr("src");

}else{

alert("请点击开始摄像按钮");

}

}

}

function dataURItoBlob(base64Data) {

var byteString;

if (base64Data.split(',')[0].indexOf('base64') >= 0)

byteString = atob(base64Data.split(',')[1]);

else

byteString = unescape(base64Data.split(',')[1]);

var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];

var ia = new Uint8Array(byteString.length);

for (var i = 0; i < byteString.length; i++) {

ia[i] = byteString.charCodeAt(i);

}

return new Blob([ia], {type: mimeString});

};

//将blob转换为file

function blobToFile(theBlob, fileName) {

theBlob.lastModifiedDate = new Date();

theBlob.name = fileName;

return theBlob;

};

function uploadfunction(){

$("#upload").on({

"click":function(){

if(click_start_vedio==0){

alert("首先点击开启摄像,然后点击拍照");

return;

}

var personName=$("#person_name").val();

if (personName){

if(click_scrap==1){

click_scrap=0

canvas = document.getElementById('canvas');

//生成图片格式base64包括:jpg、png格式

var base64Data = canvas.toDataURL("image/jpeg", 1.0);

//封装blob对象

var blob = dataURItoBlob(base64Data);

var file = blobToFile(blob, personName);

//利用FormData进行传值

var form = document.getElementById("controlform");

// 用表单来初始化

var formdata = new FormData(form);

formdata.append("person_name",personName);

//必须是file字段的添加,防止汉语名称不识别,这里用英文名称

formdata.append("file",blob,"person.jpg");

//没有问题

$.ajax({

url: ajaxurl,

type:"post",

data:formdata,

processData: false,//用于对data参数进行序列化处理 这里必须false

contentType: false, //必须

success:function(res){

if(res.status){

var valide="图片中没有脸部信息"

if (res.valide){

valide="图片有效"

}

$("#pic_result").html("文件:"+res.path+"上传成功!<br>"+valide)

//console.log(res.path)

$("#img_result").attr("src","/media/"+res.path)

if (show_result_alert){

if(res.valide)

{

alert("当前人物为:"+res.person+"\n 可能人物:"+res.min_person)

}else{

alert(valide);

}

}

}else{

console.log(res.errors)

}

}

}

)

}else{

alert("必须点击拍照!");

}

}else{

alert("必须输入姓名")

}

},

})

}

</script>

{% block exjs%}

{% endblock %}

{% endblock %}

6、人脸采集模板

人脸采集模板是继承了上面的模板,只是更改了提交按钮的post地址

{% extends 'scrapture.html' %}

{% block exjs%}

<script>

$(document).ready(function(){

playfunction();

photofunction();

uploadfunction();

initparams();

})

function initparams(){

//$("#input_person").hide()

ajaxurl="/facerecon/scrap/"

}

</script>

{% endblock%}

7、人脸采集数据模型

a) 采集人脸文件上传到后台media/persons路径,信息存入到数据库,数据库model如下:

class PersonInfor(models.Model):

"""动态上传人员信息表

Args:

models (_type_): _description_

"""

#上传的文件路径,在persons路径

file=models.FileField(verbose_name="文件",max_length=125,upload_to="persons/",default="")

#图片对应的人名

person_name=models.CharField(max_length=30,verbose_name='姓名',default="Tom")

#上传时间

create_time = models.DateField(verbose_name='上传时间')

#采集者

upload_user=models.CharField(max_length=30,verbose_name='上传者')

#是否是有效的人物图片,只有一张图片人脸的是有效的

valide_choice = ((0, "否"), (1, "是"))

isvalide=models.SmallIntegerField(choices=valide_choice,verbose_name="有效",default=0)

#保存到一个表中,去掉一个表,允许为空

rects=models.TextField(verbose_name='面部位置',blank=True)

landmarks=models.TextField(verbose_name='面部标注',blank=True)

#每个rect对应一个面部描述,由dlib_face_recognition_resnet_model_v1.dat模型获得

descriptions=models.TextField(verbose_name='面部描述',blank=True)

#显示信息用

def __str__(self):

return f"姓名:{self.person_name} 文件:{self.file}"

8、view中的人脸采集模型

首先构建一个modelform类

class PersonInforModelForm(BootrapModelForm):

"""针对上传人物图片的模型

Args:

BootrapModelForm (_type_): _description_

"""

class Meta:

model=models.PersonInfor

exclude=["upload_user","create_time","isvalide","rects","landmarks","descriptions"]

bootstrap_exclude_fileds=["file"]

def clean_file(self):

file = self.cleaned_data['file']

ext = file.name.split('.')[-1].lower()

if ext not in ["bmp","jpg","png"]:

raise forms.ValidationError("仅支持bmp,jpg,png 类型文件")

return file

9、应用bootstrap的modelform

这里的BootrapModelForm是按照参考视频的写法写的一个能够应用bootstrap的类,定义如下:

from django import forms

class Bootstrap:

bootstrap_exclude_fileds=[]

def __init__(self,*args,**kwargs):

super().__init__(*args,**kwargs)

for name,field in self.fields.items():

#不需要bootstrap的字段

if name in self.bootstrap_exclude_fileds:

continue

if  field.widget.attrs:

field.widget.attrs['class']='form-control'

field.widget.attrs['placeholder']=field.label

else:

field.widget.attrs={"class":"form-control",'placeholder':field.label}

class BootrapModelForm(Bootstrap,forms.ModelForm):

pass

class BootrapForm(Bootstrap,forms.Form):

pass

10、后台处理

其次在定义好modelform类之后,可以直接读取前段异步到后台的post内容,form= PersonInforModelForm(request.POST,request.FILES),完整的处理函数如下,代码中dlibcompute是自定义的利用dlib处理图片的模块,请参考源码:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt

def scrapy_image(request):

if request.method=="POST":

#传入信息

form= PersonInforModelForm(request.POST,request.FILES)

if form.is_valid():

form.instance.create_time=datetime.datetime.now()

#form.instance.upload_user=request.session.info.userName

info=request.session.get("info")

if info:

form.instance.upload_user=info["userName"]

else:

form.instance.upload_user="test"

#先保存,否则没有图片

form.save()

#得到图片绝对路径

absolute_file_path = os.path.join('media',form.instance.file.name)

#print(form.instance.file.name)

#print(absolute_file_path)

#得到人脸信息

rects,image=dlibcompute.find_person_rect(absolute_file_path)

#讲数据转成字符序列

s=pickle.dumps(rects)

#print(len(rects))

isValide=0

if len(rects)==1:

isValide=1

models.PersonInfor.objects.filter(file=form.instance.file.name).update(isvalide=isValide,rects=s)

return JsonResponse({"status":True,"path":form.instance.file.name,"valide":isValide})

else:

return JsonResponse({"status":False,"errors":form.errors})

return render(request,"scraperimage.html")

四、人脸识别

人脸采集的思路是:从摄像头采集图片,对图片得到图片描述信息,把描述信息与存放到数据库中的采集图片信息进行欧式距离计算,设定一个阈值,如果小于这个值就是当前人物,记录最小的距离,这是可能的人物。

1、人脸识别模板

打开、拍照、关闭摄像头都是利用上节5中的scrapture.html文件,在人脸识别模板去掉人物姓名项,利用js隐藏响应的模块即可。在识别模块下发加入已经采集的图片信息,并更换提交按钮的url,以便后台采用不同的处理方式。模板代码如下:

{% extends 'scrapture.html' %}

{% block table %}

<div class="panel panel-default" style="margin:10px 10px">

<div class="panel-heading" >

<span class="glyphicon glyphicon-th-large" aria-hidden="true"></span>人物信息

</div>

<div class="panel-body">

<table class="table table-bordered">

<thead>

<tr>

<th>ID</th>

<th姓名</th>

<th>图片</th>

<th>姓名</th>

<th>上传时间</th>

<th>是否有效</th>

</tr>

</thead>

<tbody>

{% for obj in querySet%}

<tr>

<th scope="row">{{ obj.id }}</th>

<td><img src="/media/{{obj.file}}" style="height:100px"></img></td>

<td>{{obj.person_name}}</td>

<td>{{ obj.create_time |date:"Y年m月d日"}}</td>

<td>{{ obj.get_isvalide_display }}</td>

</tr>

{% endfor %}

</tbody>

</table>

</div>

</div>

{% endblock %}

{% block exjs%}

<script>

$(document).ready(function(){

playfunction();

photofunction();

uploadfunction();

initparams();

closevideofunction();

})

function initparams(){

show_result_alert=1;

$("#input_person").hide();

$("#input_person").val("test");//用测试的名字进行

$("#result_panel").hide();

//$("#footer").hide();//隐藏,用对话框提示有效性

$("#upload").val("识别");

ajaxurl="/facerecon/recon/";

}

</script>

{% endblock%}

2、识别后台代码

后台识别时,首先查看当前上传的图片是否有人脸信息,如果有再看原来人脸采集数据表中人脸描述字段是否已经计算,如果没有计算就重新计算原采集人脸的描述信息;如果采集的人脸都已经计算描述,就比较欧氏距离。

@csrf_exempt

def face_recon(request):

"""人脸识别

Args:

request (_type_): _description_

"""

if request.method=="GET":

#只显示有效信息

querySet = models.PersonInfor.objects.filter(isvalide=1)

return render(request,"personrecon.html",{"querySet":querySet})

#提交图片后进行识别

form= PersonInforModelForm(request.POST,request.FILES)

if form.is_valid():

file = request.FILES.get("file")

#返回两个路径一个用于显示,一个用于读取

url_file_name,absolute_file_path = handle_uploaded_file(file)

#print(url_file_name,absolute_file_path)

rects,image=dlibcompute.find_person_rect(absolute_file_path)

#print(len(rects))

if len(rects)!=1:

return JsonResponse({"status":True,"path":url_file_name,"valide":0,"person":"无法识别"})

#合适的人脸数据信息,对人脸数据进行读取

baseDir=os.path.join(settings.BASE_DIR,r"picturerec\utils")

detector=dlibcompute.get_front_face_dector()

landmarks_predictor=dlibcompute.get_point_5_infor(baseDir)

face_encoder=dlibcompute.get_face_encodeing(baseDir)

#print("*"*10)

#dlibcompute.face_encodings

#先把所有在人物信息表中的数据进行计算,如果计算过了就不必计算了

compute_person_description(detector=detector,landmarks_predictor=landmarks_predictor,face_encoder=face_encoder)

#计算当前照片的的描述和标志点

descriptions,_=dlibcompute.face_dector_encodings(image,detector=detector,landmarks_predictor=landmarks_predictor,face_encoder=face_encoder)

findperson,min_person=find_person(descriptions)

#有效的提交进行图片处理

return JsonResponse({"status":True,"path":url_file_name,"valide":1,"person":findperson,"min_person":min_person})

else:

return JsonResponse({"status":False,"errors":form.errors})

3、计算原采集人脸的描述信息

def compute_person_description(detector,landmarks_predictor,face_encoder):

#默认是blank,判断用""

querySet = models.PersonInfor.objects.filter(descriptions="",isvalide=1)

#print("query sets lin 148=",len(querySet))

for temp in querySet:

#对于所有没有计算描述的图片计算描述信息,已经计算的不用

absolute_file_path = os.path.join('media', str(temp.file))

description,landmarks=dlibcompute.face_encoding_by_file(absolute_file_path,detector,landmarks_predictor,face_encoder)

if description is None:

continue

s_description=pickle.dumps(description)

s_landmarks=pickle.dumps(landmarks)

models.PersonInfor.objects.filter(id=temp.id).update(landmarks=s_landmarks,descriptions=s_description)

这里注意的是,存入采集数据库的描述信息是以二进制形式保存的numpy.ndarray,存入时利用pickle.dumps进行的。

4、识别当前人是人脸采集中的哪一位

在PersonInfor中存放有当前采集人脸图片的描述信息,这些信息是numpy.ndarray形式,是利用pickle.dumps存入,读取时,我采用的方法是,首先利用ast.literal_eval转成数组然后利用pickle.loads转成ndarray,

L1=ast.literal_eval(temp.descriptions)

np_description=pickle.loads(L1)

函数find_person是根据当前识别图片的描述与数据库中存放的描述信息进行对比,然后找到当前人是哪一个如:

def find_person(temp_description):

if temp_description is None:

print("temp_description is None")

return "temp_description is None"

if len(temp_description)==0:

print("temp_description is empty")

querySet = models.PersonInfor.objects.filter(isvalide=1,descriptions__isnull=False)#得到数据集,必须要求描述不空

thread=0.4

find_person=""

min_value_person=""

min_value=10000

for temp in querySet:

#record_description=(temp.descriptions)

L1=ast.literal_eval(temp.descriptions)

np_description=pickle.loads(L1)

if len(np_description)==0:

print(f"description is zero {temp.id}:{temp.person_name}")

continue

print(len(np_description[0]))

d=distancecompute.Euclidean_distance(np_description,temp_description)

if d<min_value:

min_value=d

#搜索

min_value_person=f"{temp.person_name}"

if d<thread:

find_person=f"{temp.person_name}"

return find_person,min_value_person

五、人脸定位与描述

1、人脸位置监测

利用dlib进行人脸定位和人脸信息的描述,利用dlib可以快速的对人脸进行定位,并根据适当的模型得到人脸上的标志点。

detector = dlib.get_frontal_face_detector()

返回人脸监测器,给监测器传入图片信息可以得到当前图片的人脸位置信息,这些信息是多个矩形信息,图片中有几张脸就有几个矩形,矩形是左上角和右下角坐标存储的。

face_locations = detector(face_image, number_of_times_to_upsample)

2、标志位的获得

根据得到人脸位置,可以利用dlib.shape_predictor产生的预测器得到人脸标志点,dlib.shape_predictor需要传入训练好的模型,这个模型有两种,一种是5个标志点,对应文件是shape_predictor_5_face_landmarks.dat,另一种是68个点,对应文件是shape_predictor_68_face_landmarks.dat,这68个点排列位置时固定的,如图

正在上传…重新上传取消

如果模型文件路径为shape_5_file,那么参数预测的代码如下:

pose_predictor_5_point = dlib.shape_predictor(shape_5_file)

得到预测器,传入图片和detector得到的人脸位置,就可以得到人脸的标志点坐标,这个坐标是相对于图片的,左上角为0,0,向右,下为正对应横纵坐标。

如果图片face_image所有脸位置是face_locations,下面landmarks_predictor标志位的预测器,下列代码得到所有脸(这是一张图)的标志位。

raw_landmarks = [landmarks_predictor(face_image, face_location) for face_location in face_locations]#

3、描述向量的获得

利用dlib.face_recognition_model_v1可以得到人脸描述器,需要传入模型,这里用的是dlib_face_recognition_resnet_model_v1.dat,把文件名传入后得到描述器,调用描述器的compute_face_descriptor函数可以得到图像的描述信息,这个信息是128个元素的ndarray数字,compute_face_descriptor传入参数是图像,标志位向量。

项目中dlibcompute模块中函数就是计算当前图片的所有描述信息,并以ndarray形式返回。

def face_encodings(face_image,face_locations,landmarks_predictor, face_encoder, num_jitters=1):

"""返回图像中每个人脸的 128D 描述符"""

if landmarks_predictor and face_encoder:

# 检测面部特征点

raw_landmarks = [landmarks_predictor(face_image, face_location) for face_location in face_locations]

# 使用每个检测到的特征点计算每个检测到的人脸的编码,返回numpy的列表,方便转换

return np.array([np.array(face_encoder.compute_face_descriptor(face_image, raw_landmark_set, num_jitters)) for

raw_landmark_set in raw_landmarks]),np.array(raw_landmarks)

else:

return None,None

利用django实现在线人脸识别相关推荐

  1. Django实战(8)——在线人脸识别系统demo(对接Redis、初步实现人脸识别功能)

    接着上一篇Django实战(7)--在线人脸识别系统(第一步.实现图片上传和MySQL数据库的对接,ORM操作数据库)https://blog.csdn.net/qq_41938259/article ...

  2. ​​​​​​​CV:利用cv2(加载人脸识别xml文件及detectMultiScale函数得到人脸列表)+keras的load_model(加载表情hdf5、性别hdf5)并标注

    CV:利用cv2+自定义load_detection_model(加载人脸识别xml文件及detectMultiScale函数得到人脸列表)+keras的load_model(加载表情hdf5.性别h ...

  3. 聪明的人脸识别4——Pytorch 利用Retinaface+Facenet搭建人脸识别平台

    睿智的目标检测51--Pytorch 利用Retinaface+Facenet搭建人脸识别平台 学习前言 什么是Retinface和Facenet 1.Retinface 2.Facenet 整体实现 ...

  4. Android在线人脸识别登录系统

    Android在线人脸识别登录系统 前言 最近需要做一个Android的在线人脸识别项目,需求是能够在线人脸识别登录,找了很多资料都是价格很高或者是离线保存样本的,最后选择免费的虹软人脸识别,经过查询 ...

  5. 百度在线人脸识别技术性能测试

    1,百度在线人脸识别技术文档 https://cloud.baidu.com/doc/FACE/Face-Search.html#.E8.AF.B7.E6.B1.82.E8.AF.B4.E6.98.8 ...

  6. 高级货!Django实现基于人脸识别的门禁管理系统【源码】

    项目介绍 基于人脸识别的门禁管理系统 (Python+Django+RESTframework+JsonWebToken+Redis+Dlib) 该项目为宿舍门禁系统管理,并额外加入宿舍管理.水电费管 ...

  7. Python+Django实现基于人脸识别的门禁管理系统,附带源码!!

    已下项目为实战开发经验,微信搜索关注公众号 [ python语言空间 ],获取更多项目源码及资源. 项目介绍 基于人脸识别的门禁管理系统(Python+Django+RESTframework+Jso ...

  8. 利用卷积神经网络实现人脸识别(python+TensorFlow)

    利用CNN卷积神经网络实现人脸识别(python+TensorFlow) 使用的人脸数据是耶鲁大学的一个人脸数据集Yale_64x64.mat,数据集已经上传Yale 64x64.mat 程序: '' ...

  9. 基于Django的web人脸识别登录功能设计与实现

    0 引言 人脸识别技术日趋成熟,开源的人脸识别库使大众更容易开发自己的应用方案,降低学习门槛,如旷视科技.商汤科技.海康威视,百度人脸识别SDK.OpenCV的人脸识别库.Python的第三方人脸识别 ...

最新文章

  1. Windows 7 操作系统核心文件
  2. 字节跳动Java面试:java软件工程师简历描述项目
  3. Python:对字符串匹配算法的分析
  4. MySQL模糊查询—in关键字
  5. IdentityServer4系列 | 快速搭建简易项目
  6. 计算机网络自顶向下方法实验报告,计算机网络自顶向下方法试验三报告.doc
  7. ORA-00972: identifier is too long问题解决
  8. shell 免杀aspx_对于asp免杀webshell的一些总结
  9. 数据库优先生成EF CRUD演示
  10. android新闻客户端实验报告,基于Android平台的新闻客户端设计与实现
  11. 常用的 7 款 MySQL 客户端工具,你值得拥有
  12. Java核心技术 卷(一) 学习记录
  13. Excel模板免费分享(办公常用、甘特图、员工绩效考核等模板)
  14. 【娱乐】你以为我在水群?其实我在内卷。(qq、微信自动发消息脚本)
  15. 转载一些Unity插件及资源
  16. 蓝牙(三)蓝牙协议的初始化
  17. 获取执行程序的原路径(绝对路径)
  18. 系统部署在服务器,如何把系统部署在云服务器
  19. Java api文档自动生成工具smartdoc+torna
  20. Elasticsearch索引安装使用

热门文章

  1. 毕业设计 java网上购物商城系统(源码+论文)
  2. 好工具推荐系列:UML绘图软件drawio(类似visio画流程图/框图/类图软件)
  3. 总结MySQL和Oracle的语法区别
  4. html+js实现生成验证码实例代码分享
  5. python实现因子分析(FA)
  6. 【swift】swift quick start
  7. 汽车大梁生产线全液压铆接机液压系统设计
  8. 用three.js写一个小场景
  9. Forrester权威专家告诉你:欺诈与反欺诈5日谈
  10. SSHelper: 在ubuntu 和安卓手机之间无线传输文件