因为我本专业是光电信息科学与工程,最近课设要做一个人脸辨认。关于我这种半途转前端的on9仔,当然是不会做啦。经过查找材料发现,能够使用opencv这个开源的计算机视觉和机器学习软件库来实现,我就想着上网CTRL+CV
一段代码交差啦哈哈哈
灵光一闪
居然能够做到人脸辨认,那岂不是能够在我的项目的登录体系中加入人脸登录,那样面试的时分又有东西可吹了
废话不多,直接开干。
思路
- 前端注册时上传自己的大头照,后端经过OpenCV练习
- 登录时前端经过tracking.js辨认出自己的人脸,再使用canvas转正base64的图片上传给后端,后端拿这张图片进行辨认
技能栈
- 前端:Vue2 + tracking.js
- 后端:Python + OpenCV + Flask
不会Python的小伙伴不要担心,我也不会哈哈哈,只用调用opencv的库就ok了
人脸辨认演示
我这儿用的是这篇文章的代码用Python进行人脸辨认[包含源代码],里面有源码和翻开教程(本来计划直接就用来交差的)
能够点我这儿下载源代码 人脸辨认代码,或许文章后边有我封装好的代码
翻开后,在终端运转以下指令,安装依赖
pip install numpy opencv-python
pip install dlib
pip install face_recognition
然后履行一下main.py文件,就能够看到运转的成果了,
总结一下
经过Python
使用OpenCV
先练习train
文件夹下的图片,然后咱们拿test
文件夹下的图片用来测试,OpenCV
会经过train
下最像的图片,放回该图片的文件名(人名)
前端实践
注册
这一部分只要把用户名(最终辨认出来的姓名)和图片上传给后端
注意 照片一定要明晰的大头照,不然OpenCV
练习不了会报错
<form
method="post"
action="http://localhost:3000/register/"
enctype="multipart/form-data"
target="hideIframe1"
>
<h3>注册</h3>
<input type="text" placeholder="账号" name="username" />
<input type="file" name="photo" />
<button style="margin-top: 10px" type="submit">注册账号</button>
</form>
tracking.js
tracking.js
的安装网上说不建议用nmp,咱们能够到官网上下载tracking.js然后把文件放在src/assets
目录下文件夹更名为 tracking 方便引入
之后咱们只要在需求的页面上引证
import "@/assets/tracking/build/data/face-min.js";
人脸登录
这一步,便是调用摄像头,辨认出人脸,把人脸图片上传到后端,后端会回来辨认后的成果
注意 我这儿仅仅本地调试,上线需求运用有https的域名 不然无法调用摄像头
<div class="video-box">
<video id="video" width="320" height="240" preload autoplay loop muted></video>
<canvas id="canvas" width="320" height="240"></canvas>
</div>
<canvas id="screenshotCanvas" width="320" height="240"></canvas>
// 初始化设置
async init() {
this.video = document.getElementById("video");
this.screenshotCanvas = document.getElementById("screenshotCanvas");
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
// 固定写法
let tracker = new window.tracking.ObjectTracker("face");
tracker.setInitialScale(4);
tracker.setStepSize(2);
tracker.setEdgesDensity(0.1);
window.tracking.track("#video", tracker, {
camera: true,
});
// 我这儿写了个sleep函数等两秒再履行,避免还没反响过来,摄像头一翻开就辨认上传了
await this.sleep(2000);
let _this = this;
tracker.on("track", function (event) {
// 检测出人脸 绘画人脸方位
context.clearRect(0, 0, canvas.width, canvas.height);
event.data.forEach(function (rect) {
context.strokeStyle = "#0764B7";
context.strokeRect(rect.x, rect.y, rect.width, rect.height);
// 上传图片
_this.uploadLock && _this.screenshotAndUpload();
});
});
},
// 上传图片
async screenshotAndUpload() {
// 上锁避免重复发送恳求
this.uploadLock = false;
// 制作当前帧图片转换为base64格局
let canvas = this.screenshotCanvas;
let video = this.video;
let ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
console.log("camvas", canvas);
// 将图片保存为png格局
let base64Img = canvas.toDataURL("image/png");
// 运用 base64Img 恳求接口即可
// console.log("base64Img:", base64Img);
//我后端地址是localhost:3000,我这儿用了webpack代理解决跨域
axios.post("/api/check", {
data: base64Img,
}).then((res) => {
。。。。。。
});
// 恳求接口成功今后翻开锁
// await this.sleep(1500);
// this.uploadLock = true;
},
到这一步前端的工作就悉数完结了
后端实践
Flask敞开服务器
我真的不会Python
,可是思路上后端要做的工作都一样,我先上网搜了下发现能够使用Flask敞开一个本地的服务器
from flask import Flask, request
app = Flask(__name__)
@app.route("/test/")
def test():
return "hello world"
if __name__ == '__main__':
app.run(host='127.0.0.1', port=3000)
运转起来,在浏览器拜访localhost:3000/tset/
,就能够看到hello word
这样咱们只需求写两个接口注册和辨认
注册
咱们只需求把前端传来的图片存在本地的,并以username
命名图片
@app.route('/register/', methods=['POST'])
def register():
img = request.files.get('photo') # 从post恳求中获取图片数据
username = request.form.get('username', '')
suffix = '.' + img.filename.split('.')[-1] # 获取文件后缀名
basedir = os.path.abspath(os.path.dirname(__file__)) # 获取当前文件途径
photo = '/static/uploads/' + username + suffix # 拼接相对途径,并把username作为图片姓名
img_path = basedir + photo # 拼接图片完好保存途径,
img.save(img_path) # 保存图片
return {'msg': 'ok'}
辨认
这儿咱们拿到的是前端传来base64格局的图片,咱们要把它转成图片并保存在本地(temp.png)
@app.route('/check', methods=['POST'])
def check():
src = request.data
print(src)
data = str(src).split(',')[1][:-3]
img_data = base64.b64decode(data)
with open("./test/temp.png", 'wb') as f:
f.write(img_data)
这儿使用OpenCV辨认这张图片,然后把成果回来
return {'msg': 'ok'}
要点来了
因为我真的一点也不会Python,我的想法很简单,计划把main.py里的代码包装成一个函数最终把辨认出来的数组return,我在/check接口中接纳。
我咨询了一下我同学一些语法问题,他是视觉辨认
这一块的大佬(10多个省奖),他听了后觉得代码写的十分的不高雅,于是乎他把一切main.py的代码封装成一个类,并把悉数代码写入一个文件中,代码如下
完好后端代码
- face_distances这个值越小阐明精度越高,大于这个值就回来
["no match"]
- 辨认完放回一个的数组
msg:['Chris]
import face_recognition as fr
import cv2
import numpy as np
import os, base64
from flask import Flask, request, Response, render_template
app=Flask(__name__)
class face:
def __init__(self, train_path):
self.known_names = []
self.known_name_encodings = []
self.train_path = train_path
def init(self):
images = os.listdir(self.train_path)
for _ in images:
image = fr.load_image_file(self.train_path + _)
image_path = self.train_path + _
encoding = fr.face_encodings(image)[0]
self.known_name_encodings.append(encoding)
self.known_names.append(os.path.splitext(os.path.basename(image_path))[0].capitalize())
def add(self, img_path):
image = fr.load_image_file(img_path)
encoding = fr.face_encodings(image)[0]
self.known_name_encodings.append(encoding)
self.known_names.append(os.path.splitext(os.path.basename(img_path))[0].capitalize())
# print(self.known_names)
def compare(self, img_path):
image = img_path
image = cv2.imread(image)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
face_locations = fr.face_locations(image)
face_encodings = fr.face_encodings(image, face_locations)
names = []
for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
matches = fr.compare_faces(self.known_name_encodings, face_encoding)
name = ""
face_distances = fr.face_distance(self.known_name_encodings, face_encoding)
print(face_distances)
if min(face_distances) > 0.45:
// face_distances这个值越小阐明精度越高,大于这个值就回来["no match"]
return ["no match"]
best_match = np.argmin(face_distances)
if matches[best_match]:
name = self.known_names[best_match]
names.append(name)
cv2.rectangle(image, (left, top), (right, bottom), (0, 0, 255), 2)
cv2.rectangle(image, (left, bottom - 15), (right, bottom), (0, 0, 255), cv2.FILLED)
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(image, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
print(names)
return names
# cv2.imshow("Result", image)
# cv2.imwrite("./output.jpg", image)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
@app.route('/register/', methods=['POST'])
def register():
global recognition
img = request.files.get('photo') # 从post恳求中获取图片数据
username = request.form.get('username', '')
suffix = '.' + img.filename.split('.')[-1] # 获取文件后缀名
basedir = os.path.abspath(os.path.dirname(__file__)) # 获取当前文件途径
photo = '/train/' + username + suffix # 拼接相对途径
img_path = basedir + photo # 拼接图片完好保存途径,时刻戳命名文件防止重复
img.save(img_path) # 保存图片
recognition.add(img_path)
return {'msg': 'ok'}
@app.route('/check', methods=['POST'])
def check():
global recognition
src = request.data
data = str(src).split(',')[1][:-3]
img_data = base64.b64decode(data)
with open("./test/temp.png", 'wb') as f:
f.write(img_data)
names = recognition.compare("./test/temp.png")
// 放回一个辨认的数组
return {'msg': names}
if __name__ == "__main__":
recognition = face("./train/")
recognition.init()
app.run(host='127.0.0.1', port=3000)
到这一步后端一切的工作也做完啦
演示
登录
我英文名叫Chris,照片就放简历的大头照哈哈哈
辨认
成功后提示,接下来操作… (自由发挥)
整个人脸登录已完结,恭喜自己成为CV程序猿哈哈哈
END
- 感想
或许许多小伙伴会说,为什么不自己写一个人脸辨认的算法呀,你都根本不明白Python
,这仅仅调库。我想说关于咱们这种小白,咱们能够站在伟人的膀子
上,使用市面上各种开源的库
,来结合自己的需求,完结公司的项目。咱们先锻炼自己的编码思维,再对自己感兴趣的范畴进行专研。✊✊
- 谢谢我们的支持,希望这篇文章能够协助到有需求的小伙伴,有各种问题能够评论区留言或许私信我