1. Code
  2. Mobile Development
  3. React Native Development

Cara Membuat Aplikasi Deteksi Wajah Dengan React Native

Apakah anda pengembang aplikasi hybrid yang ingin menyertakan deteksi wajah ke dalam aplikasi anda, tetapi anda tidak tahu harus mulai dari mana? Sebagai permulaan, anda dapat membaca An Introduction to Face Detection on Android, yang menunjukkan cara menerapkan deteksi wajah di Android.  Tetapi jika anda seperti saya dan anda tidak ingin menulis kode Java untuk membuat modul React Native yang melakukan ini untuk anda, maka anda berada di tempat yang tepat.
Scroll to top

Indonesian (Bahasa Indonesia) translation by AaliyaA (you can also view the original English article)

Apakah anda pengembang aplikasi hybrid yang ingin menyertakan deteksi wajah ke dalam aplikasi anda, tetapi anda tidak tahu harus mulai dari mana? Sebagai permulaan, anda dapat membaca An Introduction to Face Detection on Android, yang menunjukkan cara menerapkan deteksi wajah di Android.  Tetapi jika anda seperti saya dan anda tidak ingin menulis kode Java untuk membuat modul React Native yang melakukan ini untuk anda, maka anda berada di tempat yang tepat. 

Dalam tutorial ini, kita melihat Face Detection API, yang merupakan bagian dari Microsoft Cognitive Services.  API ini memungkinkan developer untuk dengan mudah menerapkan fungsi pendeteksian wajah di aplikasi. Dalam tutorial ini, saya akan menganggap bahwa ini bukan aplikasi Native React pertama anda. Jika anda baru dalam React Native, maka saya sarankan anda terlebih dahulu membaca tutorial Memulai Facebook di situs web React Native. Tutorial itu menunjukkan cara mengatur lingkungan anda dan membuat proyek Native React pertama anda. 

Prasyarat

Meskipun kami fokus pada platform Android dalam tutorial ini, dengan sedikit usaha, anda dapat menambahkan dukungan untuk platform lain. Pastikan anda memasang Android Studio. Anda dapat mengunduh Android Studio dari portal pengembang Google.

1. Apa itu API Deteksi Wajah?

Sebelum kita mulai menulis aplikasi kita, saya ingin sejenak berbicara tentang API yang akan kita gunakan untuk deteksi wajah. Microsoft face detection API menyediakan deteksi wajah dan fungsi pengenalan wajah melalui API berbasis cloud.  Ini memungkinkan kita mengirim permintaan HTTP yang berisi gambar atau URL dari gambar yang ada di web, dan menerima data tentang setiap wajah yang terdeteksi dalam gambar. 

Mengirim Permintaan ke API

Anda dapat mengajukan permintaan ke API deteksi wajah Microsoft dengan mengirimkan permintaan POST ke https://api.projectoxford.ai/face/v1.0/detect. Permintaan harus berisi informasi tajuk berikut:

  • Content-Type: Field header ini berisi tipe data dari body request. Jika anda mengirim URL gambar di web, maka nilai bidang header ini harus berupa aplikasi / json. Jika anda mengirim gambar, setel bidang header ke application/octet.-streaming.
  • Ocp-Apim-Subscription-Key: Kolom header ini berisi kunci API yang digunakan untuk mengautentikasi permintaan anda.  Saya akan menunjukkan kepada anda cara mendapatkan kunci API nanti di tutorial ini.

Secara default, API hanya mengembalikan data tentang kotak yang digunakan untuk melampirkan wajah yang terdeteksi dalam gambar. Dalam sisa tutorial ini, saya akan merujuk boxes ini sebagai face boxes. Opsi ini dapat dinonaktifkan dengan menyetel parameter query returnFaceRectangle ke false. Nilai default adalah true, yang berarti anda tidak harus menentukannya kecuali anda ingin menonaktifkan opsi ini.

Anda dapat menyediakan beberapa parameter query opsional lain untuk mengambil informasi tambahan tentang wajah yang terdeteksi:

  • returnFaceId: Jika diatur ke true, opsi ini menetapkan pengenal unik untuk setiap wajah yang terdeteksi.
  • returnFaceLandmarks: Dengan mengaktifkan opsi ini, API mengembalikan array penanda wajah wajah yang terdeteksi, termasuk mata, hidung, dan bibir. Pilihan ini dinonaktifkan secara default.
  • returnFaceAttributes: Jika opsi ini diaktifkan, API mencari dan mengembalikan atribut unik untuk setiap wajah yang terdeteksi. Anda perlu menyediakan daftar atribut yang dipisahkan koma yang Anda minati, seperti usia, jenis kelamin, senyum, rambut wajah, pose kepala, dan kacamata.

Di bawah ini adalah contoh tanggapan yang Anda dapatkan dari API yang diberikan URL permintaan berikut:

1
https://api.projectoxford.ai/face/v1.0/detect?faceId=true&faceLandmarks=true&faceAttributes=age,gender,smile,facialHair,headPose,glasses
1
[
2
    {
3
        "faceId": "c5c24a82-6845-4031-9d5d-978df9175426",
4
        "faceRectangle": {
5
            "width": 78,
6
            "height": 78,
7
            "left": 394,
8
            "top": 54
9
        },
10
        "faceLandmarks": {
11
            "pupilLeft": {
12
                "x": 412.7,
13
                "y": 78.4
14
            },
15
            "pupilRight": {
16
                "x": 446.8,
17
                "y": 74.2
18
            },
19
            "noseTip": {
20
                "x": 437.7,
21
                "y": 92.4
22
            },
23
            "mouthLeft": {
24
                "x": 417.8,
25
                "y": 114.4
26
            },
27
            "mouthRight": {
28
                "x": 451.3,
29
                "y": 109.3
30
            },
31
            "eyebrowLeftOuter": {
32
                "x": 397.9,
33
                "y": 78.5
34
            },
35
            "eyebrowLeftInner": {
36
                "x": 425.4,
37
                "y": 70.5
38
            },
39
            "eyeLeftOuter": {
40
                "x": 406.7,
41
                "y": 80.6
42
            },
43
            "eyeLeftTop": {
44
                "x": 412.2,
45
                "y": 76.2
46
            },
47
            "eyeLeftBottom": {
48
                "x": 413.0,
49
                "y": 80.1
50
            },
51
            "eyeLeftInner": {
52
                "x": 418.9,
53
                "y": 78.0
54
            },
55
            "eyebrowRightInner": {
56
                "x": 4.8,
57
                "y": 69.7
58
            },
59
            "eyebrowRightOuter": {
60
                "x": 5.5,
61
                "y": 68.5
62
            },
63
            "eyeRightInner": {
64
                "x": 441.5,
65
                "y": 75.0
66
            },
67
            "eyeRightTop": {
68
                "x": 446.4,
69
                "y": 71.7
70
            },
71
            "eyeRightBottom": {
72
                "x": 447.0,
73
                "y": 75.3
74
            },
75
            "eyeRightOuter": {
76
                "x": 451.7,
77
                "y": 73.4
78
            },
79
            "noseRootLeft": {
80
                "x": 428.0,
81
                "y": 77.1
82
            },
83
            "noseRootRight": {
84
                "x": 435.8,
85
                "y": 75.6
86
            },
87
            "noseLeftAlarTop": {
88
                "x": 428.3,
89
                "y": 89.7
90
            },
91
            "noseRightAlarTop": {
92
                "x": 442.2,
93
                "y": 87.0
94
            },
95
            "noseLeftAlarOutTip": {
96
                "x": 424.3,
97
                "y": 96.4
98
            },
99
            "noseRightAlarOutTip": {
100
                "x": 446.6,
101
                "y": 92.5
102
            },
103
            "upperLipTop": {
104
                "x": 437.6,
105
                "y": 105.9
106
            },
107
            "upperLipBottom": {
108
                "x": 437.6,
109
                "y": 108.2
110
            },
111
            "underLipTop": {
112
                "x": 436.8,
113
                "y": 111.4
114
            },
115
            "underLipBottom": {
116
                "x": 437.3,
117
                "y": 114.5
118
            }
119
        },
120
        "faceAttributes": {
121
            "age": 71.0,
122
            "gender": "male",
123
            "smile": 0.88,
124
            "facialHair": {
125
                "mustache": 0.8,
126
                "beard": 0.1,
127
                "sideburns": 0.02
128
            }
129
        },
130
        "glasses": "sunglasses",
131
        "headPose": {
132
            "roll": 2.1,
133
            "yaw": 3,
134
            "pitch": 0
135
        }
136
    }
137
]

Tanggapan sampel ini cukup jelas jadi saya tidak akan mendalami lebih dalam tentang setiap attribut. Data dapat digunakan untuk menampilkan wajah yang terdeteksi, atributnya yang berbeda, dan bagaimana Anda dapat menunjukkannya kepada pengguna. Ini dicapai dengan menafsirkan koordinat x dan y atau posisi atas dan kiri.

Memperoleh Kunci API

Untuk menggunakan API deteksi wajah Microsoft, setiap permintaan harus diautentikasi dengan kunci API. Berikut adalah langkah-langkah yang perlu Anda ambil untuk mendapatkan kunci semacam itu.

Membuat akun Microsoft Live jika Anda belum memilikinya. Masuk dengan akun Microsoft Live Anda dan daftar untuk Microsoft Azure Account. Jika Anda belum memiliki akun Microsoft Azure, Anda dapat mendaftar untuk free trial, memberi Anda akses ke layanan Microsoft selama 30 hari.

Untuk API deteksi wajah, ini memungkinkan Anda mengirim hingga dua puluh panggilan API per menit secara gratis. Jika Anda sudah memiliki akun Azure, maka Anda dapat berlangganan paket Pay-As-You-Go sehingga Anda hanya membayar untuk apa yang Anda gunakan. 

Setelah akun Microsoft Azure Anda diatur, Anda akan diarahkan ke Portal Microsoft Azure.  Di portal, arahkan ke bilah pencarian dan masukkan cognitive services di bidang pencarian.  Klik hasil yang mengatakan Cognitive Services accounts (preview). Anda harus melihat interface yang serupa dengan yang berikut: 

Cognitive Services AccountsCognitive Services AccountsCognitive Services Accounts

Klik tombol Add dan isi formulir yang terlihat: 

  • Account Name: Masukkan nama yang ingin Anda berikan ke resource. 
  • API Type: Pilih API deteksi wajah. 
  • Pricing Tier: Untuk tujuan pengujian, pilih tier gratis (hingga 20 panggilan API per menit). Jika Anda ingin menggunakan layanan dalam produksi, pilih opsi lain yang sesuai dengan kebutuhan aplikasi Anda.
  • Subscription: Pilih uji coba gratis jika Anda menggunakan akun Microsoft Azure baru.  Jika tidak, pilih opsi Pay-As-You-Go.
  • Resource Group: Pilih yang sudah ada jika Anda sudah memilikinya.  Jika tidak, buat grup sumber daya baru dengan memilih opsi baru dan masukkan nama untuk grup sumber daya. 
  • Location: Pilih West US.

Pada langkah berikutnya, Anda harus menyetujui syarat dan ketentuan Microsoft untuk melanjutkan.  Klik tombol Create dan tunggu sumber daya untuk menyelesaikan penerapan.

Setelah penerapan selesai, klik tautan All resources di bilah sisi kiri untuk melihat sumber daya yang Anda miliki saat ini.  Yang baru saja Anda buat harus terdaftar di sana. Jika tidak, coba refresh halaman.

Klik resource yang Anda buat dan klik ikon kunci untuk melihat kunci API yang terkait dengan sumber daya. Secara default, dua kunci dibuat dan Anda dapat menggunakan salah satu dari itu. 

Cognitive Services ResourceCognitive Services ResourceCognitive Services Resource

2. Membangun Aplikasi

Sebelum kita mulai membuat aplikasi, izinkan saya memberi Anda gambaran singkat tentang apa sebenarnya aplikasi tersebut. Seperti yang saya sebutkan sebelumnya, kita akan membangun aplikasi deteksi wajah.  Aplikasi ini akan memiliki dua tombol, satu untuk memilih gambar dan satu untuk mendeteksi wajah.  Tombol untuk memilih gambar akan meminta pengguna untuk memilih sumber, kamera perangkat atau galeri. 

Jika kamera dipilih, aplikasi kamera default akan diluncurkan.  Jika galeri dipilih, aplikasi akan membiarkan pengguna memilih foto dari galeri.  Setelah foto dipilih, tombol untuk mendeteksi wajah menjadi terlihat.  Mengetuk tombol ini akan mengirim permintaan ke API deteksi wajah Microsoft, yang mengembalikan data untuk wajah yang terdeteksi. Dengan menggunakan respons API, kotak kecil ditarik di sekitar wajah yang terdeteksi, termasuk label untuk jenis kelamin dan usia orang tersebut.

Ini adalah apa yang akan terlihat seperti aplikasi: 

Face Detection App ScreenshotFace Detection App ScreenshotFace Detection App Screenshot

Langkah 1: Memasang Dependensi

Sekarang kita siap untuk membangun aplikasi. Mari kita mulai dengan menginstal dependensi. Membuka jendela terminal baru di direktori kerja Anda dan eksekusi perintah berikut:

1
react native init FaceDetector

Ini menciptakan proyek React Native baru untuk kita, yang pada saat penulisan, berada pada versi 0.25.  Ketika proses setup selesai, navigasikan ke folder proyek.

Selanjutnya, kita Instal tiga library yang kita akan gunakan untuk mengembangkan aplikasi:

1
npm install lodash react-native-fetch-blob react-native-image-picker --save
  • lodash: Kami hanya menggunakan lodash untuk metode map.  Kita menggunakan metode ini untuk mengonversi hasil yang kita dapatkan dari API menjadi komponen yang akan kita render. 
  • react-native-image-picker: Library ini digunakan untuk menambahkan kemampuan untuk memilih gambar menggunakan kamera atau gambar dari galeri. 
  • react-native-fetch-blob: Library ini digunakan untuk mengirim permintaan jaringan yang memiliki konten gumpalan.  API deteksi wajah secara khusus membutuhkan gumpalan foto, tetapi API fetch tidak mendukungnya di luar box, itulah sebabnya kita menggunakan pustaka ini untuk menanganinya bagi kita. 

Langkah 2: Konfigurasi Proyek

Karena tidak semua React Native modules mendukung React Native Package Manager, kita perlu mengkonfigurasi proyek secara manual sehingga modul akan bekerja tanpa masalah.  Khususnya, kita perlu mengonfigurasi proyek agar react-native-image-picker untuk berfungsi dengan benar. 

Di dalam direktori kerja Anda, buka file android/settings.gradle dan tambahkan cuplikan berikut segera setelah include ': app'

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

Buka file android/app/build.gradle dan temukan bagian dependencies. Seharusnya terlihat seperti ini:

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

5
}

Tambahkan cuplikan berikut ke daftar dependensi: 

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

Buka android/app/src/main/AndroidManifest.xml dan tambahkan cuplikan berikut di bawah perizinan sistem default yang dibutuhkan oleh React Native.

1
<uses-permission android:name="android.permission.CAMERA" />
2
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3
<uses-feature android:name="android.hardware.camera" android:required="false"/>
4
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>

Untuk referensi, izin sistem default adalah:

1
<uses-permission android:name="android.permission.INTERNET" />
2
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

Buka android/app/src/main/java/com/facedetector/MainActivity.java dan tambahkan pernyataan impor berikut di bagian atas kelas MainActivity.

1
import com.imagepicker.ImagePickerPackage;

Saya telah menyebutkan penggunaan rnpm sebelumnya. Jika Anda belum menginstalnya di komputer Anda, sekarang adalah saat yang tepat untuk melakukannya:

1
npm install rnpm -g

Setelah terinstal, jalankan perintah rnpm link untuk secara otomatis menghubungkan modul yang telah Anda instal di settings.gradle, build.gradle, AndroidManifest.xml, dan MainActivity.java.

1
rnpm link

Ini mengurus semua yang kita lakukan secara manual untuk react-native-image-picker. Kita telah melalui proses manual menambahkan depdensi sehingga Anda tahu apa yang rnpm lakukan di bawah tenda.

Langkah 3: Komponen Titik Masuk Aplikasi

Sekarang kita siap untuk menulis beberapa kode. Pertama, buka index.android.js dan ganti konten file ini dengan yang berikut:

1
import React from 'react';
2
3
import {
4
  AppRegistry,
5
  Component,
6
  StyleSheet,
7
  Text,
8
  View
9
} from 'react-native';
10
11
import Detector from './components/Detector';
12
13
const image_picker_options = {
14
  title: 'Select Photo', 
15
  takePhotoButtonTitle: 'Take Photo...', 
16
  chooseFromLibraryButtonTitle: 'Choose from Library...',
17
  cameraType: 'back', 
18
  mediaType: 'photo',
19
  maxWidth: 480,
20
  quality: 1, 
21
  noData: false, 
22
  path: 'images'
23
};
24
25
const api_key = 'YOUR FACE DETECTION API KEY';
26
27
class FaceDetector extends Component {
28
  render() {
29
    return (
30
      <View style={styles.container}>
31
        <Detector imagePickerOptions={image_picker_options} apiKey={api_key} />

32
      </View>

33
    );
34
  }
35
}
36
37
const styles = StyleSheet.create({
38
  container: {
39
    flex: 1,
40
    justifyContent: 'center',
41
    alignItems: 'center',
42
    backgroundColor: '#F5FCFF',
43
  }
44
});
45
46
AppRegistry.registerComponent('FaceDetector', () => FaceDetector);

Apa yang kita miliki di atas adalah kode boilerplate untuk file titik entri React Native.  Pertama, kita mengimpor komponen yang kita butuhkan.

1
import React from 'react';
2
3
import {
4
  AppRegistry,
5
  Component,
6
  StyleSheet,
7
  Text,
8
  View
9
} from 'react-native';
10
11
import Detector from './components/Detector';

Kita kemudian menyatakan opsi yang akan dibutuhkan komponen Detector. Ini termasuk opsi untuk pemilih gambar dan kunci API yang Anda dapatkan dari Microsoft Azure sebelumnya.  Jangan lupa untuk memasukkan kunci API Anda dan menetapkannya ke api_key.

1
const image_picker_options = {
2
  title: 'Select Photo', 
3
  takePhotoButtonTitle: 'Take Photo...', 
4
  chooseFromLibraryButtonTitle: 'Choose from Library...',
5
  cameraType: 'back', //front or back camera?

6
  mediaType: 'photo', //the type of file that you want to pick

7
  maxWidth: 480, //the target width in which to resize the photo 

8
  quality: 1, //0 to 1 for specifying the quality of the photo

9
  noData: false, //if set to true it disables the base64 of the file

10
};
11
12
//the API Key that you got from Microsoft Azure

13
const api_key = 'YOUR FACE Detection API KEY'; 

Selanjutnya, kita buat komponen titik masuk dan, di dalam container utama, gunakan komponen Detector.  Jangan lupa untuk meneruskan properti yang diperlukan: 

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

6
      </View>

7
    );
8
  }
9
}

Kita juga mendefinisikan gaya:

1
const styles = StyleSheet.create({
2
  container: {
3
    flex: 1,
4
    justifyContent: 'center',
5
    alignItems: 'center',
6
    backgroundColor: '#F5FCFF',
7
  }
8
});

Dan akhirnya, kita mendaftarkan komponen:

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

Langkah 4: Komponen Tombol

Buat sebuah file baru di direktori komponen dan beri nama Button.js. Komponen ini akan memungkinkan kita untuk dengan mudah membuat tombol yang melakukan tindakan tertentu.  Nanti, Anda akan melihat bagaimana ini digunakan dalam komponen Detector.  Untuk saat ini, ketahuilah bahwa Anda harus meneruskan onpressbutton_stylesbutton_text_styles, dan text sebagai properti untuk menyesuaikan tampilan dan fungsi setiap tombol.

1
import React from 'react';
2
3
import {
4
  AppRegistry,
5
  Component,
6
  Text,
7
  View,
8
  TouchableHighlight
9
} from 'react-native';
10
11
export default class Button extends Component {
12
13
  render(){
14
    return (
15
      <View>
16
        <TouchableHighlight underlayColor={"#E8E8E8"} onPress={this.props.onpress} style={this.props.button_styles}>
17
          <View>
18
              <Text style={this.props.button_text_styles}>{this.props.text}</Text>

19
          </View>

20
        </TouchableHighlight>

21
      </View>

22
    );
23
  }
24
}
25
26
AppRegistry.registerComponent('Button', () => Button);

Langkah 5:Komponen Detektor 

Masih di dalam direktori komponen, buat file baru, beri nama Detector.js, dan tambahkan kode berikut ke dalamnya.  Komponen ini adalah tempat keajaiban terjadi. Luangkan waktu sejenak untuk menelusuri implementasi.

1
import React from 'react';
2
3
import {
4
  AppRegistry,
5
  Component,
6
  StyleSheet,
7
  Text,
8
  View,
9
  Image
10
} from 'react-native';
11
12
13
import NativeModules, { ImagePickerManager } from 'NativeModules';
14
15
import Button from './Button';
16
17
import RNFetchBlob from 'react-native-fetch-blob';
18
19
import _ from 'lodash';
20
21
export default class Detector extends Component {
22
  constructor(props) {
23
      super(props);
24
    this.state = {
25
  		photo_style: {
26
  			position: 'relative',
27
  			width: 480,
28
  			height: 480
29
  		},
30
  		has_photo: false,
31
  		photo: null,
32
  		face_data: null
33
  	};
34
  }
35
36
  render() {
37
    return (
38
      <View style={styles.container}>
39
		
40
		<Image
41
        	style={this.state.photo_style}
42
        	source={this.state.photo}
43
        	resizeMode={"contain"}
44
      	>
45
			{ this._renderFaceBoxes .call(this) }
46
      	</Image>

47
	
48
		<Button
49
            text="Pick Photo"
50
            onpress={this._pickImage.bind(this)}
51
            button_styles={styles.button}
52
            button_text_styles={styles.button_text} />

53
54
        { this._renderDetectFacesButton.call(this) }
55
56
      </View>

57
    );
58
  }
59
60
61
  _pickImage() {
62
  	
63
	this.setState({
64
		face_data: null
65
	});
66
67
	ImagePickerManager.showImagePicker(this.props.imagePickerOptions, (response) => {
68
	 	
69
	  if(response.error){
70
	  	alert('Error getting the image. Please try again.');
71
	  }else{
72
	  	
73
	    let source = {uri: response.uri};
74
75
	    this.setState({
76
	      photo_style: {
77
			position: 'relative',
78
			width: response.width,
79
			height: response.height
80
	      },
81
	      has_photo: true,
82
	      photo: source,
83
	      photo_data: response.data
84
	    });
85
	    
86
	  }
87
	});
88
89
  }
90
91
  _renderDetectFacesButton() {
92
  	if(this.state.has_photo){
93
	  	return  (
94
			<Button
95
	            text="Detect Faces"
96
	            onpress={this._detectFaces.bind(this)}
97
	            button_styles={styles.button}
98
	            button_text_styles={styles.button_text} />

99
	  	);
100
  	}
101
  }
102
103
  _detectFaces() {
104
105
	RNFetchBlob.fetch('POST', 'https://api.projectoxford.ai/face/v1.0/detect?returnFaceId=true&returnFaceAttributes=age,gender', {
106
		'Accept': 'application/json',
107
	    'Content-Type': 'application/octet-stream',
108
	    'Ocp-Apim-Subscription-Key': this.props.apiKey
109
	}, this.state.photo_data)
110
	.then((res) => {
111
		return res.json();		
112
	})
113
	.then((json) => {
114
		
115
		if(json.length){
116
			this.setState({
117
				face_data: json
118
			});
119
		}else{
120
			alert("Sorry, I can't see any faces in there.");
121
		}
122
		
123
		return json;
124
	})
125
	.catch (function (error) {
126
		console.log(error);
127
    	alert('Sorry, the request failed. Please try again.' + JSON.stringify(error));
128
	});
129
	
130
131
  }
132
133
  _renderFaceBoxes () {
134
135
  	if(this.state.face_data){
136
137
	  	let views = _.map(this.state.face_data, (x) => {
138
	  		
139
	  		let box = {
140
	  			position: 'absolute',
141
	  			top: x.faceRectangle.top,
142
				left: x.faceRectangle.left
143
	  		};
144
145
			let style = { 
146
				width: x.faceRectangle.width,
147
				height: x.faceRectangle.height,
148
				borderWidth: 2,
149
				borderColor: '#fff',
150
			};
151
			
152
			let attr = {
153
				color: '#fff',
154
			};
155
156
		  	return (
157
		  		<View key={x.faceId} style={box}>
158
					<View style={style}></View>

159
					<Text style={attr}>{x.faceAttributes.gender}, {x.faceAttributes.age} y/o</Text>

160
		  		</View>

161
		  	);
162
	  	});
163
164
	  	return <View>{views}</View>

165
  	}
166
167
  }
168
  
169
}
170
171
const styles = StyleSheet.create({
172
  container: {
173
    flex: 1,
174
   	alignItems: 'center',
175
   	alignSelf: 'center',
176
    backgroundColor: '#ccc'
177
  },
178
  button: {
179
	margin: 10,
180
	padding: 15,
181
	backgroundColor: '#529ecc'
182
  },
183
  button_text: {
184
  	color: '#FFF',
185
    fontSize: 20
186
  }
187
});
188
189
AppRegistry.registerComponent('Detector', () => Detector);

Mari kita hancurkan sehingga Anda tahu persis apa yang sedang terjadi. Kita mulai dengan mengimpor library yang kita butuhkan.  Ini termasuk React dan komponen bawaannya, image picker, komponen tombol, library react-native-fetch-blob , dan lodash.

1
import React from 'react';
2
3
import {
4
  AppRegistry,
5
  Component,
6
  StyleSheet,
7
  Text,
8
  View,
9
  Image
10
} from 'react-native';
11
12
13
import NativeModules, { ImagePickerManager } from 'NativeModules';
14
15
import Button from './Button';
16
17
import RNFetchBlob from 'react-native-fetch-blob';
18
19
import _ from 'lodash';

Di dalam deklarasi class, kita memiliki konstruktor yang dijalankan sebelum komponen dipasang.  Di sini kita mengatur styling default untuk foto yang dipilih, nilai boolean yang digunakan sebagai dasar apakah akan menampilkan tombol untuk mendeteksi wajah atau tidak, foto itu sendiri, dan face_data, yang digunakan sebagai sumber data untuk membuat kotak wajah . 

1
export default class Detector extends Component {
2
  constructor(props) {
3
    super(props);
4
    this.state = {
5
  		photo_style: {
6
  			position: 'relative',
7
  			width: 480,
8
  			height: 480
9
  		},
10
  		has_photo: false,
11
  		photo: null,
12
  		face_data: null
13
  	};
14
  }
15
  
16
  ...
17
}

Berikutnya adalah render() method, yang membuat foto yang dipilih dan dua tombol, pilih gambar dan mendeteksi wajah.  Perhatikan bahwa kita memanggil tiga method lain di bawah ini, _renderFaceBoxes(), _pickImage(), dan _renderDetectedFacesButton(). Kita akan berjalan melalui metode ini segera, tetapi untuk sekarang tahu bahwa mereka digunakan untuk menyederhanakan penerapan metode render().

Juga perhatikan bahwa kita menggunakan call dan bind daripada memanggil metode secara langsung.  Ini karena method di dalam kelas ES6 tidak terikat secara otomatis ke kelas.  Ini berarti Anda harus menggunakan bind atau call untuk mengikat method ke this, yang mengacu pada class itu sendiri. Jika Anda tidak tahu perbedaan antara bind and call, periksa Stack Overflow question tentang perbedaan antara call, apply, dan bind.

1
render() {
2
  return (
3
    <View style={styles.container}>
4
  
5
      	<Image
6
	        style={this.state.photo_style}
7
	        source={this.state.photo}
8
	        resizeMode={"contain"}
9
	      >
10
	    { this._renderFaceBoxes.call(this) }
11
	    </Image>

12
13
  		<Button
14
          text="Pick Photo"
15
          onpress={this._pickImage.bind(this)}
16
          button_styles={styles.button}
17
          button_text_styles={styles.button_text} />

18
19
      	{ this._renderDetectFacesButton.call(this) }
20
21
    </View>

22
  );
23
}

Method _pickImage() dipanggil ketika tombol untuk memilih gambar ditekan.  Ini menetapkan face_data ke null sehingga kotak wajah yang sudah ada, dihapus. Kemudian membuka dialog untuk memilih tempat untuk mendapatkan foto dari, kamera atau galeri. 

Dialog menggunakan objek yang dilewatkan dari index.android.js untuk menyesuaikan pengaturannya.  Setelah foto diambil, respons yang berisi lokal URI dan base64 terrepresentasi dari fotonya, dimensinya (lebar dan tinggi), dan informasi penting lainnya tentang file dikembalikan.  Kita menggunakan data ini untuk memperbarui keadaan, yang memperbarui antarmuka pengguna aplikasi. 

Perhatikan bahwa sebelumnya kita menetapkan maxWidth jadi 480 untuk opsi pemetik gambar.  Ini berarti bahwa gambar yang dipilih diubah ukurannya ke lebar dan tingginya secara otomatis disesuaikan untuk mempertahankan aspek rasio. Inilah sebabnya mengapa kita memperbarui lebar dan tinggi di photo_style untuk mengubah ukuran dari komponen Image sehingga foto sangat cocok. 

position diatur ke relative sehingga kotak wajah yang benar-benar diposisikan terhambat di dalam komponen Imagephoto digunakan sebagai sumber untuk komponen Image dan photo_data adalah representasi base64 foto. Kita perlu memasukkannya ke dalam keadaan sehingga kita bisa menggunakannya nanti ketika membuat permintaan ke API. 

1
_pickImage() {
2
  
3
  this.setState({
4
    face_data: null
5
  });
6
7
  ImagePickerManager.showImagePicker(this.props.imagePickerOptions, (response) => {
8
    
9
    if(response.error){
10
      alert('Error getting the image. Please try again.');
11
    }else{
12
      
13
      let source = {uri: response.uri}; //the source of the photo to display

14
15
      this.setState({
16
        photo_style: {
17
          	position: 'relative',
18
      		width: response.width,
19
      		height: response.height
20
        },
21
        has_photo: true,
22
        photo: source,
23
        photo_data: response.data
24
      });
25
      
26
    }
27
  });
28
29
}

Metode _renderDetectFacesButton() bertanggung jawab untuk menampilkan tombol untuk mendeteksi wajah. Hanya menampilkan tombol jika has_photo di state diatur ke true

1
_renderDetectFacesButton() {
2
  if(this.state.has_photo){
3
    return  (
4
    <Button
5
            text="Detect Faces"
6
            onpress={this._detectFaces.bind(this)}
7
            button_styles={styles.button}
8
            button_text_styles={styles.button_text} />

9
    );
10
  }
11
}

Ketika tombol deteksi wajah ditekan, method _detectFaces() dijalankan. Metode ini membuat permintaan POST ke Face Detection API, meneruskan representasi base64 dari foto yang dipilih bersama dengan beberapa opsi sebagai parameter query.

Perhatikan bahwa kita menyampaikan representasi base64 foto, tetapi file blob adalah apa yang sebenarnya dikirim ke server karena kita menggunakan library react-native-fetch-blob. Setelah kita mendapatkan balasan, kita memperbarui state dengan face_data untuk merender kotak wajah. 

1
_detectFaces() {
2
3
  RNFetchBlob.fetch('POST', 'https://api.projectoxford.ai/face/v1.0/detect?returnFaceId=true&returnFaceAttributes=age,gender', {
4
      'Accept': 'application/json',
5
      'Content-Type': 'application/octet-stream',
6
      'Ocp-Apim-Subscription-Key': this.props.apiKey
7
  }, this.state.photo_data)
8
  .then((res) => {
9
    return res.json();    
10
  })
11
  .then((json) => {
12
    
13
    if(json.length){
14
      this.setState({
15
        face_data: json
16
      });
17
    }else{
18
      //an empty array is returned if the API didn't detect any faces

19
      alert("Sorry, I can't see any faces in there.");
20
    }
21
    
22
    return json;
23
  })
24
  .catch (function (error) {
25
    console.log(error);
26
      alert('Sorry, the request failed. Please try again.' + JSON.stringify(error));
27
  });
28
29
30
}

Perhatikan bahwa, dalam kode di atas, kita menangani kasus di mana API tidak dapat mendeteksi wajah apa pun di foto dengan memperingatkan pengguna.  Ini bisa terjadi karena dua alasan:

  • Foto tidak berisi wajah apapun.
  • Wajah-wajah dalam foto tidak dapat dikenali oleh algoritma deteksi wajah, karena mereka terlalu besar atau terlalu kecil, sudut wajah besar (pose kepala), pencahayaan tidak cukup atau terlalu banyak, atau sesuatu yang menghalangi sebagian dari wajah.

Metode _renderFaceBoxes() mengembalikan kotak wajah berdasarkan pada face_data yang saat ini dalam state.  Kita menggunakan fungsi lodash map() untuk mengulang melalui data wajah.  Setiap kotak benar-benar diposisikan sehingga semuanya dimulai di tepi kiri atas komponen Image.  Posisi top dan left serta width dan height masing-masing box didasarkan pada nilai yang disimpan dalam objek faceRectangle.

1
_renderFaceBoxes() {
2
3
  if(this.state.face_data){
4
5
    let views = _.map(this.state.face_data, (x) => {
6
      
7
      let box = {
8
        position: 'absolute',
9
        top: x.faceRectangle.top,
10
          left: x.faceRectangle.left
11
      };
12
13
      let style = { 
14
        width: x.faceRectangle.width,
15
        height: x.faceRectangle.height,
16
        borderWidth: 2,
17
        borderColor: '#fff',
18
      };
19
    
20
      let attr = {
21
        color: '#fff',
22
      };
23
24
      return (
25
        <View key={x.faceId} style={box}>
26
        	<View style={style}></View>

27
        	<Text style={attr}>{x.faceAttributes.gender}, {x.faceAttributes.age} y/o</Text>

28
        </View>

29
      );
30
    });
31
32
    return <View>{views}</View>

33
  }
34
35
}

Sebelum kita mendaftarkan komponen, kita menambahkan gaya. 

1
const styles = StyleSheet.create({
2
  container: {
3
    flex: 1,
4
    alignItems: 'center',
5
    alignSelf: 'center',
6
    backgroundColor: '#ccc'
7
  },
8
  button: {
9
  margin: 10,
10
  padding: 15,
11
  backgroundColor: '#529ecc'
12
  },
13
  button_text: {
14
    color: '#FFF',
15
    fontSize: 20
16
  }
17
});

Dan akhirnya, kita mendaftar komponen.

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

3. Build dan Run

Build dan run aplikasi untuk melihat apakah semuanya berfungsi dengan benar.  Jangan lupa untuk memasukkan kunci API yang Anda peroleh dari Microsoft Azure Portal. Dengan kunci API yang valid, aplikasi tidak akan dapat mendeteksi wajah apa pun. 

Kesimpulan

Itu dia. Dalam tutorial ini, Anda belajar cara membuat aplikasi deteksi wajah menggunakan API deteksi wajah Microsoft. Saat melakukannya, Anda belajar cara menambahkan layanan ke Microsoft Azure dan membuat permintaan ke API deteksi wajah.

Jika Anda ingin mempelajari lebih lanjut tentang API deteksi wajah, periksa dokumentasi resminya dan Referensi API Layanan Kognitif.