├── .idea ├── .name ├── encodings.xml ├── modules.xml ├── misc.xml └── FlaskFaceRecognition.iml ├── static ├── pyy.jpg ├── Obama.jpg ├── bg_grey.jpeg ├── icon_add.png ├── icon_fold.png └── icon_recognize.png ├── screenshot ├── pc1.png └── pc2.png ├── know_images ├── 乔布斯 │ ├── images.jpg │ └── 5f3c2640b18f4f498b44175d6b825959.jpg ├── obama │ └── Obama.jpg ├── trump │ └── trump.jpeg ├── 沈腾 │ └── ab27e6e6b6d64df885f0f5e1a646eb37.jpg ├── 雷军 │ └── f790130b239346928ff36cc290adb744.jpg ├── 马云 │ └── 3ac36edd286c465c9d86544777210a01.jpg ├── 黄渤 │ └── 5f3c16429c3045d2ade48acc2fde0f86.jpg └── 马化腾 │ └── 8dbe23dcc123492d917280df8ea930cd.jpg ├── requirements.txt ├── test.py ├── README.md ├── train.py ├── app.py └── templates ├── video.js └── index.html /.idea/.name: -------------------------------------------------------------------------------- 1 | FlaskFaceRecognition -------------------------------------------------------------------------------- /static/pyy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/static/pyy.jpg -------------------------------------------------------------------------------- /static/Obama.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/static/Obama.jpg -------------------------------------------------------------------------------- /screenshot/pc1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/screenshot/pc1.png -------------------------------------------------------------------------------- /screenshot/pc2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/screenshot/pc2.png -------------------------------------------------------------------------------- /static/bg_grey.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/static/bg_grey.jpeg -------------------------------------------------------------------------------- /static/icon_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/static/icon_add.png -------------------------------------------------------------------------------- /static/icon_fold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/static/icon_fold.png -------------------------------------------------------------------------------- /know_images/乔布斯/images.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/know_images/乔布斯/images.jpg -------------------------------------------------------------------------------- /static/icon_recognize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/static/icon_recognize.png -------------------------------------------------------------------------------- /know_images/obama/Obama.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/know_images/obama/Obama.jpg -------------------------------------------------------------------------------- /know_images/trump/trump.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/know_images/trump/trump.jpeg -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /know_images/沈腾/ab27e6e6b6d64df885f0f5e1a646eb37.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/know_images/沈腾/ab27e6e6b6d64df885f0f5e1a646eb37.jpg -------------------------------------------------------------------------------- /know_images/雷军/f790130b239346928ff36cc290adb744.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/know_images/雷军/f790130b239346928ff36cc290adb744.jpg -------------------------------------------------------------------------------- /know_images/马云/3ac36edd286c465c9d86544777210a01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/know_images/马云/3ac36edd286c465c9d86544777210a01.jpg -------------------------------------------------------------------------------- /know_images/黄渤/5f3c16429c3045d2ade48acc2fde0f86.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/know_images/黄渤/5f3c16429c3045d2ade48acc2fde0f86.jpg -------------------------------------------------------------------------------- /know_images/乔布斯/5f3c2640b18f4f498b44175d6b825959.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/know_images/乔布斯/5f3c2640b18f4f498b44175d6b825959.jpg -------------------------------------------------------------------------------- /know_images/马化腾/8dbe23dcc123492d917280df8ea930cd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishrong/FlaskFaceRecognition/HEAD/know_images/马化腾/8dbe23dcc123492d917280df8ea930cd.jpg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Click==7.0 2 | dlib==19.16.0 3 | face-recognition==1.2.3 4 | face-recognition-models==0.3.0 5 | Flask==1.0.2 6 | Flask-Script==2.0.6 7 | itsdangerous==1.1.0 8 | Jinja2==2.10 9 | MarkupSafe==1.1.0 10 | numpy==1.15.4 11 | Pillow==5.4.1 12 | Werkzeug==0.14.1 13 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import face_recognition 2 | 3 | import train 4 | 5 | known_image = face_recognition.load_image_file("timg.jpg") 6 | known_encoding = face_recognition.face_encodings(known_image)#对脸部信息编码,一个人 7 | train.init() 8 | reconize_result = train.recognize_from_upload(known_image) # 识别结果 9 | print(reconize_result) -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 基于web的在线人脸识别系统 2 | ## 所涉及的python库 3 | * Flask 4 | * face_recognition 5 | 6 | ## 实现功能 7 | * 可以拖拽文件或者在系统的文件浏览中选择文件进行人脸识别 8 | * 可以对未知的人脸进行训练命名 9 | * 支持调用摄像头实时识别 10 | * 适配移动端与pc端 11 | 12 | ## 界面截图 13 | ![](https://github.com/fishrong/FlaskFaceRecognition/raw/master/screenshot/pc1.png) 14 | ![](https://github.com/fishrong/FlaskFaceRecognition/raw/master/screenshot/pc2.png) 15 | -------------------------------------------------------------------------------- /.idea/FlaskFaceRecognition.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 21 | 22 | 24 | -------------------------------------------------------------------------------- /train.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import face_recognition 4 | face_datas ={}#存图片信息以及人脸编码,格式:{"bob":[...,..],...} 5 | 6 | #添加数据:人脸编码信息 7 | def add_data(who,pic_name): 8 | known_image = face_recognition.load_image_file(pic_name) 9 | known_encoding = face_recognition.face_encodings(known_image)#对脸部信息编码,一个人 10 | if known_encoding==[]: 11 | print("图片错误:",pic_name) 12 | else: 13 | known_encoding = known_encoding[0] 14 | if who in face_datas: 15 | face_datas[who].append(known_encoding) 16 | 17 | else: 18 | face_datas[who] = [known_encoding] 19 | 20 | 21 | # 初始化,即训练文件中已有人脸信息 22 | def init(): 23 | names = [x for x in os.listdir("know_images")]#获取该文件夹下的目录名 24 | # print(names) 25 | for i in names: 26 | name = [x for x in os.listdir("./know_images/"+i)] 27 | # print(name) 28 | for j in name:#获取每一个文件夹下的图片名称 29 | add_data(i,"./know_images/"+i+"/"+j)#将文件夹名称及其目录下所有图片名称 30 | 31 | 32 | # 从服务端选择文件识别,用于测试 33 | def recognize_from_fold(who): 34 | unknown_image = face_recognition.load_image_file("obama2.jpeg") # 需识别图片 35 | unknown_encoding = face_recognition.face_encodings(unknown_image)[0] 36 | 37 | results = face_recognition.compare_faces(who, unknown_encoding) # 比较,返回[true] 或[false] 38 | print(results) 39 | 40 | 41 | # 从上传文件中识别 42 | def recognize_from_upload(file): 43 | img_info = [] 44 | 45 | unknown_image = face_recognition.load_image_file(file) # 待识别图片 46 | 47 | unknown_encoding = face_recognition.face_encodings(unknown_image) 48 | if unknown_encoding==[]: # 无人脸 49 | return "noface" 50 | face_locations = face_recognition.face_locations(unknown_image) 51 | print("face_locations",face_locations) 52 | 53 | for k in unknown_encoding: #遍历多张脸 54 | 55 | find = False 56 | for i in face_datas: # 遍历已训练的人脸编码信息 57 | if face_recognition.compare_faces(face_datas[i], k,tolerance=0.4)[0]: # 比较字典中与待识别图片,第一个参数为数组!!! 58 | img_info.append(i) 59 | find = True 60 | break 61 | if not find: 62 | img_info.append("somebody") 63 | return img_info,face_locations 64 | 65 | if __name__ == '__main__': 66 | init() 67 | # recognize_from_fold(face_datas['trump']['encoding']) 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import os 3 | 4 | import uuid 5 | 6 | 7 | 8 | from PIL import Image 9 | from flask import Flask, render_template, request 10 | import face_recognition 11 | from flask_script import Manager 12 | import train 13 | 14 | 15 | app = Flask(__name__) 16 | # manager = Manager(app) 17 | app.config['secret_key'] = "ddddd" 18 | train.init() 19 | 20 | 21 | @app.route('/') 22 | def index(): 23 | return render_template("index.html") 24 | 25 | 26 | @app.route('/pichandler', methods=['post', 'get']) 27 | def pichandler(): 28 | name = "" 29 | locations ="" 30 | 31 | pic_data_url = request.form.get("picdata") 32 | # print(">>>>>>>",request.form.get('picdata')) 33 | imgdata = base64.b64decode(pic_data_url.split(',')[1]) 34 | with open("temp3.jpg", 'wb') as f: # 把上传图片保存为文件,!!!有待优化 35 | f.write(imgdata) 36 | 37 | # pic = request.files.get("myPic") # 上传图片 38 | # print("pic:",pic) 39 | 40 | reconize_result = train.recognize_from_upload("temp3.jpg") # 识别结果 41 | print("Recognize_result:", reconize_result) 42 | print(type(reconize_result)) 43 | for i in reconize_result[0]: 44 | if name == "": 45 | name = i 46 | else: 47 | name = name + "," + i 48 | for i in reconize_result[1]: 49 | if locations == "": 50 | locations = i 51 | else: 52 | locations = str(locations) + ";" + str(i) 53 | 54 | return str(name)+"-"+str(locations) 55 | 56 | 57 | @app.route('/update', methods=['post', 'get']) 58 | def update(): 59 | pic_data_url = request.form.get("picdata") 60 | imgdata = base64.b64decode(pic_data_url.split(',')[1]) 61 | 62 | with open("temp.jpg", 'wb') as f: # 把上传图片保存为文件,!!!有待优化 63 | f.write(imgdata) 64 | known_image = face_recognition.load_image_file("temp.jpg") 65 | name_list = request.form.get("picinfo").split(",") # 上传名字 66 | print("need_to_update:", name_list) 67 | for name in name_list: # * 为内容未改变 68 | if name != "*": 69 | # known_encoding = face_recognition.face_encodings(known_image)[name_list.index(name)] # 对改变名字的脸部信息编码 70 | face_location = face_recognition.face_locations(known_image)[name_list.index(name)] 71 | top, right, bottom, left = face_location 72 | face_image = known_image[top:bottom, left:right] 73 | pil_image = Image.fromarray(face_image) 74 | if not os.path.exists("know_images/" + name): 75 | os.mkdir("know_images/" + name) 76 | uuid_str = uuid.uuid4().hex 77 | pil_image.save("know_images/" + name + "/" + uuid_str + ".jpg") # 保存图片 78 | train.add_data(name, "know_images/" + name + "/" + uuid_str + ".jpg") 79 | 80 | # print(known_encoding) 81 | return "success" 82 | 83 | 84 | @app.route('/vidohandler',methods=['get','post']) 85 | def vido_handler(): 86 | name = "" 87 | locations = "" 88 | pic_data_url = request.form.get("picdata") 89 | imgdata = base64.b64decode(pic_data_url.split(',')[1]) 90 | 91 | with open("temp2.jpg", 'wb') as f: # 把上传图片保存为文件,!!!有待优化 92 | f.write(imgdata) 93 | reconize_result = train.recognize_from_upload("temp2.jpg") # 识别结果 94 | print("reconize_result:",reconize_result) 95 | if reconize_result=="noface": 96 | return reconize_result 97 | for i in reconize_result[0]: 98 | if name == "": 99 | name = i 100 | else: 101 | name = name + "," + i 102 | for i in reconize_result[1]: 103 | if locations == "": 104 | locations = i 105 | else: 106 | locations = str(locations) + ";" + str(i) 107 | 108 | return str(name)+"-"+str(locations) 109 | 110 | 111 | @app.route('/testjpg',methods=['post','get']) 112 | def testjpg(): 113 | pic_data_url = request.form.get("picdata") 114 | #print(">>>>>>>",request.form.get('picdata')) 115 | 116 | imgdata = base64.b64decode(pic_data_url.split(',')[1]) 117 | 118 | with open("temp3.jpg", 'wb') as f: # 把上传图片保存为文件,!!!有待优化 119 | f.write(imgdata) 120 | return "success" 121 | 122 | 123 | 124 | if __name__ == '__main__': 125 | app.run(host="0.0.0.0",port="5001",ssl_context='adhoc') 126 | -------------------------------------------------------------------------------- /templates/video.js: -------------------------------------------------------------------------------- 1 | //访问用户媒体设备的兼容方法 2 | function getUserMedia(constraints, success, error) { 3 | if (navigator.mediaDevices.getUserMedia) { 4 | //最新的标准API 5 | navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error); 6 | } else if (navigator.webkitGetUserMedia) { 7 | //webkit核心浏览器 8 | navigator.webkitGetUserMedia(constraints, success, error) 9 | } else if (navigator.mozGetUserMedia) { 10 | //firfox浏览器 11 | navigator.mozGetUserMedia(constraints, success, error); 12 | } else if (navigator.getUserMedia) { 13 | //旧版API 14 | navigator.getUserMedia(constraints, success, error); 15 | } 16 | } 17 | 18 | // let video = document.getElementById('video'); 19 | 20 | 21 | context.strokeStyle = "red"; 22 | context2.strokeStyle = "red"; 23 | 24 | function success(stream) { 25 | //兼容webkit核心浏览器 26 | let CompatibleURL = window.URL || window.webkitURL; 27 | //将视频流设置为video元素的源 28 | //console.log(stream); 29 | myStream = stream; 30 | //video.src = CompatibleURL.createObjectURL(stream); 31 | video.srcObject = stream; 32 | video.play(); 33 | } 34 | 35 | function error(error) { 36 | console.log(`访问用户媒体设备失败${error.name}, ${error.message}`); 37 | document.getElementById("testvideo").innerHTML=`访问用户媒体设备失败${error.name}`+`${error.message}`; 38 | } 39 | 40 | function playvideo() { 41 | if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) { 42 | //调用用户媒体设备, 访问摄像头 43 | getUserMedia({video: {width: 640, height: 480}}, success, error); 44 | } else { 45 | alert('不支持访问用户媒体'); 46 | } 47 | } 48 | 49 | 50 | $('#upload').click(function () { 51 | console.log("开始上传..."); 52 | context2.drawImage(video, 0, 0, video_width, video_height); 53 | var src = canvas2.toDataURL("image/jpeg"); 54 | console.log(src); 55 | send(src, "{{ url_for('vido_handler') }}") 56 | }); 57 | var timer; 58 | 59 | function start_recognization() { 60 | timer = setInterval(upload, 800); 61 | } 62 | 63 | function stop_recognization() { 64 | clearInterval(timer); 65 | context.clearRect(0, 0, video_width, video_height); 66 | } 67 | 68 | function upload() { 69 | // console.log("开始上传..."); 70 | 71 | context2.drawImage(video, 0, 0, video_width, video_height); 72 | var src = canvas2.toDataURL("image/jpeg"); 73 | send_video_pic(src, "{{ url_for('vido_handler') }}") 74 | } 75 | 76 | function send_video_pic(fileList, url) { 77 | var fd = new FormData(); 78 | fd.append("picdata", fileList); 79 | var xhr = new XMLHttpRequest(); 80 | xhr.open("post", url, true); 81 | //服务器响应 82 | 83 | xhr.onreadystatechange = function () { 84 | context.clearRect(0, 0, video_width, video_height); 85 | 86 | if (xhr.status === 200 && xhr.readyState === 4 && xhr.responseText !== 'noface') { 87 | // console.log("success"); 88 | 89 | var responses = xhr.responseText.split("-");//'-'分开名字和位置 90 | var response_names = responses[0].split(",");//名字数组 91 | // console.log("res_names:", response_names); 92 | 93 | 94 | var response_loctions = responses[1].split(";");//位置数组 95 | //div_names.innerHTML = "";//与服务器传回顺序颠倒 96 | 97 | for (var i = 0; i < response_names.length; i++) { 98 | 99 | 100 | //设置名字位置 101 | var res_loction = response_loctions[i].replace("(", "").replace(")", "").split(","); 102 | //console.log("res_locations:", res_loction); 103 | var top = parseInt(res_loction[0]); 104 | var right = parseInt(res_loction[1]); 105 | var bottom = parseInt(res_loction[2]); 106 | var left = parseInt(res_loction[3]); 107 | context.strokeStyle = "red"; 108 | context.fillStyle = "red"; 109 | 110 | context.fillRect(left, bottom, right - left, 30);//文字背景色 111 | context.strokeRect(left, top, right - left, bottom - top);//脸部框 112 | context.fillStyle = "white"; 113 | context.font = "24px serif"; 114 | context.textAlign = "center"; 115 | context.fillText(response_names[i], (left + right) / 2, bottom + 20);//文字 116 | 117 | 118 | } 119 | 120 | } 121 | 122 | }; 123 | xhr.send(fd); 124 | } -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 在线人脸识别系统 11 | 18 | 19 | 20 |
21 |
22 |
23 |

在线人脸识别系统

24 | 25 | 27 | 28 | 30 | 31 |
32 |
33 | 34 | 45 | 46 |
47 |
48 |
49 | 50 | ... 51 |
52 | 53 |

拖拽图片到窗口开始识别

54 | 55 |
56 |
57 |
58 |
59 | 60 | 61 |
62 |
63 |
64 |
65 |
66 | 67 | 68 | 69 | 70 | 71 | 457 | 460 | 461 | --------------------------------------------------------------------------------