安装的模块版本:
- Django (1.11)
- dlib (19.7.0)
- python(3.6)
效果演示图:
dlib安装可参考:https://blog.youkuaiyun.com/ezhchai/article/details/79087046
Anaconda python3.6 安装下载:https://www.anaconda.com/download/
代码项目下载:https://download.youkuaiyun.com/download/u012434961/10826509
项目目录结构:
dlibUint.py
简单采用单例模式,避免68个人脸标注点预测器重复训练。
import dlib
import numpy as np
import cv2
import os
def singleton(cls):
instances = {}
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class dlibUint(object):
def __init__(self):
#项目路径
self.baseDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
#获取人脸分类器
self.detector = dlib.get_frontal_face_detector()
#获取人脸预测器
self.predictor = dlib.shape_predictor(self.baseDir + '\\Code\\shape_predictor_68_face_landmarks.dat')
views.py
上传的图片是base64字节码,需要转化成np序列
def facedetect(request):
if request.method=='POST':
try:
detector = dlibUint().detector
predictor = dlibUint().predictor
imgBase64 = request.POST.get('imgdata')
img_b64decode = base64.b64decode(imgBase64)
img_array = np.fromstring(img_b64decode,np.uint8) # 转换np序列
img=cv2.imdecode(img_array,cv2.COLOR_BGR2GRAY) # 转换Opencv格式
rects = detector(img, 1)
if( len(rects)<1):
raise Exception("未识别到人脸")
if len(rects)> 1 :
raise Exception("请上传个人照片")
array = np.array([[p.x, p.y] for p in predictor(img, rects[0]).parts()])
json_dict = \
{"StatusCode": 1,
"message": '',
"result": array.tolist()
}
except Exception as e:
json_dict = \
{"StatusCode": -1,
"message": str(e),
"result": ''
}
return JsonResponse(json_dict)
return JsonResponse(json_dict)
index.html
滑动条低于50% 是缩小,高于则进行放大。
上传图片时对图片的分辨率进行适度改小,(不然后面处理图片手机会变得很卡)。
//图片显示
var compressPicture = function (imgId, blob) {
var maxH = 800;
var maxW = 800;
var quality = 0.5, image = new Image();
image.src = blob;
image.onload = function () {
var that = this;
// 生成比例
var width = that.width, height = that.height;
//判断上传图片是否超过最大值
if (width > maxW || height > maxH) {
if (width > height) {
height = height * maxW / width;
width = maxW;
} else {
width = width * maxH / height;
height = maxH;
}
}
canvas.width = parseInt(width);
canvas.height = parseInt(height);
ctx.drawImage(that, 0, 0, parseInt(width), parseInt(height));
// 生成base64,兼容修复移动设备需要引入mobileBUGFix.js
var imgurl = canvas.toDataURL('image/jpeg', quality);
// 修复IOS兼容问题
if (navigator.userAgent.match(/iphone/i)) {
var mpImg = new MegaPixImage(image);
mpImg.render(canvas, {
maxWidth: width,
maxHeight: height,
quality: quality
});
imgurl = canvas.toDataURL('image/jpeg', quality);
}
$('#' + imgId).attr("src", imgurl);
oFaceDat = ctx.getImageData( 0, 0, that.width, that.height );
oImg.width = oFaceDat.width;
oImg.height = oFaceDat.height;
oImg.data = oFaceDat.data.slice(0);
};
};
图片处理用canvas进行处理
重点: faceFilter.js 是处理人脸器官缩放的。
下巴的缩放我采用该扇形区域内的像素点以蓝色的中心点,按滤镜的公式进行 像素点的挪移。
ScaleFactor = 1 - XY / PowRadius;
ScaleFactor = 1 - eyeStrength / 100 * ScaleFactor; //按照这种关系计算取样点的位置\
var PosX = parseInt(OffsetX * ScaleFactor + PointX);
var PosY = parseInt(OffSetY * ScaleFactor + PointY);
附上:比较好用的视频转gif:https://www.aconvert.com/cn/video/