Python创建接口项目(FastAPI)及人脸识别

2022-06-15 11:30:06 浏览数 (1)

前言

我们要实现一个人脸识别的功能,人脸识别的都是调用本地的图片,所以我们搭建一个接口服务来提供图片的上传。

接口

一般接口

接口使用FastAPI框架

https://fastapi.tiangolo.com/zh/#_4

注意

该框架需要Python 3.6 及更高版本

环境变量中添加

KEY

VALUE

Path

D:ToolsPython310D:ToolsPython310Scripts

另外要注意

系统变量的优先级要比用户变量的优先级高,如果配置后还是2.x版本,就要看看是否系统变量中也配置了。 配置完成后要重启开发工具,不用重启电脑。

安装

代码语言:javascript复制
pipenv install fastapi
pipenv install uvicorn[standard]

创建一个 main.py 文件并写入以下内容:

代码语言:javascript复制
from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
    return {"item_id": item_id, "q": q}

通过以下命令运行服务器:

代码语言:javascript复制
pipenv run uvicorn main:app --reload

使用浏览器访问

http://127.0.0.1:8000/items/5?q=somequery

这样我们的接口服务就搭建好了。

对接的接口文档地址

http://127.0.0.1:8000/docs

静态文件

代码语言:javascript复制
from fastapi.staticfiles import StaticFiles
app.mount("/web", StaticFiles(directory="web"), name="web")

所有以/web/开头的请求都会访问到web目录中。

文件上传

一般文件上传

要用 File,需要先安装这个库

代码语言:javascript复制
pipenv install python-multipart

代码

代码语言:javascript复制
# -*- coding:utf-8 -*-
import uuid
import uvicorn
import os

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.get("/")
def read_root():
    return {"code": 0, "msg": "请求成功"}


# file 参数类型是字节 bytes
@app.post("/upfile/")
async def upfile(file: bytes = File(...)):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def uploadfile(image: UploadFile = File(...)):
    try:
        if not os.path.exists("images"):
            os.makedirs("images")
    except Exception as e:
        print(e)
    suffix_arr = image.filename.split(".")
    suffix = suffix_arr[len(suffix_arr) - 1]
    file_name = os.getcwd()   "/images/"   str(uuid.uuid1())   "."   suffix

    with open(file_name, "wb ") as f:
        f.write(image.file.read())
        f.close()

    return {"filename": file_name}


if __name__ == "__main__":
    uvicorn.run(app="main:app", host="127.0.0.1", port=8000, reload=True, debug=True)

Base64图片上传

代码语言:javascript复制
import base64
from fastapi import Body

@app.post("/base64file")
async def uploadfile(image=Body(None), suffix=Body(None)):
    imgdata = base64.b64decode(image)
    file_name = os.getcwd()   "/images/"   str(uuid.uuid1())   "."   suffix
    file = open(file_name, 'wb')
    file.write(imgdata)
    file.close()
    return {"code": 0, "obj": file_name}

人像识别

face_recognition

https://github.com/ageitgey/face_recognition

安装

代码语言:javascript复制
pipenv install cmake
pipenv install dlib
pipenv install face_recognition

使用

代码语言:javascript复制
import face_recognition
image = face_recognition.load_image_file("your_file.jpg")
face_locations = face_recognition.face_locations(image)

deepface

https://github.com/serengil/deepface

安装

代码语言:javascript复制
pipenv install deepface

使用

代码语言:javascript复制
from deepface import DeepFace
result = DeepFace.verify(img1_path = "img1.jpg", img2_path = "img2.jpg")
print(result)

注意

这个库主要用于对比人脸相似度,人脸的特征等功能。

接口对接人脸识别

代码语言:javascript复制
# -*- coding:utf-8 -*-
import uuid
import uvicorn
import os

from fastapi import FastAPI, File, UploadFile
from starlette.responses import RedirectResponse
import face_recognition

app = FastAPI()


@app.get("/")
def root():
    response = RedirectResponse(url="/docs")
    return response


@app.post("/uploadfile/")
async def uploadfile(image: UploadFile = File(...)):
    try:
        if not os.path.exists("images"):
            os.makedirs("images")
    except Exception as e:
        print(e)
    suffix_arr = image.filename.split(".")
    suffix = suffix_arr[len(suffix_arr) - 1]
    file_name = os.getcwd()   "/images/"   str(uuid.uuid1())   "."   suffix

    with open(file_name, "wb ") as f:
        f.write(image.file.read())
        f.close()
    image = face_recognition.load_image_file(file_name)
    face_locations = face_recognition.face_locations(image)
    if len(face_locations) > 0:
        return {"code": 0, "obj": face_locations}
    else:
        return {"code": 1, "obj": face_locations}

if __name__ == "__main__":
    uvicorn.run(app="main:app", host="127.0.0.1", port=8000, reload=True, debug=True)

WEB获取摄像头做识别

代码语言:javascript复制
<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title></title>
</head>

<body>
  <div class="imgouter">
    <div class="left_div"><video id="v"></video></div>
    <canvas id="canvas" style="display:none;"></canvas>
    <img id="photo" alt="photo" class="right_div">
  </div>
  <div class="msg"></div>

</body>
<style>
  body {
    margin: 0;
    padding: 0;
  }

  .imgouter {
    display: flex;
    height: 90vh;
    width: 100vw;
  }

  .left_div,
  .right_div {
    width: 0;
    flex: 1;
  }

  #v {
    width: 100%;
    height: 100%;
    object-fit: fill;
  }

  .msg {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 10vh;
    font-size: 30px;
  }
</style>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
  function upload_img (imgstr) {
    let arr = imgstr.split(";base64,");
    let suffix = arr[0].split("/")[1];
    let base64str = arr[1];
    let para = {
      image: base64str,
      suffix: suffix
    };
    axios
      .post('/base64file', para)
      .then(function (response) {
        let data = response.data;
        if (data.code === 0) {
          document.querySelector(".msg").innerHTML = "发现人像:"   data.obj.length;
        } else {
          document.querySelector(".msg").innerHTML = "未发现人像";
        }
      })
      .catch(function (error) {
        console.log(error);
      });

  }
  !(function () {
    // 老的浏览器可能根本没有实现 mediaDevices,所以我们可以先设置一个空的对象
    if (navigator.mediaDevices === undefined) {
      navigator.mediaDevices = {};
    }
    if (navigator.mediaDevices.getUserMedia === undefined) {
      navigator.mediaDevices.getUserMedia = function (constraints) {
        // 首先,如果有getUserMedia的话,就获得它
        var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

        // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
        if (!getUserMedia) {
          return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
        }

        // 否则,为老的navigator.getUserMedia方法包裹一个Promise
        return new Promise(function (resolve, reject) {
          getUserMedia.call(navigator, constraints, resolve, reject);
        });
      }
    }
    const constraints = {
      video: true,
      audio: false
    };
    let videoPlaying = false;
    let v = document.getElementById('v');
    let promise = navigator.mediaDevices.getUserMedia(constraints);
    promise.then(stream => {
      // 旧的浏览器可能没有srcObject
      if ("srcObject" in v) {
        v.srcObject = stream;
      } else {
        // 防止在新的浏览器里使用它,应为它已经不再支持了
        v.src = window.URL.createObjectURL(stream);
      }
      v.onloadedmetadata = function (e) {
        v.play();
        videoPlaying = true;
        take_pic();
        setInterval(() => {
          take_pic();
        }, 3000);
      };
    }).catch(err => {
      console.error(err.name   ": "   err.message);
    });

    function take_pic () {
      if (videoPlaying) {
        let canvas = document.getElementById('canvas');
        canvas.width = v.videoWidth;
        canvas.height = v.videoHeight;
        canvas.getContext('2d').drawImage(v, 0, 0);
        let data = canvas.toDataURL("image/jpeg", 0.8);
        //console.info(data);
        upload_img(data);
        document.getElementById('photo').setAttribute('src', data);
      }
    }

  })();
</script>

</html>

web端只能传base64,后端也要处理base64

代码语言:javascript复制
import base64
import uuid
import os
from fastapi import Body

@app.post("/base64file")
async def uploadfile(image=Body(None), suffix=Body(None)):
    imgdata = base64.b64decode(image)
    file_name = os.getcwd()   "/images/"   str(uuid.uuid1())   "."   suffix
    file = open(file_name, 'wb')
    file.write(imgdata)
    file.close()
    try:
        image = face_recognition.load_image_file(file_name)
        face_locations = face_recognition.face_locations(image)
        if os.path.exists(file_name):
            os.remove(file_name)
        if len(face_locations) > 0:
            return {"code": 0, "obj": face_locations}
        else:
            return {"code": 1, "obj": face_locations}
    except Exception as e:
        return {"code": 1, "obj": [], "msg": str(e)}

0 人点赞