使用React构建面部识别Web应用程序

使用React构建面部识别Web应用程序

时间:2020-6-27 作者:gykj

如果您要构建面部识别Web应用程序,则本文将向您介绍一种简单的集成方式。在本文中,我们将介绍使用React的人脸识别Web应用程序的人脸检测模型和Predict API。

什么是面部识别,为什么重要?

面部识别是一种涉及对人脸进行分类和识别的技术,主要是通过绘制各个面部特征并数学记录唯一比率并将数据存储为面部打印。您的移动相机中的人脸检测将利用此技术。

面部识别技术如何工作

面部识别是一种增强的应用程序生物识别软件,它使用深度学习算法将实时捕获的图像或数字图像与存储的面部图像进行比较,以验证个人身份。但是,深度学习是一类机器学习算法,它使用多层来从原始输入中逐步提取更高级别的功能。例如,在图像处理中,较低的层可以标识边缘,而较高的层可以标识与人有关的概念,例如数字或字母或面部。

面部检测是在扫描图像中识别人脸的过程。提取过程涉及获取面部区域(例如眼睛间距,变化,角度和比率)以确定对象是否为人。

Clarifai API入门

在本文中,我们仅关注一种名为人脸检测的Clarifai模型。该特定模型返回有关图像包含人脸的可能性的概率分数,并使用边界框协调这些人脸出现的位置。该模型非常适合任何构建监视或检测人类活动的应用程序的人。该预测API分析你的图像或视频,告诉你什么是他们的内部。API将返回概念列表,以及图像中包含这些概念的可能性的相应概率。

随着我们继续本教程,您将可以将所有这些与React集成在一起,但是既然您已经简要了解了有关Clarifai API的更多信息,那么您可以在此处进行深入研究。

我们在本文中构建的内容类似于手机中弹出式照相机上的面部检测框。下图显示了更多信息:

示例应用

您会看到一个检测人脸的矩形框。我们将使用React构建这种简单的应用程序。

设置开发环境

第一步是为您的项目创建一个新目录并启动一个新的react项目,您可以为其选择任何名称。我将在该项目中使用npm软件包管理器,但您可以根据自己的选择使用yarn。

注意本教程需要Node.js。如果没有,请在继续操作之前访问Node.js官方网站进行下载和安装。

打开终端并创建一个新的React项目。

我们使用的create-react-app是一个学习React的舒适环境,并且是开始为React 构建新的单页应用程序的最佳方法。这是一个全局软件包,我们将从npm安装。它创建了一个包含webpack,babel和许多不错功能的入门项目。

/* install react app globally */
npm install -g create-react-app

/* create the app in your new directory */
create-react-app face-detect

/* move into your new react directory */
cd face-detect

/* start development sever */
npm start

让我先解释一下上面的代码。我们正在使用全局npm install -g create-react-app安装create-react-app软件包,以便您可以在任何项目中使用它。create-react-app face-detect由于将在全球范围内使用,因此将为您创建项目环境。之后,cd face-detect将您移至我们的项目目录。npm start将启动我们的开发服务器。现在我们准备开始构建我们的应用程序。

您可以使用任何选择的编辑器打开项目文件夹。我使用Visual Studio代码。它是一个免费的IDE,带有大量的插件,可简化您的生活,并且可用于所有主要平台。您可以从官方网站下载

此时,您应该具有以下文件夹结构。

FACE-DETECT TEMPLATE
├── node_modules
├── public 
├── src
├── .gitignore
├── package-lock.json
├── package.json
├── README.md

注意: React为我们提供了一个页面的React应用程序模板,让我们摆脱不必要的需求。首先,删除src文件夹中的logo.svg文件,并替换src / app.js中的代码,如下所示。

import React, { Component } from "react";
import "./App.css";
class App extends Component {
  render() {
    return (
      
      
    );
  }
}
export default App;

src / App.js

我们要做的是通过删除徽标和其他不必要的代码来清除组件。现在,将src / App.css替换为下面的最小CSS:

.App {
  text-align: center;
}
.center {
  display: flex;
  justify-content: center;
}

我们将在此项目中使用Tachyons,它是一个工具,可让您使用尽可能少的CSS创建快速加载,高度可读和100%响应的界面。

您可以通过npm将tachyons安装到该项目:

# install tachyons into your project
npm install tachyons

安装完成后,让我们将Tachyons添加到下面的src / index.js文件中的项目中。

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
// add tachyons below into your project, note that its only the line of code you adding here
import "tachyons";

ReactDOM.render(<App />, document.getElementById("root"));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.register();

上面的代码与您之前的代码没有什么不同,我们所做的只是添加了tachyons的import语句。

因此,让我们在src / index.css文件中为界面提供一些样式。


body {
  margin: 0;
  font-family: "Courier New", Courier, monospace;
  -webkit-font-smoothing: antialiased;
  -Moz-osx-font-smoothing: grayscale;
  background: #485563; /* fallback for old browsers */
  background: linear-gradient(
    to right,
    #29323c,
    #485563
  ); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
button {
  cursor: pointer;
}
code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
    monospace;
}

src / index.css

在上面的代码块中,我向页面添加了背景色和光标指针,这时我们已经设置了界面,让我们开始在下一个会话中创建组件。

构建我们的React组件

在这个项目中,我们将有两个组件,我们有一个URL输入框,可以从互联网上为我们获取图像- ImageSearchForm我们还有一个图像组件,可以通过人脸检测框显示图像FaceDetect。让我们开始构建以下组件:

src目录中创建一个名为Components的新文件夹。在打开ImageSearchForm文件夹之后,在src / Components内部创建另外两个文件夹ImageSearchFormFaceDetect,并按照ImageSearchForm.jsImageSearchForm.css创建两个文件。

然后打开FaceDetect目录,并按照FaceDetect.jsFaceDetect.css创建两个文件。

完成所有这些步骤后,您的文件夹结构应在src / Components目录中如下所示:

src/Components TEMPLATE

├── src
  ├── Components 
    ├── FaceDetect
      ├── FaceDetect.css 
      ├── FaceDetect.js 
    ├── ImageSearchForm
      ├── ImageSearchForm.css 
      ├── ImageSearchForm.js

至此,我们有了Components文件夹结构,现在让我们将其导入到我们的App组件中。打开您的src / App.js文件夹,使其看起来像我下面的内容。

import React, { Component } from "react";
import "./App.css";
import ImageSearchForm from "./components/ImageSearchForm/ImageSearchForm";
// import FaceDetect from "./components/FaceDetect/FaceDetect";

class App extends Component {
  render() {
    return (
      <div className="App">
        <ImageSearchForm />
        {/* <FaceDetect /> */}
      </div>
    );
  }
}
export default App;

src / App.js

在上面的代码中,我们在第10行和第11行安装了组件,但是如果您注意到FaceDetect注释已经注释掉了,因为在下一节之前我们尚未对其进行处理,并且为了避免代码中的错误,我们需要在其中添加注释。我们还将组件导入了我们的应用程序。

要开始使用ImageSearchForm文件,请打开该ImageSearchForm.js文件,然后让我们在下面创建组件。下面的示例是我们的ImageSearchForm组件,它将包含一个输入表单和一个按钮。

import React from "react";
import "./ImageSearchForm.css";

// imagesearch form component

const ImageSearchForm = () => {
  return (
    <div className="ma5 to">
      <div className="center">
        <div className="form center pa4 br3 shadow-5">
          <input className="f4 pa2 w-70 center" type="text" />
          <button className="w-30 grow f4 link ph3 pv2 dib white bg-blue">
            Detect
          </button>
        </div>
      </div>
    </div>
  );
};
export default ImageSearchForm;

ImageSearchForm.js

在上面的行组件中,我们具有输入表单以从Web上获取图像,并具有检测按钮以执行面部检测操作。我在这里使用Tachyons CSS,其工作原理类似于引导程序;您只需要打电话className。您可以在他们的网站上找到更多详细信息。

要设置组件的样式,请打开ImageSearchForm.css文件。现在,让我们对以下组件进行样式设置:

.form {
  width: 700px;
  background: radial-gradient(
      circle,
      transparent 20%,
      slategray 20%,
      slategray 80%,
      transparent 80%,
      transparent
    ),
    radial-gradient(
        circle,
        transparent 20%,
        slategray 20%,
        slategray 80%,
        transparent 80%,
        transparent
      )
      50px 50px,
    linear-gradient(#a8b1bb 8px, transparent 8px) 0 -4px,
    linear-gradient(90deg, #a8b1bb 8px, transparent 8px) -4px 0;
  background-color: slategray;
  background-size: 100px 100px, 100px 100px, 50px 50px, 50px 50px;
}

CSS样式属性是表单背景的CSS模式,只是为了提供美观的设计。您可以在此处生成您选择的CSS模式并将其替换为。

再次打开您的终端以运行您的应用程序。

/* To start development server again */
npm start

我们的ImageSearchForm组件显示在下图中。

图片搜索页
图片搜索页。(大型预览

现在,我们的应用程序与第一个组件一起运行。

图像识别API

现在是时候创建一些功能,在其中输入图像URL,按“检测”,如果图像存在面部,则图像会出现并带有面部检测框。在此之前,请设置我们的Clarifai帐户以将API集成到我们的应用中。

如何设置CLARIFAI帐户

该API可以利用其机器学习应用程序或服务。对于本教程,我们将利用每月可进行5,000次操作的开发人员免费使用的层。您可以在此处阅读更多信息并注册登录后将带您进入帐户信息中心,点击我的第一个应用程序,或创建一个应用程序以获取您的API密钥,我们将在此应用程序中使用该API密钥。

注意:您不能使用我的,必须先得到我的。

Clarifai仪表板
Clarifai-仪表板。(大型预览

这就是您上面的仪表板的外观。您在那里的API密钥可让您访问Clarifai服务。图片下方的箭头指向复制图标以复制您的API密钥。

如果您使用Clarifai模型,您会看到他们使用机器学习来训练所​​谓的模型,他们通过给计算机提供许多图片来训练计算机,您还可以创建自己的模型并使用自己的图像和概念来教它。但是这里我们将利用他们的人脸检测模型

人脸检测模型具有一个预测API,我们可以对其进行调用(在此处的文档中了解更多信息)。

因此,让我们在clarifai下面安装软件包。

打开您的终端并运行以下代码:

/* Install the client from npm */
npm install clarifai

完成安装后clarifai,我们需要使用前面学习的上述安装将软件包导入到我们的应用程序中。

但是,我们需要在输入搜索框中创建功能以检测用户输入的内容。我们需要一个状态值,以便我们的应用程序知道用户输入的内容,记住它并在得到更改后随时对其进行更新。

您需要从Clarifai获得API密钥,并且还必须clarifai通过npm进行安装。

以下示例显示了我们如何导入clarifai应用程序以及如何实现API密钥。

请注意,(作为用户)您必须从网上获取任何清晰的图像URL并将其粘贴到输入字段中;该URL的状态值imageUrl如下。

import React, { Component } from "react";
// Import Clarifai into our App
import Clarifai from "clarifai";
import ImageSearchForm from "./components/ImageSearchForm/ImageSearchForm";
// Uncomment FaceDetect Component
import FaceDetect from "./components/FaceDetect/FaceDetect";
import "./App.css";

// You need to add your own API key here from Clarifai.
const app = new Clarifai.App({
  apiKey: "ADD YOUR API KEY HERE",
});

class App extends Component {
  // Create the State for input and the fectch image
  constructor() {
    super();
    this.state = {
      input: "",
      imageUrl: "",
    };
  }

// setState for our input with onInputChange function
  onInputChange = (event) => {
    this.setState({ input: event.target.value });
  };

// Perform a function when submitting with onSubmit
  onSubmit = () => {
        // set imageUrl state
    this.setState({ imageUrl: this.state.input });
    app.models.predict(Clarifai.FACE_DETECT_MODEL, this.state.input).then(
      function (response) {
        // response data fetch from FACE_DETECT_MODEL 
        console.log(response);
        /* data needed from the response data from clarifai API, 
           note we are just comparing the two for better understanding 
           would to delete the above console*/ 
        console.log(
          response.outputs[0].data.regions[0].region_info.bounding_box
        );
      },
      function (err) {
        // there was an error
      }
    );
  };
  render() {
    return (
      <div className="App">
        // update your component with their state
        <ImageSearchForm
          onInputChange={this.onInputChange}
          onSubmit={this.onSubmit}
        />
        // uncomment your face detect app and update with imageUrl state
        <FaceDetect imageUrl={this.state.imageUrl} />
      </div>
    );
  }
}
export default App;

在上面的代码块中,我们导入了clarifai以便可以访问Clarifai服务并添加我们的API密钥。我们使用state管理的价值inputimageUrlonSubmit当单击“ 检测”按钮时,我们有一个函数被调用,我们设置imageUrlClarifai FACE DETECT MODEL的状态并获取图像,该模型返回响应数据或错误。

现在,我们将从API获得的数据记录到控制台。我们将来会在确定人脸检测模型时使用它。

目前,您的终端会出现错误,因为我们需要更新ImageSearchFormFaceDetect组件文件。

使用以下代码更新ImageSearchForm.js文件:

import React from "react";
import "./ImageSearchForm.css";
// update the component with their parameter
const ImageSearchForm = ({ onInputChange, onSubmit }) => {
  return (
    <div className="ma5 mto">
      <div className="center">
        <div className="form center pa4 br3 shadow-5">
          <input
            className="f4 pa2 w-70 center"
            type="text"
            onChange={onInputChange}    // add an onChange to monitor input state
          />
          <button
            className="w-30 grow f4 link ph3 pv2 dib white bg-blue"
            onClick={onSubmit}  // add onClick function to perform task
          >
            Detect
          </button>
        </div>
      </div>
    </div>
  );
};
export default ImageSearchForm;

在上面的代码块中,我们onInputChange从props 传递了一个函数,当onChange输入字段上发生事件时要调用该onSubmit函数,我们对与onClick事件关联的函数也进行了相同的操作。

现在,让我们创建上面FaceDetectsrc / App.js中未注释的组件。打开FaceDetect.js文件并输入以下代码:

在下面的示例中,我们创建了FaceDetect组件以传递props imageUrl

import React from "react";
// Pass imageUrl to FaceDetect component
const FaceDetect = ({ imageUrl }) => {
  return (
  # This div is the container that is holding our fetch image and the face detect box
    <div className="center ma">
      <div className="absolute mt2">
                        # we set our image SRC to the url of the fetch image 
        <img alt="" src={imageUrl} width="500px" heigh="auto" />
      </div>
    </div>
  );
};
export default FaceDetect;

这个组件将显示我们已经能够确定的图像,作为我们从API获得响应的结果。这就是为什么我们要传递imageUrl到组件作为道具,这是我们再设置为src在的img标签。

现在我们都有我们的ImageSearchForm组件并且FaceDetect组件正在工作。Clarifai FACE_DETECT_MODEL已使用其模型检测到了图像中人的位置,并向我们​​提供了数据,但没有提供可在控制台中检查的框。

图像链接表
图像链接表。(大型预览

现在,我们的FaceDetect组件正在工作,而Clarifai Model在从我们在ImageSearchForm组件中输入的URL提取图像时正在工作。但是,要查看Clarifai提供给我们的数据响应,以注释我们的结果以及响应中需要的数据部分(如果您还记得我们console.logApp.js文件中创建了两个)。

因此,让我们打开控制台以查看下面的响应:

图像链接表[控制台]
图像链接表[控制台]。(大型预览

console.log上面可以看到的第一个语句是Clarifai FACE_DETECT_MODEL的响应数据(如果成功的话),如果成功的话,console.log我们可以使用,而第二个语句是我们正在使用的数据,以便使用来检测人脸data.region.region_info.bounding_box。在第二个console.log中,bounding_box数据为:

bottom_row: 0.52811456
left_col: 0.29458505
right_col: 0.6106333
top_row: 0.10079138

在我们看来,这可能有点扭曲,但让我简要地分解一下。此时,Clarifai FACE_DETECT_MODEL已使用其模型检测到了人脸在图像中的位置,并向我们​​提供了数据而非框,我们需要做一些数学和计算才能显示框或我们想要做的任何事情与我们应用程序中的数据。所以让我解释一下上面的数据,

bottom_row: 0.52811456 这表明我们的面部检测框从底部图像高度的52%开始。
left_col: 0.29458505 这表明我们的面部检测框从左侧图像宽度的29%开始。
right_col: 0.6106333 这表明我们的面部检测框从右侧的图像宽度的61%开始。
top_row: 0.10079138 这表明我们的面部检测框从顶部的图像高度的10%开始。

如果您看一下我们上面的应用程序中间阶段,您会发现该模型可以准确地检测出图像中人脸的bounding_box。但是,这使我们不得不编写一个函数来创建包含样式的框,该函数将根据API提供给我们的响应数据,根据我们正在构建的内容的早期信息显示一个框。因此,让我们在下一部分中实现它。

创建面部检测盒

这是我们网络应用程序的最后一部分,通过使用Clarifai FACE_DETECT_MODEL计算从网络上获取的任何图像的面部位置,然后显示一个面部框,我们可以全面实现面部识别。让我们打开src / App.js文件,并包含以下代码:

在下面的示例中,我们calculateFaceLocation使用来自Clarifai的响应数据创建了一个带有一点数学运算的函数,然后计算人脸与图像宽度和高度的坐标,以便为它提供一种显示人脸框的样式。

import React, { Component } from "react";
import Clarifai from "clarifai";
import ImageSearchForm from "./components/ImageSearchForm/ImageSearchForm";
import FaceDetect from "./components/FaceDetect/FaceDetect";
import "./App.css";

// You need to add your own API key here from Clarifai.
const app = new Clarifai.App({
  apiKey: "ADD YOUR API KEY HERE",
});

class App extends Component {
  constructor() {
    super();
    this.state = {
      input: "",
      imageUrl: "",
      box: {},  # a new object state that hold the bounding_box value
    };
  }

  // this function calculate the facedetect location in the image
  calculateFaceLocation = (data) => {
    const clarifaiFace =
      data.outputs[0].data.regions[0].region_info.bounding_box;
    const image = document.getElementById("inputimage");
    const width = Number(image.width);
    const height = Number(image.height);
    return {
      leftCol: clarifaiFace.left_col * width,
      topRow: clarifaiFace.top_row * height,
      rightCol: width - clarifaiFace.right_col * width,
      bottomRow: height - clarifaiFace.bottom_row * height,
    };
  };

  /* this function display the face-detect box base on the state values */
  displayFaceBox = (box) => {
    this.setState({ box: box });
  };

  onInputChange = (event) => {
    this.setState({ input: event.target.value });
  };

  onSubmit = () => {
    this.setState({ imageUrl: this.state.input });
    app.models
      .predict(Clarifai.FACE_DETECT_MODEL, this.state.input)
      .then((response) =>
        # calculateFaceLocation function pass to displaybox as is parameter
        this.displayFaceBox(this.calculateFaceLocation(response))
      )
      // if error exist console.log error
      .catch((err) => console.log(err));
  };

  render() {
    return (
      <div className="App">
        <ImageSearchForm
          onInputChange={this.onInputChange}
          onSubmit={this.onSubmit}
        />
        // box state pass to facedetect component
        <FaceDetect box={this.state.box} imageUrl={this.state.imageUrl} />
      </div>
    );
  }
}
export default App;

我们在这里所做的第一件事是创建另一个名为的状态值box,它是一个空对象,其中包含我们收到的响应值。我们要做的下一件事是创建一个名为的函数calculateFaceLocation,当在onSubmit方法中调用它时,它将接收从API获得的响应。在calculateFaceLocation方法内部,我们将image调用所获得的元素对象分配给document.getElementById("inputimage")我们用来执行一些计算的对象。

leftCol clarifaiFace.left_col是宽度的百分比乘以图像的宽度,那么我们将获得图像的实际宽度以及left_col应在的位置。
topRow clarifaiFace.top_row是高度的百分比乘以图像的高度,那么我们将获得图像的实际高度以及top_row应位于的高度。
rightCol 这会从(clarifaiFace.right_colwidth)中减去宽度,从而知道right_Col应该在哪里。
bottomRow 从(clarifaiFace.right_colheight)中减去高度,即可知道bottom_Row应该在哪里。

在该displayFaceBox方法中,我们将box值的状态更新为从调用获得的数据calculateFaceLocation

我们需要更新我们的FaceDetect组件,以打开FaceDetect.js文件,并向其中添加以下更新。

import React from "react";
// add css to style the facebox
import "./FaceDetect.css";
// pass the box state to the component

const FaceDetect = ({ imageUrl, box }) => {
  return (
    <div className="center ma">
      <div className="absolute mt2">
            /* insert an id to be able to manipulate the image in the DOM */
        <img id="inputimage" alt="" src={imageUrl} width="500px" heigh="auto" />
       //this is the div displaying the faceDetect box base on the bounding box value 
      <div
          className="bounding-box"
          // styling that makes the box visible base on the return value
          style={{
            top: box.topRow,
            right: box.rightCol,
            bottom: box.bottomRow,
            left: box.leftCol,
          }}
        ></div>
      </div>
    </div>
  );
};
export default FaceDetect;

为了显示框在脸部周围,我们将box对象从父组件传递到该FaceDetect组件中,然后可以使用该组件对img标签进行样式设置。

我们导入了尚未创建的CSS,打开FaceDetect.css并添加以下样式:

.bounding-box {
  position: absolute;
  box-shadow: 0 0 0 3px #fff inset;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  cursor: pointer;
}

注意下面的样式和最终输出,您可以看到我们将盒子阴影的颜色设置为白色并显示柔韧性。

此时,您的最终输出应如下所示。在下面的输出中,我们现在使用面部框来显示面部检测并使用白色的边框样式颜色。

最终应用1
最终应用。(大型预览

让我们尝试下面的另一个图像:

最终应用程式2
最终应用。(大型预览

结论

我希望您喜欢本教程。我们已经学习了如何构建可以与更多功能集成到我们未来项目中的人脸识别应用程序,还学习了如何在React中使用出色的机器学习API。您始终可以从以下参考资料中阅读有关Clarifai API的更多信息。如果您有任何问题,可以将其留在评论部分,我们很乐意回答每一个问题,并为您解决任何问题。

Github上提供了本文的支持库

 

版权所有:https://www.eraycloud.com 转载请注明出处