Files
reprecord-app/lib/main.dart
2021-11-16 16:22:32 -06:00

182 lines
4.4 KiB
Dart

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<CameraDescription> cameras = [];
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
runApp(CameraApp());
}
class CameraApp extends StatefulWidget {
@override
_CameraAppState createState() => _CameraAppState();
}
class _CameraAppState extends State<CameraApp> {
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 = <int>[];
var gray = <int>[];
var diff = <int>[];
var dst = <int>[];
var background = <double>[];
@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: <Widget>[
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;
}