182 lines
4.4 KiB
Dart
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;
|
|
}
|