Cách tạo một Ứng dụng Phát hiện Khuôn mặt Với React Native

Có phải bạn là một nhà phát triển ứng dụng lai muốn thêm tính năng phát hiện khuôn mặt vào trong ứng dụng của bạn, nhưng bạn không có ý tưởng rằng mình sẽ bắt đầu từ đâu? Để bắt đầu, bạn có thể đọc bài Giới thiệu về Phát hiện Khuôn mặt trên Android, hướng dẫn bạn cách cài đặt tính năng gốc phát hiện khuôn mặt trên Android. Nhưng nếu bạn giống tôi và bạn không muốn viết code Java mà tạo một mô-đun React Native để thực hiện việc này cho bạn, thì bạn đang ở đúng chỗ rồi đấy.

Trong hướng dẫn này, chúng ta tìm hiểu Face Detection API, là một phần của Microsoft Cognitive Services. API này cho phép các nhà phát triển dễ dàng cài đặt tính năng phát hiện khuôn mặt trong các ứng dụng. Trong hướng dẫn này, tôi sẽ giả định rằng đây không phải là ứng dụng React Native đầu tiên của bạn. Nếu bạn là người mới bắt đầu làm quen với React Native, thì tôi khuyên bạn nên đọc Hướng dẫn Làm quen của Facebook trên trang web React Native. Hướng dẫn đó chỉ ra cho bạn cách thiết lập môi trường và tạo dự án React Native đầu tiên của bạn.

Yêu cầu

Mặc dù trong hướng dẫn này chúng ta tập trung vào nền tảng Android, nhưng chỉ cần một chút chỉnh sửa, bạn đã có thể thêm hỗ trợ cho các nền tảng khác. Đảm bảo là bạn đã cài đặt Android Studio. Bạn có thể tải Android Studio về từ trang nhà phát triển của Google.

1. Face Detection API Là gì?

Trước khi chúng ta bắt đầu viết ứng dụng, tôi muốn dành một chút thời gian để nói về API mà chúng ta sẽ sử dụng để phát hiện khuôn mặt. Face Detection API của Microsoft cung cấp tính năng phát hiện khuôn mặt và nhận dạng khuôn mặt thông qua một API dựa trên đám mây. API này cho phép chúng ta gửi một yêu cầu HTTP có chứa một hình ảnh hoặc URL của một hình ảnh hiện có trên web, và nhận dữ liệu về bất kỳ khuôn mặt nào được phát hiện ra trong hình ảnh.

Gửi Yêu cầu đến API

Bạn có thể thực hiện các yêu cầu đến Face Detection API của Microsoft bằng cách gửi một yêu cầu POST đến https://api.projectoxford.ai/face/v1.0/detect. Yêu cầu nên chứa các thông tin header sau đây:

  • Content-Type: Trường header này chứa kiểu dữ liệu body của yêu cầu. Nếu bạn đang gửi URL của hình ảnh trên web, thì giá trị của trường header này phải là application/json. Nếu bạn đang gửi một hình ảnh, hãy thiết lập trường header này thành application/octet-stream.
  • Ocp-Apim-Subscription-Key: Trường header này chứa khóa API được sử dụng để xác thực các yêu cầu của bạn. Tôi sẽ hướng dẫn cho bạn cách để lấy được một khóa API sau trong hướng dẫn này.

Mặc định, API chỉ trả về dữ liệu về các hộp được sử dụng để bao quanh các khuôn mặt đã được phát hiện trong hình ảnh. Trong phần còn lại của hướng dẫn này, tôi sẽ tham chiếu đến các hộp này dưới dạng là các hộp khuôn mặt. Tùy chọn này có thể bị vô hiệu hoá bằng cách thiết lập tham số truy vấn returnFaceRectangle thành false. Giá trị mặc định là true, điều đó có nghĩa là bạn không phải chỉ định nó trừ khi bạn muốn vô hiệu hóa tùy chọn này.

Bạn có thể cung cấp một vài tham số truy vấn tùy chọn khác để truy xuất các thông tin phụ về các khuôn mặt được phát hiện:

  • returnFaceId: Nếu được thiết lập thành true, thì tùy chọn này sẽ gán một định danh duy nhất cho mỗi khuôn mặt được phát hiện.
  • returnFaceLandmarks: Bằng cách kích hoạt tùy chọn này, API sẽ trả về một mảng các landmark của khuôn mặt được phát hiện, bao gồm mắt, mũi và môi. Mặc định tùy chọn này không được bật.
  • returnFaceAttributes: Nếu tùy chọn này được kích hoạt, thì API sẽ tìm kiếm và trả về các thuộc tính duy nhất cho mỗi khuôn mặt được phát hiện. Bạn cần cung cấp một danh sách các thuộc tính được phân cách bởi dấu phẩy mà bạn muốn, chẳng hạn như tuổi tác, giới tính, nụ cười, mái tóc, tư thế đầu và kính.

Dưới đây là một phản hồi mẫu mà bạn nhận được từ API cho yêu cầu đến URL sau đây:

https://api.projectoxford.ai/face/v1.0/detect?faceId=true&faceLandmarks=true&faceAttributes=age,gender,smile,facialHair,headPose,glasses
[
    {
        "faceId": "c5c24a82-6845-4031-9d5d-978df9175426",
        "faceRectangle": {
            "width": 78,
            "height": 78,
            "left": 394,
            "top": 54
        },
        "faceLandmarks": {
            "pupilLeft": {
                "x": 412.7,
                "y": 78.4
            },
            "pupilRight": {
                "x": 446.8,
                "y": 74.2
            },
            "noseTip": {
                "x": 437.7,
                "y": 92.4
            },
            "mouthLeft": {
                "x": 417.8,
                "y": 114.4
            },
            "mouthRight": {
                "x": 451.3,
                "y": 109.3
            },
            "eyebrowLeftOuter": {
                "x": 397.9,
                "y": 78.5
            },
            "eyebrowLeftInner": {
                "x": 425.4,
                "y": 70.5
            },
            "eyeLeftOuter": {
                "x": 406.7,
                "y": 80.6
            },
            "eyeLeftTop": {
                "x": 412.2,
                "y": 76.2
            },
            "eyeLeftBottom": {
                "x": 413.0,
                "y": 80.1
            },
            "eyeLeftInner": {
                "x": 418.9,
                "y": 78.0
            },
            "eyebrowRightInner": {
                "x": 4.8,
                "y": 69.7
            },
            "eyebrowRightOuter": {
                "x": 5.5,
                "y": 68.5
            },
            "eyeRightInner": {
                "x": 441.5,
                "y": 75.0
            },
            "eyeRightTop": {
                "x": 446.4,
                "y": 71.7
            },
            "eyeRightBottom": {
                "x": 447.0,
                "y": 75.3
            },
            "eyeRightOuter": {
                "x": 451.7,
                "y": 73.4
            },
            "noseRootLeft": {
                "x": 428.0,
                "y": 77.1
            },
            "noseRootRight": {
                "x": 435.8,
                "y": 75.6
            },
            "noseLeftAlarTop": {
                "x": 428.3,
                "y": 89.7
            },
            "noseRightAlarTop": {
                "x": 442.2,
                "y": 87.0
            },
            "noseLeftAlarOutTip": {
                "x": 424.3,
                "y": 96.4
            },
            "noseRightAlarOutTip": {
                "x": 446.6,
                "y": 92.5
            },
            "upperLipTop": {
                "x": 437.6,
                "y": 105.9
            },
            "upperLipBottom": {
                "x": 437.6,
                "y": 108.2
            },
            "underLipTop": {
                "x": 436.8,
                "y": 111.4
            },
            "underLipBottom": {
                "x": 437.3,
                "y": 114.5
            }
        },
        "faceAttributes": {
            "age": 71.0,
            "gender": "male",
            "smile": 0.88,
            "facialHair": {
                "mustache": 0.8,
                "beard": 0.1,
                "sideburns": 0.02
            }
        },
        "glasses": "sunglasses",
        "headPose": {
            "roll": 2.1,
            "yaw": 3,
            "pitch": 0
        }
    }
]

Phản hồi mẫu này khá dễ hiểu vì vậy tôi sẽ không đi sâu vào ý nghĩa của từng thuộc tính. Dữ liệu có thể được sử dụng để hiển thị những khuôn mặt được phát hiện, các thuộc tính khác nhau của chúng và cách bạn có thể hiển thị chúng với người dùng. Điều này đạt được bằng cách dịch tọa độ x và y hoặc top và left.

Lấy một Khoá API

Để sử dụng Face Detection API của Microsoft, mỗi yêu cầu phải được xác thực bằng một khoá API. Dưới đây là các bước bạn cần thực hiện để lấy một khóa như vậy.

Tạo một tài khoản Microsoft Live nếu bạn chưa có. Đăng nhập vào tài khoản Microsoft Live của bạn và đăng ký một Tài khoản Azure của Microsoft. Nếu bạn vẫn chưa có tài khoản Microsoft Azure, bạn có thể đăng ký dùng thử miễn phí, cho phép bạn truy cập vào các dịch vụ của Microsoft trong 30 ngày.

Đối với Face Detection API, nó cho phép bạn gửi tối đa 20 cuộc gọi API miễn phí mỗi phút. Nếu bạn đã có một tài khoản Azure, thì bạn có thể đăng ký gói Pay-As-You-Go để bạn chỉ phải phải trả cho những gì bạn sử dụng.

Một khi tài khoản Microsoft Azure của bạn được thiết lập xong, bạn sẽ được chuyển hướng đến Microsoft Azure Portal. Trong portal, hãy chuyển đến thanh tìm kiếm và nhập cognitive services trong trường tìm kiếm. Nhấp vào kết quả có dòng chữ Cognitive Services accounts (preview). Bạn sẽ thấy một giao diện tương tự như sau:

Nhấp vào nút Add và điền vào form mà bạn thấy:

  • Account Name: Nhập tên mà bạn muốn đặt cho tài nguyên.
  • API Type: Chọn Face Detection API
  • Pricing Tier: Đối với mục đích thử nghiệm, hãy chọn free tier (tối đa 20 cuộc gọi API mỗi phút). Nếu bạn muốn sử dụng dịch vụ trong sản phẩm, hãy chọn một tuỳ chọn khác phù hợp với nhu cầu của ứng dụng của bạn.
  • Subscription: Chọn Free trial nếu bạn đang sử dụng một tài khoản Microsoft Azure mới. Nếu không, hãy chọn tùy chọn Pay-As-You-Go.
  • Resource Group: Chọn một cái nếu bạn đã có sẵn. Nếu không, tạo một Resource Group mới bằng cách chọn tùy chọn New và nhập tên cho Resource Group.
  • Location: Chọn West US.

Trong bước tiếp theo, bạn cần phải đồng ý với các điều khoản và điều kiện của Microsoft để tiếp tục. Nhấp vào nút Create và chờ cho Resource hoàn tất việc triển khai.

Sau khi triển khai xong, hãy nhấp vào liên kết All resources ở thanh sidebar để xem các tài nguyên mà bạn hiện có. Cái mà bạn vừa mới tạo ra sẽ được liệt kê trong đó. Nếu không, hãy thử làm mới trang.

Nhấp vào Resource mà bạn đã tạo ra và nhấp vào biểu tượng cái khoá để xem các khóa API liên kết với Resource. Mặc định, hai khoá được tạo ra và bạn có thể sử dụng một trong hai.

2. Xây dựng Ứng dụng

Trước khi chúng ta bắt đầu xây dựng ứng dụng, hãy để tôi cung cấp cho bạn một cái nhìn khái quát về ứng dụng. Như tôi đã đề cập trước đó, chúng ta sẽ xây dựng một ứng dụng phát hiện khuôn mặt. Ứng dụng sẽ có hai nút, một là để chọn một hình ảnh và một để phát hiện các khuôn mặt. Nút chọn hình ảnh sẽ yêu cầu người dùng chọn một nguồn, camera của thiết bị hoặc thư viện hình ảnh.

Nếu camera được chọn, thì ứng dụng camera mặc định sẽ được khởi chạy. Nếu thư viện hình ảnh được chọn, thì ứng dụng sẽ cho phép người dùng chọn một bức ảnh từ thư viện hình ảnh. Khi một hình ảnh đã được chọn, nút để phát hiện khuôn mặt sẽ hiện lên. Nhấn vào nút này sẽ gửi một yêu cầu đến Face Detection API của Microsoft, sẽ trả về dữ liệu chứa các khuôn mặt đã được phát hiện. Bằng phản hồi từ API, các hộp nhỏ sẽ được vẽ xung quanh khuôn mặt đã được phát hiện, bao gồm nhãn cho giới tính và độ tuổi của người đó.

Sau đây là ảnh minh hoạ cho ứng dụng:

Bước 1: Cài đặt các Phụ thuộc

Bây giờ chúng ta đã sẵn sàng để xây dựng ứng dụng. Hãy bắt đầu bằng cách cài đặt các phụ thuộc. Mở cửa sổ terminal mới trong thư mục hiện hành của bạn và thực thi lệnh sau:

react native init FaceDetector

Lệnh này tạo ra một dự án React Native mới cho chúng ta, và tại thời điểm bài viết, là phiên bản 0.25. Khi quá trình cài đặt đã hoàn tất, hãy chuyển đến thư mục của dự án.

Tiếp theo, chúng ta cài đặt ba thư viện mà chúng ta sẽ sử dụng để phát triển ứng dụng:

npm install lodash react-native-fetch-blob react-native-image-picker --save
  • lodash: Chúng ta chỉ sử dụng phương thức map của lodash. Chúng ta sử dụng phương thức này để chuyển đổi kết quả mà chúng ta nhận được từ API thành một thành phần mà chúng ta sẽ kết xuất.
  • react-native-image-picker: Thư viện này được sử dụng để thêm khả năng chọn một hình ảnh bằng camera hoặc từ thư viện hình.
  • react-native-fetch-blob: Thư viện này được sử dụng để gửi các yêu cầu kết nối mạng có nội dung BLOB. Face Detection API đặc biệt cần dữ liệu blob của ảnh, nhưng API fetch mặc định không hỗ trợ điều đó, đó là lý do tại sao chúng ta sử dụng thư viện này để xử lý việc đó cho chúng ta.

Bước 2: Cấu hình Dự án

Vì không phải tất cả các mô-đun React Mative đều hỗ trợ React Native Package Manager, nên chúng ta cần phải cấu hình dự án một cách thủ công vì vậy mà các mô-đun này sẽ hoạt động mà không gặp vấn đề gì. Cụ thể, chúng ta cần phải cấu hình dự án cho react-native-image-picker để hoạt động đúng.

Bên trong thư mục hiện hành của bạn, mở tập tin android/settings.gradle và thêm đoạn code sau đây ngay sau include ': app':

include ':react-native-image-picker'
project(':react-native-image-picker').projectDir = new File(settingsDir, '../node_modules/react-native-image-picker/android')



Mở tập tin android/app/build.gradle và tìm phần dependencies. Nó sẽ tương tự như thế này:

dependencies 
    compile fileTree(dir: "libs", include: ["*.jar"])
    compile "com.android.support:appcompat-v7:23.0.1"
    compile "com.facebook.react:react-native:+"  // From node_modules
}

Thêm đoạn code sau đây vào danh sách các phụ thuộc:

compile project(':react-native-image-picker')

Mở android/app/src/main/AndroidManifest.xml và thêm đoạn code dưới đây để cấp quyền hệ thống mặc định mà React Native cần.





Các quyền hệ thống mặc định là:



Mở android/app/src/main/java/com/facedetector/MainActivity.java và thêm câu lệnh import sau đây ở trên cùng của lớp MainActivity.

import com.imagepicker.ImagePickerPackage;

Tôi đã đề cập đến việc sử dụng rnpm trước đây. Nếu bạn vẫn chưa cài đặt nó trên máy tính của mình, thì đây là lúc tốt để làm điều đó:

npm install rnpm -g

Sau khi cài đặt, hãy chạy lệnh rnpm link để tự động liên kết các mô-đun mà bạn đã cài đặt trong settings.gradlebuild.gradleAndroidManifest.xml và MainActivity.java.

rnpm link



Nó sẽ lo mọi thứ mà chúng ta thực hiện thủ công cho react-native-image-picker. Chúng ta đã trải qua quá trình thủ công trong việc thêm một phụ thuộc, như vậy bạn biết được những gì mà rnpm thực hiện.

Bước 3: Thành phần Khởi điểm của Ứng dụng

Bây giờ chúng ta đã sẵn sàng để viết một số code. Đầu tiên, hãy mở index.android.js và thay thế nội dung của tập tin này bằng nội dung sau:

import React from 'react';
import {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View
} from 'react-native';

import Detector from './components/Detector';

const image_picker_options = {
  title: 'Select Photo', 
  takePhotoButtonTitle: 'Take Photo...', 
  chooseFromLibraryButtonTitle: 'Choose from Library...',
  cameraType: 'back', 
  mediaType: 'photo',
  maxWidth: 480,
  quality: 1, 
  noData: false, 
  path: 'images'
};

const api_key = 'YOUR FACE DETECTION API KEY';

class FaceDetector extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Detector imagePickerOptions={image_picker_options} apiKey={api_key} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  }
});

AppRegistry.registerComponent('FaceDetector', () => FaceDetector);

Những gì chúng ta có ở trên là code mẫu cho một tập tin khởi điểm của React Native. Trước tiên, chúng ta import các thành phần mà chúng ta cần.

import React from 'react';
 import {
   AppRegistry,
   Component,
   StyleSheet,
   Text,
   View
 } from 'react-native';
 import Detector from './components/Detector';

Sau đó chúng ta khai báo các tùy chọn mà thành phần Detector sẽ cần đến. Điều này bao gồm các tùy chọn cho image picker và khóa API mà bạn nhận được từ Microsoft Azure trước đó. Đừng quên nhập khóa API của bạn và gán nó cho api_key.

const image_picker_options = {
   title: 'Select Photo', 
   takePhotoButtonTitle: 'Take Photo…', 
   chooseFromLibraryButtonTitle: 'Choose from Library…',
   cameraType: 'back', //front or back camera?
   mediaType: 'photo', //the type of file that you want to pick
   maxWidth: 480, //the target width in which to resize the photo 
   quality: 1, //0 to 1 for specifying the quality of the photo
   noData: false, //if set to true it disables the base64 of the file
 };
 //the API Key that you got from Microsoft Azure
 const api_key = 'YOUR FACE Detection API KEY';

Tiếp theo, chúng ta tạo ra thành phần khởi điểm và, bên trong container chính, sử dụng thành phần Detector. Đừng quên truyền vào các thuộc tính cần thiết:

 class FaceDetector extends Component {
render() {
return (



);
}
} 

Ngoài ra chúng ta còn định nghĩa các phong cách:

 const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
}); 

Và cuối cùng, chúng ta đăng ký thành phần:

AppRegistry.registerComponent('FaceDetector', () => FaceDetector);

Bước 4: Thành phần Button

Tạo một tập tin mới trong thư mục components và đặt tên nó là Button.js. Thành phần này sẽ cho phép chúng ta dễ dàng tạo ra các nút để thực hiện một hành động cụ thể. Sau này, bạn sẽ thấy nó được sử dụng như thế nào trong thành phần Detector. Bây giờ, chỉ cần biết rằng bạn cần truyền onpressbutton_stylesbutton_text_styles và text như là các thuộc tính để tùy biến giao diện và tính năng của mỗi nút.

import React from 'react';
 
import {
  AppRegistry,
  Component,
  Text,
  View,
  TouchableHighlight
} from 'react-native';
 
export default class Button extends Component {
 
  render(){
    return (
      
        
          
              {this.props.text}
          
        
      
    );
  }
}
 
AppRegistry.registerComponent('Button', () => Button);

Bước 5: Thành phần Detector

Vẫn ở trong thư mục components, hãy tạo một tập tin mới, đặt tên là Detector.js, và thêm đoạn code sau đây vào nó. Thành phần này là nơi thực hiện những công việc chính. Hãy dành một ít thời gian để cài đặt của nó.

import React from 'react';
 
import {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View,
  Image
} from 'react-native';
 
 
import NativeModules, { ImagePickerManager } from 'NativeModules';
 
import Button from './Button';
 
import RNFetchBlob from 'react-native-fetch-blob';
 
import _ from 'lodash';
 
export default class Detector extends Component {
  constructor(props) {
      super(props);
    this.state = {
        photo_style: {
            position: 'relative',
            width: 480,
            height: 480
        },
        has_photo: false,
        photo: null,
        face_data: null
    };
  }
 
  render() {
    return (
      
         
        
            { this._renderFaceBoxes .call(this) }
        
     
        

Hãy chia nhỏ nó ra để bạn biết chính xác những gì đang xảy ra. Chúng ta bắt đầu bằng cách import các thư viện mà chúng ta cần. Code này bao gồm React và các thành phần mặc định của nó, image picker, thành phần button, thư viện react-native-fetch-blob, và lodash.

import React from 'react';
 
import {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View,
  Image
} from 'react-native';
 
 
import NativeModules, { ImagePickerManager } from 'NativeModules';
 
import Button from './Button';
 
import RNFetchBlob from 'react-native-fetch-blob';
 
import _ from 'lodash';

Bên trong khai báo lớp, chúng ta có hàm xây dựng được thực thi trước khi thành phần được gắn kết. Ở đây chúng ta thiết lập phong cách mặc định cho tấm ảnh đã chọn, giá trị boolean được sử dụng như một cơ sở để xác định nút để phát hiện khuôn mặt có được hiển thị hay không, bản thân tấm ảnh và face_data, được sử dụng như là nguồn dữ liệu để xây dựng các hộp bao quanh khuôn mặt.

import React from 'react';
 
import {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View,
  Image
} from 'react-native';
 
 
import NativeModules, { ImagePickerManager } from 'NativeModules';
 
import Button from './Button';
 
import RNFetchBlob from 'react-native-fetch-blob';
 
import _ from 'lodash';

Tiếp theo là phương thức render(), kết xuất tấm ảnh được chọn và hai cái nút, nút chọn hình ảnh và phát hiện khuôn mặt. Xin lưu ý rằng, chúng ta đang gọi ba phương thức khác ở dưới đây, _renderFaceBoxes()_pickImage() và _renderDetectedFacesButton(). Chúng ta sẽ từng bước tìm hiểu các phương thức này, còn bây giờ, chúng ta biết rằng chúng được sử dụng để đơn giản hóa việc cài đặt phương thức render().

Đồng thời lưu ý rằng chúng ta đang sử dụng call và bind thay cho việc gọi các phương thức một cách trực tiếp. Điều này là do các phương thức bên trong các lớp của ES6 không tự động ràng buộc với lớp. Điều này có nghĩa là bạn cần sử dụng bind hoặc call để ràng buộc các phương thức này với this, từ khoá chỉ đến chính bản thân lớp đó. Nếu bạn không biết sự khác nhau giữa bind và call, hãy xem câu hỏi này trên Stack Overflow về sự khác nhau giữa callapply và bind.

render() {return (<View style={styles.container}> <Imagestyle={this.state.photo_style}source={this.state.photo}resizeMode={"contain"}>{ this._renderFaceBoxes.call(this) }</Image> <Buttontext="Pick Photo"onpress={this._pickImage.bind(this)}button_styles={styles.button}button_text_styles={styles.button_text} /> { this._renderDetectFacesButton.call(this) } </View>);}

Phương thức _pickImage() được gọi khi nút chọn hình ảnh được nhấn. Việc này thiết lập face_data thành null do đó các hộp bao quanh khuôn mặt hiện tại, nếu có, sẽ bị xóa. Sau đó mở hộp thoại lựa chọn nơi để lấy một tấm ảnh từ, camera hoặc thư viện hình ảnh.

Hộp thoại này sử dụng đối tượng được truyền từ index.android.js để tùy biến các cài đặt của nó. Khi một tấm ảnh đã được chọn, một phản hồi có chứa URI cục bộ và dữ liệu base64 của ảnh, kích thước (chiều rộng và chiều cao) của nó, và các thông tin quan trọng khác về tập tin sẽ được trả về. Chúng ta sử dụng dữ liệu này để cập nhật state, sau đó cập nhật giao diện người dùng của ứng dụng.

Lưu ý rằng, trước đó chúng ta đã chỉ định một maxWidth là 480 cho các tuỳ chọn của image picker. Điều này có nghĩa là hình ảnh được chọn bị thay đổi kích thước thành chiều rộng và chiều cao đó được tinh chỉnh một cách tự động để duy trì tỷ lệ khung hình. Đây là lý do tại sao chúng ta cập nhật chiều rộng và chiều cao trong photo_style để thay đổi kích thước thành phần Image sao cho tấm hình vừa vặn với nó.

position được thiết lập thành relative để các hộp cố định bao quanh khuôn mặt ràng buộc bên trong thành phần Imagephoto được sử dụng như là nguồn cho thành phần Image và photo_data là dữ liệu base64 của của ảnh. Chúng ta cần phải đặt nó bên trong state để chúng ta có thể sử dụng nó sau này khi tạo yêu cầu đến API.

_pickImage() { this.setState({face_data: null}); ImagePickerManager.showImagePicker(this.props.imagePickerOptions, (response) => { if(response.error){alert('Error getting the image. Please try again.');}else{ let source = {uri: response.uri}; //the source of the photo to display this.setState({photo_style: {position: 'relative',width: response.width,height: response.height},has_photo: true,photo: source,photo_data: response.data}); }}); }

Phương thức _renderDetectFacesButton() chịu trách nhiệm hiển thị nút phát hiện khuôn mặt. Nó chỉ hiển thị nút nếu has_photo ở trong state được thiết lập thành true.

_renderDetectFacesButton() {if(this.state.has_photo){return  (<Buttontext="Detect Faces"onpress={this._detectFaces.bind(this)}button_styles={styles.button}button_text_styles={styles.button_text} />);}}

Khi nút phát hiện khuôn mặt được nhấn, thì phương thức _detectFaces() được thực thi. Phương thức này tạo một yêu cầu POST đến Face Detection API, truyền vào dữ liệu base64 của ảnh được chọn cùng với một số tùy chọn đóng vài trò như các tham số truy vấn.

Lưu ý rằng, chúng ta truyền vào dữ liệu base64 của tấm ảnh, nhưng tập tin blob là những gì thật sự được gửi đến máy chủ bởi vì chúng ta đang sử dụng thư viện react-native-fetch-blob. Một khi chúng ta nhận được phản hồi, chúng ta sẽ cập nhật state bằng face_data để kết xuất các hộp xung quanh khuôn mặt.

_detectFaces() { RNFetchBlob.fetch('POST', 'https://api.projectoxford.ai/face/v1.0/detect?returnFaceId=true&returnFaceAttributes=age,gender', {'Accept': 'application/json','Content-Type': 'application/octet-stream','Ocp-Apim-Subscription-Key': this.props.apiKey}, this.state.photo_data).then((res) => {return res.json();    }).then((json) => { if(json.length){this.setState({face_data: json});}else{//an empty array is returned if the API didn't detect any facesalert("Sorry, I can't see any faces in there.");} return json;}).catch (function (error) {console.log(error);alert('Sorry, the request failed. Please try again.' + JSON.stringify(error));});  }

Lưu ý rằng, trong đoạn code trên, chúng ta xử lý các trường hợp trong đó API không thể phát hiện bất kỳ khuôn mặt nào trong ảnh bằng cách cảnh báo cho người dùng. Điều này có thể xảy ra vì hai lý do:

  • Bức ảnh không có chứa bất kỳ khuôn mặt nào.
  • Các khuôn mặt trong bức ảnh không thể được nhận dạng bởi thuật toán phát hiện khuôn mặt, bởi vì chúng quá lớn hoặc quá nhỏ, góc quay quá lớn (tư thế đầu), thiếu hoặc thừa sáng, hoặc có cái gì đó đang che một phần khuôn mặt.

Phương thức _renderFaceBoxes() trả về các hộp bao quanh khuôn mặt dựa trên face_data hiện đang ở trong state. Chúng ta sử dụng hàm map() của lodash để lặp qua dữ liệu khuôn mặt. Mỗi cái hộp được cố định để mọi thứ bắt đầu ở cạnh trên bên trái của thành phần Image. Vị trí top và left và width và height của mỗi hộp dựa trên các giá trị được lưu trữ trong đối tượng faceRectangle.

_renderFaceBoxes() { if(this.state.face_data){ let views = _.map(this.state.face_data, (x) => { let box = {position: 'absolute',top: x.faceRectangle.top,left: x.faceRectangle.left}; let style = { width: x.faceRectangle.width,height: x.faceRectangle.height,borderWidth: 2,borderColor: '#fff',}; let attr = {color: '#fff',}; return (<View key={x.faceId} style={box}><View style={style}></View><Text style={attr}>{x.faceAttributes.gender}, {x.faceAttributes.age} y/o</Text></View>);}); return <View>{views}</View>} }

Trước khi đăng ký thành phần này, chúng ta thêm các phong cách.

const styles = StyleSheet.create({container: {flex: 1,alignItems: 'center',alignSelf: 'center',backgroundColor: '#ccc'},button: {margin: 10,padding: 15,backgroundColor: '#529ecc'},button_text: {color: '#FFF',fontSize: 20}});

Và cuối cùng, chúng ta đăng ký thành phần.

1AppRegistry.registerComponent('Detector', () => Detector);

3. Build và Chạy

Build và chạy ứng dụng để xem mọi thứ có hoạt động bình thường hay không. Đừng quên nhập khóa API mà bạn đã lấy được từ Microsoft Azure Portal. Với một khoá API không hợp lệ, ứng dụng sẽ không thể phát hiện bất kỳ khuôn mặt nào.

Phần Tóm tắt

Chỉ vậy thôi! Trong hướng dẫn này, bạn đã học được cách tạo một ứng dụng phát hiện khuôn mặt bằng Face Detection API của Microsoft. Trong quá trình đó, bạn cũng đã học được cách thêm một dịch vụ Microsoft Azure và tạo một yêu cầu đến Face Detection API.

Nếu bạn muốn tìm hiểu thêm về Face Detection API, hãy xem tài liệu hướng dẫn chính thức và Cognitive Services API Reference.

Post Comment