import 'dart:ui' as ui; import 'package:firebase_ml_vision/firebase_ml_vision.dart'; import 'package:flutter/material.dart'; enum Detector { barcode, face, label, cloudLabel, text } class BarcodeDetectorPainter extends CustomPainter { BarcodeDetectorPainter(this.imageSize, this.barcodes); final Size imageSize; final List barcodes; @override void paint(Canvas canvas, Size size) { final Paint paint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 2.0; for (Barcode barcode in barcodes) { paint.color = Colors.green; canvas.drawRect( _scaleRect( rect: barcode.boundingBox, imageSize: imageSize, widgetSize: size, ), paint, ); } } @override bool shouldRepaint(BarcodeDetectorPainter oldDelegate) { return oldDelegate.imageSize != imageSize || oldDelegate.barcodes != barcodes; } } class FaceDetectorPainter extends CustomPainter { FaceDetectorPainter(this.imageSize, this.faces); final Size imageSize; final List faces; @override void paint(Canvas canvas, Size size) { final Paint paint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 2.0 ..color = Colors.red; for (Face face in faces) { canvas.drawRect( _scaleRect( rect: face.boundingBox, imageSize: imageSize, widgetSize: size, ), paint, ); } } @override bool shouldRepaint(FaceDetectorPainter oldDelegate) { return oldDelegate.imageSize != imageSize || oldDelegate.faces != faces; } } class LabelDetectorPainter extends CustomPainter { LabelDetectorPainter(this.imageSize, this.labels); final Size imageSize; final List labels; @override void paint(Canvas canvas, Size size) { final ui.ParagraphBuilder builder = ui.ParagraphBuilder( ui.ParagraphStyle( textAlign: TextAlign.left, fontSize: 23.0, textDirection: TextDirection.ltr), ); builder.pushStyle(ui.TextStyle(color: Colors.green)); // for (Label label in labels) { // builder.addText('Label: ${label.label}, ' // 'Confidence: ${label.confidence.toStringAsFixed(2)}\n'); // } builder.pop(); canvas.drawParagraph( builder.build() ..layout(ui.ParagraphConstraints( width: size.width, )), const Offset(0.0, 0.0), ); } @override bool shouldRepaint(LabelDetectorPainter oldDelegate) { return oldDelegate.imageSize != imageSize || oldDelegate.labels != labels; } } // Paints rectangles around all the text in the image. class TextDetectorPainter extends CustomPainter { TextDetectorPainter(this.imageSize, this.visionText); final Size imageSize; final VisionText visionText; @override void paint(Canvas canvas, Size size) { final Paint paint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 2.0; Rect _getRect(TextContainer container) { return _scaleRect( rect: container.boundingBox, imageSize: imageSize, widgetSize: size, ); } for (TextBlock block in visionText.blocks) { for (TextLine line in block.lines) { for (TextElement element in line.elements) { paint.color = Colors.green; canvas.drawRect(_getRect(element), paint); } paint.color = Colors.yellow; canvas.drawRect(_getRect(line), paint); } paint.color = Colors.red; canvas.drawRect(_getRect(block), paint); } } @override bool shouldRepaint(TextDetectorPainter oldDelegate) { return oldDelegate.imageSize != imageSize || oldDelegate.visionText != visionText; } } Rect _scaleRect({ required Rect rect, required Size imageSize, required Size widgetSize, }) { final double scaleX = widgetSize.width / imageSize.width; final double scaleY = widgetSize.height / imageSize.height; return Rect.fromLTRB( rect.left.toDouble() * scaleX, rect.top.toDouble() * scaleY, rect.right.toDouble() * scaleX, rect.bottom.toDouble() * scaleY, ); }