I'm trying to create a realtime poseNet demo app with the help of Flutter and its Camera package. Displaying the camera preview works very well, but when I try to access the image stream via controller.startImageStream the program crashes. I've succeded in tracking the source of that bug down, and it seems to me that the incoming frames in the 'controller.startImageStream' return values of null. Why is this, and how can I possibly fix it?

The snippet looks like this:

controller.startImageStream((CameraImage img) { controller.stopImageStream(); if (!isPaused) { runPoseNetOnFrame(bytesList: img.planes.map((plane) { return plane.bytes; }).toList(), imageHeight: img.height, imageWidth: img.width, numResults: 1).then((recognitions) { setState(() { photo = img; _recognitions = recognitions; imageHeight = img.height; imageWidth = img.width; }); }); } });

And it's the variable, img that's for every iteration composed of nothing but type null when it really should contain a frame of type CameraImage

While the app crashes I get this error in my console:

E/flutter (26077): [ERROR:flutter/shell/common/shell.cc(178)] Dart Error: Unhandled exception: E/flutter (26077): NoSuchMethodError: The getter 'isActive' was called on null. E/flutter (26077): Receiver: null E/flutter (26077): Tried calling: isActive

Here's my code for the entire page:

import 'package:flutter/material.dart'; import 'package:tflite/tflite.dart'; import 'package:flutter/services.dart'; import 'dart:typed_data'; import 'package:camera/camera.dart'; class CoachPage extends StatefulWidget { @override _CoachPageState createState() { return _CoachPageState(); } } class _CoachPageState extends State<CoachPage> { bool isPaused = true; CameraController controller; List cameras; int selectedCameraIdx; String imagePath; static const MethodChannel _channel = const MethodChannel('tflite'); String model; List<dynamic> _recognitions; int imageHeight; int imageWidth; CameraImage photo; @override void initState() { super.initState(); availableCameras().then((availableCameras) { cameras = availableCameras; if (cameras.length > 0) { setState(() { selectedCameraIdx = 0; }); _initCameraController(cameras[selectedCameraIdx]); } else{ print("No camera available"); } }).catchError((err) { print('Error: $err.code

Error Message: $err.message'); }); } void _initCameraController(CameraDescription cameraDescription) { controller = CameraController(cameraDescription, ResolutionPreset.medium); controller.initialize().then((_) { if (!mounted) { return; } controller.addListener(() {}); controller.startImageStream((CameraImage img) { controller.stopImageStream(); if (!isPaused) { runPoseNetOnFrame(bytesList: img.planes.map((plane) { return plane.bytes; }).toList(), imageHeight: img.height, imageWidth: img.width, numResults: 1).then((recognitions) { setState(() { photo = img; _recognitions = recognitions; imageHeight = img.height; imageWidth = img.width; }); }); } }); setState(() {}); });} @override void dispose() { controller?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Container( child: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Expanded( flex: 1, child: isPaused ? _cameraPreviewWidget() : _renderKeypoints(), ), SizedBox(height: 10.0), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ _cameraTogglesRowWidget(), _captureControlRowWidget(context), Spacer(), Text(photo.toString()) ], ), SizedBox(height: 20.0) ], ), ), ), ); } /// Display Camera preview. Widget _cameraPreviewWidget() { if (controller == null || !controller.value.isInitialized) { return const Text( 'Loading', style: TextStyle( color: Colors.white, fontSize: 20.0, fontWeight: FontWeight.w900, ), ); } return AspectRatio( aspectRatio: controller.value.aspectRatio, child: CameraPreview(controller), ); } /// Display the control bar with buttons to take pictures Widget _captureControlRowWidget(context) { return Expanded( child: Align( alignment: Alignment.center, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisSize: MainAxisSize.max, children: [ FloatingActionButton( child:(isPaused) ? Icon(Icons.play_arrow) : Icon(Icons.pause), backgroundColor: Colors.blueGrey, onPressed: () { setState(() { isPaused = !isPaused; }); }) ], ), ), ); } /// Display a row of toggle to select the camera (or a message if no camera is available). Widget _cameraTogglesRowWidget() { if (cameras == null || cameras.isEmpty) { return Spacer(); } CameraDescription selectedCamera = cameras[selectedCameraIdx]; CameraLensDirection lensDirection = selectedCamera.lensDirection; return Expanded( child: Align( alignment: Alignment.centerLeft, child: FlatButton.icon( onPressed: _onSwitchCamera, icon: Icon(_getCameraLensIcon(lensDirection)), label: Text( "${lensDirection.toString().substring(lensDirection.toString().indexOf('.') + 1)}")), ), ); } IconData _getCameraLensIcon(CameraLensDirection direction) { switch (direction) { case CameraLensDirection.back: return Icons.camera_rear; case CameraLensDirection.front: return Icons.camera_front; case CameraLensDirection.external: return Icons.camera; default: return Icons.device_unknown; } } void _onSwitchCamera() { selectedCameraIdx = selectedCameraIdx < cameras.length - 1 ? selectedCameraIdx + 1 : 0; CameraDescription selectedCamera = cameras[selectedCameraIdx]; _initCameraController(selectedCamera); } void _showCameraException(CameraException e) { String errorText = 'Error: ${e.code}

Error Message: ${e.description}'; print(errorText); print('Error: ${e.code}

${e.description}'); } Future loadModel() async { Tflite.close(); String res = await Tflite.loadModel( model: "assets/posenet_mv1_075_float_from_checkpoints.tflite"); model = res; } Future<List> runPoseNetOnFrame( {@required List<Uint8List> bytesList, int imageHeight = 1280, int imageWidth = 720, double imageMean = 127.5, double imageStd = 127.5, int rotation: 90, // Android only int numResults = 1, double threshold = 0.5, int nmsRadius = 20, bool asynch = true}) async { return await _channel.invokeMethod( 'runPoseNetOnFrame', { "bytesList": bytesList, "imageHeight": imageHeight, "imageWidth": imageWidth, "imageMean": imageMean, "imageStd": imageStd, "rotation": rotation, "numResults": numResults, "threshold": threshold, "nmsRadius": nmsRadius, "asynch": asynch, }, ); } List<Widget> _renderKeypoints() { var lists = <Widget>[]; _recognitions.forEach((re) { var list = re["keypoints"].values.map<Widget>((k) { var x = k["x"]; var y = k["y"]; return Positioned( left: x - 6, top: y - 6, width: 100, height: 12, child: Container( child: Text( "● ${k["part"]}", style: TextStyle( color: Color.fromRGBO(37, 213, 253, 1.0), fontSize: 12.0, ), ), ), ); }).toList(); lists.addAll(list); }); return lists; } }

Thanks in advance! ;)