Bug known when scanning face, the camera spamming take photo and doing flashing on screen on iPhone

17 Views Asked by At

example of the problem I got

code from the problematic program

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image/image.dart' as imglib;

import 'package:shared_preferences/shared_preferences.dart';
import 'package:camera/camera.dart';
import 'package:google_mlkit_face_detection/google_mlkit_face_detection.dart';
import 'package:flutter_face_api/face_api.dart' as Regula;

import '../conn/getFoto.dart';


String nama = "-";
String pin = "-";
String instruk = "Scanning...";
String _similarity = "nil";

var takenPicture;
var takenPicturePath;

int camNum = 1;
double persenCocok = 0;

bool faceUp = false;
bool faceDown = false;
bool faceRight = false;
bool faceLeft = false;
bool faceCenter = false;

class AbsenFoto extends StatefulWidget {
  const AbsenFoto({super.key});

  @override
  State<AbsenFoto> createState() => _AbsenFotoState();
}

class _AbsenFotoState extends State<AbsenFoto> {
  List<CameraDescription>? cameras;
  CameraController? controller;

  var faceDetector;
  late List<Face> _faces;

  Color topBar = Color.fromRGBO(22, 149, 0, 1.0);
  Color dataBackgroundColor = Color.fromRGBO(152, 136, 136, 1.0);
  Color switchCameraButtonColor = Color.fromRGBO(3, 217, 254, 1.0);
  Color batalButton = Color.fromRGBO(234, 0, 1, 1.0);

  @override
  void initState() {
    camInit();
    _facesInit();
    getFoto().gettingFoto();
    super.initState();
  }

  @override
  void dispose() {
    faceDetector.close();
    controller?.dispose();
    faceUp = false;
    faceDown = false;
    faceRight = false;
    faceLeft = false;
    faceCenter = false;
    instruk = "Scanning...";
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    setState(() {
      getNama();
    });
    return Scaffold(
      appBar: AppBar(
        title: Text(
          "Absensi Mangusada",
        ),
        backgroundColor: topBar,
        foregroundColor: CupertinoColors.white,
      ),
      body: Padding(
        padding: EdgeInsets.only(top: 20),
        child: SingleChildScrollView(
          child: Center(
            child: Column(
              children: [
                Container(
                  height: 380,
                  width: 240,
                  child: showCam(),
                ),
                SizedBox(
                  height: 50,
                ),
                Text(
                  instruk,
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                  textAlign: TextAlign.center,
                ),
                SizedBox(
                  height: 16,
                ),
                Container(
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(10),
                    color: dataBackgroundColor,
                  ),
                  height: 100,
                  width: 310,
                  padding: EdgeInsets.only(top: 30, left: 16),
                  child: Align(
                    alignment: Alignment.centerLeft,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        SizedBox(
                          width: 8,
                        ),
                        Text(
                          nama,
                          style: TextStyle(color: CupertinoColors.white),
                        ),
                        Text(
                          pin,
                          style: TextStyle(color: CupertinoColors.white),
                        ),
                      ],
                    ),
                  ),
                ),
                SizedBox(
                  height: 16,
                ),
                ElevatedButton(
                  onPressed: () async {
                    if (camNum == 0) {
                      camNum = 1;
                      await updateController(cameras![camNum]);
                    } else if (camNum == 1) {
                      camNum = 0;
                      await updateController(cameras![camNum]);
                    }
                  },
                  child: Text("SWITCH CAMERA"),
                  style: ButtonStyle(
                    backgroundColor:
                        MaterialStatePropertyAll(switchCameraButtonColor),
                    foregroundColor:
                        MaterialStatePropertyAll(CupertinoColors.white),
                    minimumSize: MaterialStateProperty.all(
                      Size(310, 60),
                    ),
                    shape: MaterialStatePropertyAll(
                      RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10),
                      ),
                    ),
                  ),
                ),
                SizedBox(
                  height: 16,
                ),
                ElevatedButton(
                  onPressed: () {
                    if (mounted) {
                      controller!.dispose();
                      faceUp = false;
                      faceDown = false;
                      faceRight = false;
                      faceLeft = false;
                      faceCenter = false;
                    }
                    Navigator.pushReplacementNamed(context, '/absen');
                  },
                  child: Text("BATAL"),
                  style: ButtonStyle(
                    backgroundColor: MaterialStatePropertyAll(batalButton),
                    foregroundColor:
                        MaterialStatePropertyAll(CupertinoColors.white),
                    minimumSize: MaterialStateProperty.all(
                      Size(310, 60),
                    ),
                    shape: MaterialStatePropertyAll(
                      RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  camInit() async {
    cameras = await availableCameras();
    if (cameras != null) {
      controller = CameraController(cameras![1], ResolutionPreset.high, imageFormatGroup: Platform.isAndroid ? ImageFormatGroup.nv21 : ImageFormatGroup.bgra8888, enableAudio: false);

      await controller!.initialize().then((_) {
        if (!mounted) {
          return;
        }
        setState(() {});
      });
    } else {
      print("NO any camera found");
    }
  }

  showCam() {
    if (controller == null) {
      return Center(child: Text("Loading Camera..."),);
    } else if (!controller!.value.isInitialized) {
      return Center(child: CircularProgressIndicator(),);
    } else {
      return Stack(
        children: [
          CameraPreview(controller!),
          FutureBuilder<List<Face>>(
            future: _detectFaces(),
            builder: (context, snapshot) {
              return Container();
            }
          ),
        ],
      );
    }
  }

  _facesInit() {
    final FaceDetectorOptions options = FaceDetectorOptions(
      enableClassification: true,
      enableTracking: true,
      enableLandmarks: true,
      enableContours: true,
      performanceMode: FaceDetectorMode.accurate
    );
    faceDetector = FaceDetector(options: options);
  }

  updateController(CameraDescription description) {
    controller?.dispose().then((value) async {
      setState(() {});
      controller = CameraController(description, ResolutionPreset.high, imageFormatGroup: Platform.isAndroid ? ImageFormatGroup.nv21 : ImageFormatGroup.bgra8888, enableAudio: false);
      controller?.initialize().then((_) {
        setState(() {});
      });
    });
  }

  Future<List<Face>> _detectFaces() async {
    takenPicture = await controller?.takePicture();
    takenPicturePath = takenPicture.path;
    final inputImage = InputImage.fromFilePath(takenPicture!.path);
    _faces = await faceDetector.processImage(inputImage);

    setState(() {
      if (_faces.isEmpty) {
        instruk = "Wajah tidak terdeteksi";
      } else {
        instruk = "Scanning...";
        if (faceUp == false) {
          instruk = "Hadap ke atas";
          _faces.single.headEulerAngleX! >= 20 ? faceUp = true : faceUp = false ;
        } else if (faceDown == false) {
          instruk = "Hadap ke bawah";
          _faces.single.headEulerAngleX! <= -20 ? faceDown = true : faceDown = false ;
        } else if (faceRight == false) {
          instruk = "Toleh ke kanan";
          _faces.single.headEulerAngleY! <= -20 ? faceRight = true : faceRight = false ;
        } else if (faceLeft == false) {
          instruk = "Toleh ke kiri";
          _faces.single.headEulerAngleY! >= 20 ? faceLeft = true : faceLeft = false ;
        } else if (faceCenter == false) {
          instruk = "Lihat ke depan";
          (_faces.single.headEulerAngleY! >= -5 && _faces.single.headEulerAngleY! <= 5) && (_faces.single.headEulerAngleX! >= -5 && _faces.single.headEulerAngleX! <= 5)
              ? faceCenter = true : faceCenter = false ;
        } else {
          instruk = "Harap tunggu...\nTahan Posisi Anda";
        }
      }
    });
    if (faceUp == true && faceDown == true && faceRight == true && faceLeft == true && faceCenter == true) {
      instruk = "Harap tunggu...\nTahan Posisi Anda";
      compareFace();

      if (persenCocok >= 95) {
        await controller?.pausePreview();

        showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text("Verifikasi Liveness Berhasil!"),
              content: Text('Anda asli!\nWajah anda $_similarity sama dengan yang ada di server'),
              actions: [
                TextButton(
                  onPressed: () {
                    setState(() {
                      faceUp = false;
                      faceDown = false;
                      faceRight = false;
                      faceLeft = false;
                      faceCenter = false;
                    });
                    Navigator.pushNamedAndRemoveUntil(context, "/home", (route) => false);
                  },
                  child: Text("OK"),
                )
              ],
            );
          }
        );
      } else if (_similarity == "error") {
        showDialog(
            context: context,
            builder: (BuildContext context) {
              return AlertDialog(
                title: Text("Verifikasi Liveness Berhasil!"),
                content: Text('Anda asli!\nTetapi wajah anda tidak sama dengan gambar yang ada di server'),
                actions: [
                  TextButton(
                    onPressed: () {
                      setState(() {
                        faceUp = false;
                        faceDown = false;
                        faceRight = false;
                        faceLeft = false;
                        faceCenter = false;
                      });
                      Navigator.pushNamedAndRemoveUntil(context, "/home", (route) => false);
                    },
                    child: Text("OK"),
                  )
                ],
              );
            }
        );
      } else {
        instruk = "Harap tunggu...\nTahan Posisi Anda";
      }
    }
    return _faces;
  }

  compareFace() async {
    var image1 = Regula.MatchFacesImage();
    var image2 = Regula.MatchFacesImage();

    imglib.Image? FileImage1 = imglib.decodeImage(File(takenPicturePath).readAsBytesSync());
    imglib.Image? FileImage2 = imglib.decodeImage(File(getFoto().getPathPhoto()).readAsBytesSync());

    List<int> image1Bytes = imglib.encodePng(FileImage1!);
    List<int> image2Bytes = imglib.encodePng(FileImage2!);

    image1.bitmap = base64Encode(image1Bytes);
    image1.imageType = Regula.ImageType.PRINTED;

    image2.bitmap = base64Encode(image2Bytes);
    image2.imageType = Regula.ImageType.PRINTED;

    if (image1.bitmap == null ||
        image1.bitmap == "" ||
        image2.bitmap == null ||
        image2.bitmap == "") return 0;

    var request = await Regula.MatchFacesRequest();
    request.images = [image1, image2];
    Regula.FaceSDK.matchFaces(jsonEncode(request)).then((value) {
      var response = Regula.MatchFacesResponse.fromJson(json.decode(value));
      Regula.FaceSDK.matchFacesSimilarityThresholdSplit(
          jsonEncode(response!.results), 0.75)
          .then((str) {
        var split = Regula.MatchFacesSimilarityThresholdSplit.fromJson(
            json.decode(str));
        setState(() {
          _similarity = split!.matchedFaces.isNotEmpty
              ? ("${(split.matchedFaces[0]!.similarity! * 100).toStringAsFixed(2)}%")
              : "error";

          persenCocok = split.matchedFaces.isNotEmpty
              ? (split.matchedFaces[0]!.similarity! * 100)
              : 0;
        });
      });
    });
    return _similarity;
  }

  getNama() async {
    final prefs = await SharedPreferences.getInstance();

    nama = prefs.get("user").toString();
    pin = prefs.get("pin").toString();
  }
}

I tried running the code on Android and it successfully displayed the camera and face scanning. and when I type the code on the iOS device the camera is spamming taking photos and flashing on the iPhone screen

I hope everything can run smoothly like on Android

0

There are 0 best solutions below