Flutter:将条形码叠加在Firebase视觉检测到的条形码上 [英] Flutter : Overlaying the graphics on the barcode which is detected by firebase vision

查看:127
本文介绍了Flutter:将条形码叠加在Firebase视觉检测到的条形码上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Flutter中实现条形码扫描仪应用程序,在该应用程序中,可以将相机作为小部件嵌入而不是使其全屏显示.

因此,我使用了

在Redmi 5上输出相同的代码

我将所有设备的摄像头分辨率默认设置为(1280 x 720),并且在覆盖前也要缩放输出

我试图了解是什么在不同设备上造成了这种情况

  1. 现在,如果我尝试调整摄像头预览的小部件高度,则在oneplus上的结果也不一致

我认为这与缩放部分有关,但我不确定.

下面的代码用于相机预览和叠加图形

  import'package:flutter/material.dart';导入'package:flutter/rendering.dart';导入'package:qr_mobile_vision/qr_camera.dart';导入'package:qr_mobile_vision/qr_barcode.dart';导入'package:vision_demo/barcode_detctor_painter.dart';导入'package:vision_demo/overlay.dart';void main(){debugPaintSizeEnabled = false;runApp(new HomePage());}HomePage扩展StatefulWidget {@overrideHomeState createState()=>新的HomeState();}类HomeState扩展State< HomePage>{@override窗口小部件build(BuildContext context){返回新的MaterialApp(home:新的MyApp());}}MyApp类扩展了StatefulWidget {@override_MyAppState createState()=>新的_MyAppState();}类别_MyAppState扩展了State< MyApp>{bool camState = false;列表<条形码>条码= List< Barcode>();@overrideinitState(){super.initState();}@override窗口小部件build(BuildContext context){返回新的脚手架(appBar:新的AppBar(标题:new Text('Demo app'),),正文:新中心(子级:新列(crossAxisAlignment:CrossAxisAlignment.center,mainAxisAlignment:MainAxisAlignment.start,子代:< Widget> [camState?新的SizedBox(宽度:MediaQuery.of(context).size.width,高度:MediaQuery.of(context).size.height-300-AppBar().preferredSize.height,子代:Stack(孩子们: [新的QrCamera(onError :(上下文,错误)=>文本(error.toString(),样式:TextStyle(颜色:Colors.red),),qrCodeCallback :(代码){setState((){条形码=代码;});},子代:新容器(装饰:新BoxDecoration(颜色:Colors.transparent,),),),容器(约束:const BoxConstraints.expand(),装饰:ShapeDecoration(形状:QrScannerOverlayShape(cutOutSize:MediaQuery.of(context).size.width-160,borderColor:Colors.white),)),LayoutBuilder(builder:(BuildContext context,BoxConstraints约束){返回_buildResults(constraints);})],),):展开(子项:新的中心(子项:新的Text(未激活照相机")))),],),),floatActionButton:新的FloatingActionButton(子:new Text(按我",textAlign:TextAlign.center,),onPressed:(){setState((){camState =!camState;});}),);}小部件_buildResults(BoxConstraints约束){const Text noResultsText = Text('无结果!');如果(条形码==空){返回noResultsText;}CustomPainter画家;最终大小imageSize = Size(720.0,1280.0);如果(条形码是!List< Barcode>)返回noResultsText;painter = BarcodeDetectorPainter(imageSize,条码);返回CustomPaint(大小:大小(double.maxFinite,double.maxFinite),画家:画家,);}} 

下面是用于调整图形大小以覆盖图形的代码.

  import'package:flutter/material.dart';导入'package:qr_mobile_vision/qr_barcode.dart';BarcodeDetectorPainter类扩展了CustomPainter {BarcodeDetectorPainter(this.absoluteImageSize,this.barcodeLocations);//absoluteImageSize将始终为(1280 x 720)最终列表<条形码>条码位置;最终大小absoluteImageSize;@override无效油漆(帆布,尺寸){最后的double scaleX = size.width/absoluteImageSize.width;最终的double scaleY = size.height/absoluteImageSize.height;矩形scaleRect(条形码条形码){返回Rect.fromLTRB(条码.boundingBox.left * scaleX,条码.boundingBox.top * scaleY,条码.boundingBox.right * scaleX,条码.boundingBox.bottom * scaleY,);}最终Paint paint = Paint()..style = PaintingStyle.fill..strokeWidth = 2.0;用于(条形码位置中的条形码){paint.color = Colors.green;canvas.drawRect(scaleRect(条形码),油漆);}}@overridebool shouldRepaint(BarcodeDetectorPainter oldDelegate){返回oldDelegate.absoluteImageSize!= absoluteImageSize ||oldDelegate.barcodeLocations!=条码位置;}} 

解决这两个问题很重要,因为在此之后,我想限制扫描区域,以便仅捕获与我添加的切口尺寸对齐的条形码.

感谢您的任何帮助.

解决方案

我能够解决此问题,问题是在多个设备上都具有恒定的分辨率,某些设备可能没有我设置的分辨率,因此可以通过编程实现根据屏幕尺寸设置最佳最低分辨率可以解决我的问题.

I am trying to implement a barcode scanner app in Flutter where the camera can be embedded as a widget rather than making it fullscreen.

So I went with the flutter_qr_mobile_vision package as we can use the native camera features and also restricting the camera preview size.

But the above package gives only the barcode string which is detected by the MLKit and not the barcode details like bounding box, barcode type, and other information, so I took the source code of the above package and made some changes so that I get the bounding box which can be used to overlay a graphic on the detected barcode(s).

The code for what im trying to do can be found here

Now I'm facing two problems while using these changes (Android implementation only as of now)

  1. When I'm trying to overlay the bounding box on top of the barcode, results are inconsistent across multiple devices.

For example:

Works fine on oneplus in fullscreen

Same code output on Redmi 5

I have kept the camera resolution by default as (1280 x 720) for all the devices and scaling the output as well before overlaying

I'm trying to understand what is causing this on different devices

  1. Now If I try to resize the widget height of the camera preview, the results are inconsistent on oneplus as well

I feel this is something to do with the scaling part but im not sure.

Below code is for camera preview and overlay graphic

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:qr_mobile_vision/qr_camera.dart';
import 'package:qr_mobile_vision/qr_barcode.dart';
import 'package:vision_demo/barcode_detctor_painter.dart';
import 'package:vision_demo/overlay.dart';

void main() {
  debugPaintSizeEnabled = false;
  runApp(new HomePage());
}

class HomePage extends StatefulWidget {
  @override
  HomeState createState() => new HomeState();
}

class HomeState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(home: new MyApp());
  }
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool camState = false;
  List<Barcode> barcode = List<Barcode>();

  @override
  initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Demo app'),
      ),
      body: new Center(
        child: new Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            camState
                ? new SizedBox(
                    width: MediaQuery.of(context).size.width,
                    height: MediaQuery.of(context).size.height - 300 - AppBar().preferredSize.height,
                    child: Stack(
                      children: [
                        new QrCamera(
                          onError: (context, error) => Text(
                            error.toString(),
                            style: TextStyle(color: Colors.red),
                          ),
                          qrCodeCallback: (code) {
                            setState(() {
                              barcode = code;
                            });
                          },
                          child: new Container(
                            decoration: new BoxDecoration(
                              color: Colors.transparent,
                            ),
                          ),
                        ),
                        Container(
                            constraints: const BoxConstraints.expand(),
                            decoration: ShapeDecoration(
                              shape: QrScannerOverlayShape(cutOutSize: MediaQuery.of(context).size.width - 160, borderColor: Colors.white),
                            )),
                        LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
                          return _buildResults(constraints);
                        })
                      ],
                    ),
                  )
                : Expanded(child: new Center(child: new Text("Camera inactive"))),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
          child: new Text(
            "press me",
            textAlign: TextAlign.center,
          ),
          onPressed: () {
            setState(() {
              camState = !camState;
            });
          }),
    );
  }

  Widget _buildResults(BoxConstraints constraints) {
    const Text noResultsText = Text('No results!');

    if (barcode == null) {
      return noResultsText;
    }

    CustomPainter painter;

    final Size imageSize = Size(720.0, 1280.0);

    if (barcode is! List<Barcode>) return noResultsText;
    painter = BarcodeDetectorPainter(imageSize, barcode);

    return CustomPaint(
      size: Size(double.maxFinite, double.maxFinite),
      painter: painter,
    );
  }
}

Below is the code im using to resize for overlaying the graphics.

import 'package:flutter/material.dart';
import 'package:qr_mobile_vision/qr_barcode.dart';

class BarcodeDetectorPainter extends CustomPainter {
  BarcodeDetectorPainter(this.absoluteImageSize, this.barcodeLocations); // absoluteImageSize will always be (1280 x 720) 

  final List<Barcode> barcodeLocations;
  final Size absoluteImageSize;

  @override
  void paint(Canvas canvas, Size size) {
    final double scaleX = size.width / absoluteImageSize.width;
    final double scaleY = size.height / absoluteImageSize.height;

    Rect scaleRect(Barcode barcode) {
      return Rect.fromLTRB(
        barcode.boundingBox.left * scaleX,
        barcode.boundingBox.top * scaleY,
        barcode.boundingBox.right * scaleX,
        barcode.boundingBox.bottom * scaleY,
      );
    }

    final Paint paint = Paint()
      ..style = PaintingStyle.fill
      ..strokeWidth = 2.0;

    for (Barcode barcode in barcodeLocations) {
      paint.color = Colors.green;

      canvas.drawRect(scaleRect(barcode), paint);
    }
  }

  @override
  bool shouldRepaint(BarcodeDetectorPainter oldDelegate) {
    return oldDelegate.absoluteImageSize != absoluteImageSize || oldDelegate.barcodeLocations != barcodeLocations;
  }
}


Resolving these 2 issue is important because after this i want to restrict the scanning area so that i can capture only the barcode which is aligned on the cutout size that I have added.

Any sort of help is appreciated.

解决方案

I was able to solve this issue, the problem is having a constant resolution throughout multiple devices, some devices might not have the resolution that I have set, so programmatically setting the best minimum resolution based on the screen size has resolved my problem.

这篇关于Flutter:将条形码叠加在Firebase视觉检测到的条形码上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆