import 'dart:async'; import 'dart:ffi'; import 'dart:ui'; import 'dart:typed_data'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:camera/camera.dart'; import 'package:image/image.dart' as img; List cameras = []; Future main() async { WidgetsFlutterBinding.ensureInitialized(); cameras = await availableCameras(); runApp(CameraApp()); } class CameraApp extends StatefulWidget { @override _CameraAppState createState() => _CameraAppState(); } class _CameraAppState extends State { CameraController? controller; var streaming = false; var image_width = 0; var image_height = 0; var posy = 0.0; var posx = 0.0; var count = 0; var frameNumber = 0; static const alpha = 0.90; static const thresh = 50; var previousImage = []; var gray = []; var diff = []; var dst = []; var background = []; @override void initState() { super.initState(); controller = CameraController(cameras[1], ResolutionPreset.low); controller!.initialize().then((_) { if (!mounted) { return; } setState(() {}); }); } @override void dispose() { controller?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final CameraController cameraController = controller!; if (!cameraController.value.isInitialized) { return Container(); } return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('Home'), ), body: Stack(children: [ diffView(), Container( height: image_height.toDouble(), width: image_width.toDouble(), child: CustomPaint( painter: OpenPainter(posx, posy), ), ), ]), floatingActionButton: FloatingActionButton( child: const Icon(Icons.plus_one), onPressed: () { startStream(); }, ), ), debugShowCheckedModeBanner: false, ); } Widget diffView() { return Transform.rotate( angle: 0.0, //pi * -0.5 child: diff.isEmpty ? Container() : Image.memory(Uint8List.fromList(img.encodeJpg((img.Image.fromBytes( image_width, image_height, diff, format: img.Format.luminance))))), ); } void startStream() { final CameraController? cameraController = controller; if (cameraController == null || !cameraController.value.isInitialized) { return; } if (streaming == false) { cameraController.startImageStream(handleImage); } else { cameraController.stopImageStream(); } setState(() { streaming = !streaming; }); } void handleImage(CameraImage src) async { if (previousImage.isEmpty) { previousImage = List.filled(src.planes[0].bytes.length, 0); gray = List.filled(src.planes[0].bytes.length, 0); diff = List.filled(src.planes[0].bytes.length, 0); dst = List.filled(src.planes[0].bytes.length, 0); background = List.filled(src.planes[0].bytes.length, 0.0); image_width = src.width; image_height = src.height; } else { if (frameNumber % 10 == 0) { gray = src.planes[0].bytes; count = 0; var xVal = 0.0; var yVal = 0.0; for (var i = 0; i < gray.length; i++) { background[i] = background[i] * alpha + gray[i] * (1.0 - alpha); diff[i] = (gray[i] - background[i].toInt()).abs(); dst[i] = background[i].toInt(); if (diff[i] < thresh) { diff[i] = 0; } else { //diff[i] = 255; xVal += diff[i] * ((i % image_width) + 1); yVal += diff[i] * ((i % image_height) + 1); count += diff[i]; } } // End Processing previousImage = gray.toList(); if (count != 0) { posx = xVal / count; posy = yVal / count; print("$count ${posx.toInt()} ${posy.toInt()}"); } setState(() {}); } frameNumber += 1; } } } class OpenPainter extends CustomPainter { double posx; double posy; OpenPainter(this.posx, this.posy); @override void paint(Canvas canvas, Size size) { canvas.drawCircle(Offset(posx, posy), 10, Paint()..color = Color.fromARGB(255, 0, 255, 0)); } @override bool shouldRepaint(CustomPainter oldDelegate) => true; }