Get started with FacePing's face recognition API using Flutter
Create a new Flutter project and add required dependencies:
flutter create faceping_demo
cd faceping_demo
Update pubspec.yaml
:
dependencies:
flutter:
sdk: flutter
http: ^1.2.0
image_picker: ^1.0.7
Create lib/create_group.dart
:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class CreateGroupWidget extends StatefulWidget {
const CreateGroupWidget({super.key});
@override
State<CreateGroupWidget> createState() => _CreateGroupWidgetState();
}
class _CreateGroupWidgetState extends State<CreateGroupWidget> {
final _groupNameController = TextEditingController();
String _status = '';
Future<void> _createGroup() async {
try {
final response = await http.post(
Uri.parse('https://api.faceping.ai/groups/${_groupNameController.text}'),
headers: {'Authorization': 'Bearer your_api_key_here'},
);
setState(() {
_status = response.statusCode == 200
? 'Group created successfully'
: 'Failed to create group';
});
} catch (e) {
setState(() {
_status = 'Error creating group';
});
}
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
controller: _groupNameController,
decoration: const InputDecoration(
labelText: 'Enter group name',
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _createGroup,
child: const Text('Create Group'),
),
if (_status.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text(_status),
),
],
);
}
}
Create lib/upload_face.dart
:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'dart:io';
class UploadFaceWidget extends StatefulWidget {
const UploadFaceWidget({super.key});
@override
State<UploadFaceWidget> createState() => _UploadFaceWidgetState();
}
class _UploadFaceWidgetState extends State<UploadFaceWidget> {
File? _image;
String _status = '';
final _picker = ImagePicker();
Future<void> _pickImage() async {
final pickedFile = await _picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
setState(() {
_image = File(pickedFile.path);
});
await _uploadFace();
}
}
Future<void> _uploadFace() async {
if (_image == null) return;
try {
var request = http.MultipartRequest(
'POST',
Uri.parse('https://api.faceping.ai/groups/my-group/faces'),
);
request.headers['Authorization'] = 'Bearer your_api_key_here';
request.files.add(
await http.MultipartFile.fromPath('image', _image!.path),
);
final response = await request.send();
setState(() {
_status = response.statusCode == 200
? 'Face uploaded successfully'
: 'Failed to upload face';
});
} catch (e) {
setState(() {
_status = 'Error uploading face';
});
}
}
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: _pickImage,
child: const Text('Select Image'),
),
const SizedBox(height: 16),
if (_image != null)
Image.file(
_image!,
height: 200,
width: 200,
fit: BoxFit.cover,
),
if (_status.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text(_status),
),
],
);
}
}
Create lib/search_faces.dart
:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'dart:convert';
import 'dart:io';
class SearchFacesWidget extends StatefulWidget {
const SearchFacesWidget({super.key});
@override
State<SearchFacesWidget> createState() => _SearchFacesWidgetState();
}
class _SearchFacesWidgetState extends State<SearchFacesWidget> {
File? _image;
String _status = '';
List<double> _matches = [];
final _picker = ImagePicker();
Future<void> _pickImage() async {
final pickedFile = await _picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
setState(() {
_image = File(pickedFile.path);
});
await _searchFaces();
}
}
Future<void> _searchFaces() async {
if (_image == null) return;
try {
var request = http.MultipartRequest(
'POST',
Uri.parse('https://api.faceping.ai/groups/my-group/search'),
);
request.headers['Authorization'] = 'Bearer your_api_key_here';
request.files.add(
await http.MultipartFile.fromPath('image', _image!.path),
);
final response = await request.send();
if (response.statusCode == 200) {
final responseData = await response.stream.bytesToString();
final data = json.decode(responseData);
setState(() {
_matches = (data['matches'] as List)
.map((m) => m['score'] as double)
.toList();
_status = 'Found ${_matches.length} matches';
});
} else {
throw Exception('Failed to search faces');
}
} catch (e) {
setState(() {
_status = 'Error searching faces';
_matches = [];
});
}
}
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: _pickImage,
child: const Text('Select Image'),
),
const SizedBox(height: 16),
if (_image != null)
Image.file(
_image!,
height: 200,
width: 200,
fit: BoxFit.cover,
),
if (_status.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text(_status),
),
if (_matches.isNotEmpty)
Expanded(
child: ListView.builder(
itemCount: _matches.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('Match Score: ${_matches[index].toStringAsFixed(2)}'),
);
},
),
),
],
);
}
}