Minha solução abaixo
import 'dart:io';
import 'package:aws_client/rekognition_2016_06_27.dart' as aws;
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:nonio_ponto/db/usuario.dart';
import 'package:nonio_ponto/db/validacao_facial.dart';
import 'package:quickalert/quickalert.dart';
class AWSRekognitionScreen extends StatefulWidget {
final List<CameraDescription>? cameraDescriptions;
final Usuario? usuario;
final ValidacaoFacial? validacaoFacial;
AWSRekognitionScreen({Key? key, this.cameraDescriptions, this.usuario, this.validacaoFacial}) : super(key: key);
@override
_AWSRekognitionScreenState createState() => _AWSRekognitionScreenState();
}
class _AWSRekognitionScreenState extends State<AWSRekognitionScreen> {
final ImagePicker _picker = ImagePicker();
late CameraController _cameraController;
late Future<void> _initControllerFuture;
// Chaves de acesso (substitua pelas suas)
final _awsAccessKey = "---------";
final _awsSecretKey = "---------";
final _awsRegion = "us-east-1"; // Altere conforme necessário
bool _toggleCamera = false;
Future<void> _analyzeImage(File imageFile) async {
try {
aws.Rekognition rekognition = aws.Rekognition(
region: _awsRegion,
credentials: aws.AwsClientCredentials(
accessKey: _awsAccessKey,
secretKey: _awsSecretKey,
),
);
print(rekognition.toString());
final imageBytes = await imageFile.readAsBytes();
final response = await rekognition.compareFaces(
sourceImage: aws.Image(bytes: imageBytes),
targetImage: aws.Image(bytes: imageBytes),
);
//String detectedText = response.sourceImageFace?.map((detection) => detection.detectedText).join("\n") ?? "Nenhum texto detectado";
//print(detectedText);
setState(() {
//_result = detectedText;
});
} catch (e) {
setState(() {
//_result = "Erro ao analisar imagem: $e";
});
}
}
@override
void initState() {
super.initState();
_cameraController = CameraController(widget.cameraDescriptions![0], ResolutionPreset.high);
_initControllerFuture = _cameraController.initialize();
}
@override
void dispose() {
_cameraController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _initControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
final scale = 1 / (_cameraController.value.aspectRatio * MediaQuery.of(context).size.aspectRatio);
return Transform.scale(
scale: scale,
alignment: Alignment.topCenter,
child: Stack(
children: [
CameraPreview(
_cameraController,
child: Container(
padding: EdgeInsets.all(20.0),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: InkWell(
borderRadius: BorderRadius.all(Radius.circular(50.0)),
onTap: () async {
try {
// Ensure that the camera is initialized.
await _initControllerFuture;
// Attempt to take a picture and get the file `image`
// where it was saved.
XFile image = await _cameraController.takePicture();
if (image.path != null) {
setState(() {
//_image = File(image.path);
});
await _analyzeImage(File(image.path));
print(File(image.path).toString());
}
Navigator.of(context).pop();
} catch (e) {
// If an error occurs, log the error to the console.
print(e);
}
},
child: Container(
padding: EdgeInsets.all(4.0),
child: Icon(Icons.camera_alt, color: Colors.white, size: 35.0),
),
),
),
Expanded(
child: InkWell(
borderRadius: BorderRadius.all(Radius.circular(50.0)),
onTap: () {
if (!_toggleCamera) {
onCameraSelected(widget.cameraDescriptions![0]);
setState(() {
_toggleCamera = true;
});
} else {
onCameraSelected(widget.cameraDescriptions![1]);
setState(() {
_toggleCamera = false;
});
}
},
child: Container(
padding: EdgeInsets.all(4.0),
child: Icon(Icons.flip_camera_android, color: Colors.white, size: 35.0),
),
),
),
],
),
),
),
IgnorePointer(
child: CustomPaint(
painter: CirclePainter(),
child: Container(),
),
),
],
),
);
} else {
// Otherwise, display a loading indicator.
return const Center(child: CircularProgressIndicator());
}
},
),
);
}
void onCameraSelected(CameraDescription cameraDescription) async {
_cameraController = CameraController(cameraDescription, ResolutionPreset.high);
_cameraController.addListener(() {
if (mounted) setState(() {});
if (_cameraController.value.hasError) {
showMessage('Camera Error: ${_cameraController.value.errorDescription}');
}
});
try {
_initControllerFuture = _cameraController.initialize();
} on CameraException catch (e) {
showMessage('Camera Error: $e');
}
if (mounted) setState(() {});
}
void showMessage(String s) {
QuickAlert.show(
disableBackBtn: false,
showConfirmBtn: false,
context: context,
type: QuickAlertType.error,
title: 'Error',
text: s.toString(),
);
}
}
class RectanglePainter extends CustomPainter {
double? topMargin;
Size? Function(Size)? size;
// style
double strokeWidth = 2.0;
Color strokeColor = Colors.white;
Color? overlayColor;
Radius? borderRadius;
RectanglePainter({
this.topMargin,
this.strokeWidth = 2.0,
this.strokeColor = Colors.white,
this.overlayColor,
this.borderRadius,
});
@override
void paint(Canvas canvas, Size size) {
final topMargin = this.topMargin ?? (size.height * 0.3);
final width = this.size?.call(size)?.width ?? size.width * 0.8;
final height = this.size?.call(size)?.height ?? ((size.width * 0.8) / 1.5);
final borderRadius = this.borderRadius ?? const Radius.circular(10);
// Step 1: Draw the overlay with transparent rectangle
final overlayPath = Path()
..addRRect(
RRect.fromRectAndRadius(
Rect.fromCenter(
center: Offset(size.width / 2, topMargin),
width: width,
height: height,
),
borderRadius,
),
)
..addRect(Rect.fromLTWH(0.0, 0.0, size.width, size.height))
..fillType = PathFillType.evenOdd;
final overlayColor = this.overlayColor ?? Colors.black.withOpacity(0.7);
final overlayPaint = Paint()
..style = PaintingStyle.fill
..color = overlayColor; // semi-transparent black overlay
canvas.drawPath(overlayPath, overlayPaint);
// Step 2: Draw the white stroke around the circle
final strokePath = Path()
..addRRect(
RRect.fromRectAndRadius(
Rect.fromCenter(
center: Offset(size.width / 2, topMargin),
width: width,
height: height,
),
borderRadius,
),
);
final strokePaint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..color = strokeColor; // white stroke
canvas.drawPath(strokePath, strokePaint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
class CirclePainter extends CustomPainter {
double? topMargin;
double? Function(Size size)? circleRadius;
double progress = 0.0;
// style
double strokeWidth = 2.0;
Color strokeColor = Colors.white;
Color? overlayColor;
Color progressColor = Colors.green;
CirclePainter({
this.topMargin,
this.circleRadius,
this.progress = 0.0,
this.strokeWidth = 2.0,
this.strokeColor = Colors.white,
this.overlayColor,
this.progressColor = Colors.green,
});
@override
void paint(Canvas canvas, Size size) {
final circleRadius = this.circleRadius?.call(size) ?? ((size.width / 1.25) / 2);
final topMargin = this.topMargin ?? (size.height * 0.35);
// Step 1: Draw the overlay with transparent circle
final overlayPath = Path()
..addOval(
Rect.fromCenter(
center: Offset(
size.width / 2, // x-axis center
topMargin, // y-axis center with margin
),
width: size.width / 2,
height: size.height / 3)
/*Rect.fromCircle(
center: Offset(
size.width / 2, // x-axis center
topMargin, // y-axis center with margin
),
radius: circleRadius,
)*/,
)
..addRect(Rect.fromLTWH(0, 0, size.width, size.height))
..fillType = PathFillType.evenOdd;
final overlayColor = this.overlayColor ?? Colors.black.withOpacity(0.7);
final overlayPaint = Paint()
..style = PaintingStyle.fill
..color = overlayColor;
canvas.drawPath(overlayPath, overlayPaint);
// Step 2: Draw the white stroke around the circle
final strokePath = Path()
..addOval( Rect.fromCenter(
center: Offset(
size.width / 2, // x-axis center
topMargin, // y-axis center with margin
),
width: size.width / 2,
height: size.height / 3)/*Rect.fromCircle(
center: Offset(
size.width / 2, // x-axis center
topMargin, // y-axis center with margin
),
radius: circleRadius,
)*/);
final strokePaint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..color = strokeColor; // white stroke
canvas.drawPath(strokePath, strokePaint);
if (progress != 0.0) {
assert(this.progress >= 0.0 && this.progress <= 1.0);
// Step 3: Draw the progress arc (quarter circle)
final progressRect = Rect.fromCircle(
center: Offset(
size.width / 2, // x-axis center
topMargin, // y-axis center with margin
),
radius: circleRadius,
);
final strokeProgressPaint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..color = progressColor;
final progress = this.progress * 4; // 4 means full of circle, 2 means half of circle, 1 means quarter of circle
// Draw only a portion of the circle, progress defines how much
canvas.drawArc(
progressRect,
-90 * 3.1416 / 180, // Start angle (-90° = top of the circle)
progress * (3.14 / 2), // Sweep angle based on progress (quarter of circle = π/2 radians)
false,
strokeProgressPaint,
);
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
class OverlayPainter extends CustomPainter {
final double screenWidth;
final double screenHeight;
OverlayPainter({required this.screenWidth, required this.screenHeight});
@override
void paint(Canvas canvas, Size size) {
final radius = screenWidth * 0.45;
final strokeWidth = 2.0;
final circlePath = Path()
..addOval(Rect.fromCircle(
center: Offset(screenWidth / 2, screenHeight / 2.5),
radius: radius,
));
final outerPath = Path()
..addRect(Rect.fromLTWH(0, 0, screenWidth, screenHeight));
final overlayPath =
Path.combine(PathOperation.difference, outerPath, circlePath);
final paint = Paint()
..color = Colors.black.withOpacity(0.7)
..style = PaintingStyle.fill;
final borderPaint = Paint()
..color = Colors.white
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth;
canvas.drawPath(overlayPath, paint);
canvas.drawCircle(
Offset(screenWidth / 2, screenHeight / 2.5),
radius,
borderPaint,
);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}