Flutter增强现实相机插件camera_deep_ar的使用

Flutter增强现实相机插件camera_deep_ar的使用

获取开始

首先,从DeepAR获取您的API密钥。您可以访问DeepAR官网来获取这些密钥。

DeepArConfig config = DeepArConfig(
  androidKey:
      "3b58c448bd650192e7c53d965cfe5dc1c341d2568b663a3962b7517c4ac6eeed0ba1fb2afe491a4b",
  ioskey:
      "53618212114fc16bbd7499c0c04c2ca11a4eed188dc20ed62a7f7eec02b41cb34d638e72945a6bf6",
  displayMode: DisplayMode.camera,
);

创建控制器

创建CameraDeepArController实例,并设置一些初始状态变量。

final deepArController = CameraDeepArController(config);
String _platformVersion = 'Unknown';
bool isRecording = false;
CameraMode cameraMode = config.cameraMode;
DisplayMode displayMode = config.displayMode;

设置事件监听器

为控制器设置事件处理器以处理相机准备就绪、拍照完成、视频录制完成等事件。

deepArController.setEventHandler(DeepArEventHandler(
  onCameraReady: (v) {
    _platformVersion = "onCameraReady $v";
    setState(() {});
  },
  onSnapPhotoCompleted: (v) {
    _platformVersion = "onSnapPhotoCompleted $v";
    setState(() {});
  },
  onVideoRecordingComplete: (v) {
    _platformVersion = "onVideoRecordingComplete $v";
    setState(() {});
  },
  onSwitchEffect: (v) {
    _platformVersion = "onSwitchEffect $v";
    setState(() {});
  },
));

创建DeepAR相机预览小部件

DeepArPreview小部件添加到应用中以显示相机预览。

DeepArPreview(deepArController),

控制器函数

可以调用以下方法来控制相机:

  • 拍照:

    deepArController.snapPhoto();
    
  • 开始录制视频:

    deepArController.startVideoRecording();
    
  • 切换效果:

    deepArController.switchEffect(cameraMode, imgPath);
    
  • 停止视频录制:

    deepArController.stopVideoRecording();
    

Android配置

在Android上,您需要确保添加了必要的权限,并且在proguard-rules.pro文件中保持类成员不受混淆。

<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

-keepclassmembers class ai.deepar.ar.DeepAR { *; }

iOS配置

在iOS上,您只需要在Info.plist文件中添加权限描述信息。

<key>NSCameraUsageDescription</key>
<string>Allows you to capture your best moment</string>
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Allows you to capture your best moment</string>
<key>NSMicrophoneUsageDescription</key>
<string>Needs access to your mic to help your record voice notes on chat/message conversations</string>

完整示例代码

下面是完整的示例代码,展示了如何使用camera_deep_ar插件。

import 'dart:io';

import 'package:camera_deep_ar/camera_deep_ar.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';

import 'config.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final deepArController = CameraDeepArController(config);
  String _platformVersion = 'Unknown';
  bool isRecording = false;
  CameraMode cameraMode = config.cameraMode;
  DisplayMode displayMode = config.displayMode;
  int currentEffect = 0;

  List get effectList {
    switch (cameraMode) {
      case CameraMode.mask:
        return masks;
        break;
      case CameraMode.effect:
        return effects;
        break;

      case CameraMode.filter:
        return filters;
        break;
      default:
        return masks;
    }
  }

  List masks = [
    "none",
    "assets/aviators",
    "assets/bigmouth",
    "assets/lion",
    "assets/dalmatian",
    "assets/bcgseg",
    "assets/look2",
    "assets/fatify",
    "assets/flowers",
    "assets/grumpycat",
    "assets/koala",
    "assets/mudmask",
    "assets/obama",
    "assets/pug",
    "assets/slash",
    "assets/sleepingmask",
    "assets/smallface",
    "assets/teddycigar",
    "assets/tripleface",
    "assets/twistedface",
  ];
  List effects = [
    "none",
    "assets/fire",
    "assets/heart",
    "assets/blizzard",
    "assets/rain",
  ];
  List filters = [
    "none",
    "assets/drawingmanga",
    "assets/sepia",
    "assets/bleachbypass",
    "assets/realvhs",
    "assets/filmcolorperfection"
  ];

  [@override](/user/override)
  void initState() {
    super.initState();
    CameraDeepArController.checkPermissions();
    deepArController.setEventHandler(DeepArEventHandler(
      onCameraReady: (v) {
        _platformVersion = "onCameraReady $v";
        setState(() {});
      },
      onSnapPhotoCompleted: (v) {
        _platformVersion = "onSnapPhotoCompleted $v";
        setState(() {});
      },
      onVideoRecordingComplete: (v) {
        _platformVersion = "onVideoRecordingComplete $v";
        setState(() {});
      },
      onSwitchEffect: (v) {
        _platformVersion = "onSwitchEffect $v";
        setState(() {});
      },
    ));
  }

  [@override](/user/override)
  void dispose() {
    deepArController?.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        appBar: AppBar(
          title: const Text('DeepAR Camera Example'),
        ),
        body: Stack(
          children: [
            DeepArPreview(deepArController),
            Align(
              alignment: Alignment.bottomCenter,
              child: Container(
                padding: EdgeInsets.all(20),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: [
                    Text(
                      'Response >>> : $_platformVersion\n',
                      textAlign: TextAlign.center,
                      style: TextStyle(fontSize: 14, color: Colors.white),
                    ),
                    SizedBox(
                      height: 20,
                    ),
                    Container(
                      child: Row(
                        children: [
                          Expanded(
                            child: FlatButton(
                              onPressed: () {
                                if (null == deepArController) return;
                                if (isRecording) return;
                                deepArController.snapPhoto();
                              },
                              child: Icon(Icons.camera_enhance_outlined),
                              color: Colors.white,
                              padding: EdgeInsets.all(15),
                            ),
                          ),
                          if (displayMode == DisplayMode.image)
                            Expanded(
                              child: FlatButton(
                                onPressed: () async {
                                  String path = "assets/testImage.png";
                                  final file = await deepArController.createFileFromAsset(path, "test");

                                  await Future.delayed(Duration(seconds: 1));

                                  deepArController.changeImage(file.path);
                                  print("DAMON - Calling Change Image Flutter");
                                },
                                child: Icon(Icons.image),
                                color: Colors.orange,
                                padding: EdgeInsets.all(15),
                              ),
                            ),
                          if (isRecording)
                            Expanded(
                              child: FlatButton(
                                onPressed: () {
                                  if (null == deepArController) return;
                                  deepArController.stopVideoRecording();
                                  isRecording = false;
                                  setState(() {});
                                },
                                child: Icon(Icons.videocam_off),
                                color: Colors.red,
                                padding: EdgeInsets.all(15),
                              ),
                            )
                          else
                            Expanded(
                              child: FlatButton(
                                onPressed: () {
                                  if (null == deepArController) return;
                                  deepArController.startVideoRecording();
                                  isRecording = true;
                                  setState(() {});
                                },
                                child: Icon(Icons.videocam),
                                color: Colors.green,
                                padding: EdgeInsets.all(15),
                              ),
                            ),
                        ],
                      ),
                    ),
                    SizedBox(
                      height: 10,
                    ),
                    SingleChildScrollView(
                      padding: EdgeInsets.all(15),
                      scrollDirection: Axis.horizontal,
                      child: Row(
                        children: List.generate(effectList.length, (p) {
                          bool active = currentEffect == p;
                          String imgPath = effectList[p];
                          return GestureDetector(
                            onTap: () async {
                              if (!deepArController.value.isInitialized) return;
                              currentEffect = p;
                              deepArController.switchEffect(cameraMode, imgPath);
                              setState(() {});
                            },
                            child: Container(
                              margin: EdgeInsets.all(6),
                              width: active ? 70 : 55,
                              height: active ? 70 : 55,
                              alignment: Alignment.center,
                              child: Text(
                                "$p",
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                    fontWeight: active ? FontWeight.bold : null,
                                    fontSize: active ? 16 : 14,
                                    color: active ? Colors.white : Colors.black),
                              ),
                              decoration: BoxDecoration(
                                  color: active ? Colors.orange : Colors.white,
                                  border: Border.all(
                                      color: active ? Colors.orange : Colors.white,
                                      width: active ? 2 : 0),
                                  shape: BoxShape.circle),
                            ),
                          );
                        }),
                      ),
                    ),
                    SizedBox(
                      height: 5,
                    ),
                    Row(
                      children: List.generate(CameraMode.values.length, (p) {
                        CameraMode mode = CameraMode.values[p];
                        bool active = cameraMode == mode;

                        return Expanded(
                          child: Container(
                            height: 40,
                            margin: EdgeInsets.all(2),
                            child: TextButton(
                              onPressed: () async {
                                cameraMode = mode;
                                setState(() {});
                              },
                              style: TextButton.styleFrom(
                                backgroundColor: Colors.black,
                                primary: Colors.black,
                              ),
                              child: Text(
                                describeEnum(mode),
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                    fontWeight: active ? FontWeight.bold : null,
                                    fontSize: active ? 16 : 14,
                                    color: Colors.white.withOpacity(active ? 1 : 0.6)),
                              ),
                            ),
                          ),
                        );
                      }),
                    ),
                    SizedBox(
                      height: 5,
                    ),
                    Row(
                      children: List.generate(DisplayMode.values.length, (p) {
                        DisplayMode mode = DisplayMode.values[p];
                        bool active = displayMode == mode;

                        return Expanded(
                          child: Container(
                            height: 40,
                            margin: EdgeInsets.all(2),
                            child: TextButton(
                              onPressed: () async {
                                displayMode = mode;
                                await deepArController.setDisplayMode(mode: mode);
                                setState(() {});
                              },
                              style: TextButton.styleFrom(
                                backgroundColor: Colors.purple,
                                primary: Colors.black,
                              ),
                              child: Text(
                                describeEnum(mode),
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                    fontWeight: active ? FontWeight.bold : null,
                                    fontSize: active ? 16 : 14,
                                    color: Colors.white.withOpacity(active ? 1 : 0.6)),
                              ),
                            ),
                          ),
                        );
                      }),
                    )
                  ],
                ),
              ),
            )
          ],
        ),
      ),
    );
  }

  static Future<File> _loadFile(String path, String name) async {
    final ByteData data = await rootBundle.load(path);
    Directory tempDir = await getTemporaryDirectory();
    File tempFile = File('${tempDir.path}/$name');
    await tempFile.writeAsBytes(data.buffer.asUint8List(), flush: true);
    return tempFile;
  }
}

更多关于Flutter增强现实相机插件camera_deep_ar的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter增强现实相机插件camera_deep_ar的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,camera_deep_ar 是一个用于增强现实(AR)功能的插件,它通常允许开发者在应用中集成实时面部识别和其他AR效果。尽管 camera_deep_ar 并不是 Flutter 官方提供的插件,且其具体实现和API可能因版本和第三方库而异,但我可以提供一个大致的代码框架,帮助你了解如何在 Flutter 项目中使用一个假想的 AR 相机插件。

请注意,由于我无法直接访问最新的 camera_deep_ar 插件(因为该名称可能不是官方或广泛认可的插件名称),以下代码将基于一个假设的 AR 插件 API 来进行演示。如果你使用的是特定的第三方库,请参考其官方文档进行相应调整。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加所需的依赖项。这里我们假设有一个名为 flutter_ar_camera 的插件(注意:这不是一个真实存在的插件名,你需要替换为实际使用的插件名):

dependencies:
  flutter:
    sdk: flutter
  flutter_ar_camera: ^x.y.z  # 替换为实际版本号

2. 导入插件

在你的 Dart 文件中导入插件:

import 'package:flutter_ar_camera/flutter_ar_camera.dart';

3. 使用 AR 相机

下面是一个基本的 Flutter 应用示例,它展示了如何使用一个假想的 AR 相机插件来显示相机预览并处理面部识别数据。

import 'package:flutter/material.dart';
import 'package:flutter_ar_camera/flutter_ar_camera.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter AR Camera Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ARCameraScreen(),
    );
  }
}

class ARCameraScreen extends StatefulWidget {
  @override
  _ARCameraScreenState createState() => _ARCameraScreenState();
}

class _ARCameraScreenState extends State<ARCameraScreen> {
  late ARCameraController _cameraController;

  @override
  void initState() {
    super.initState();
    _cameraController = ARCameraController();
    _cameraController.initialize().then((_) {
      if (!mounted) return;
      setState(() {});
    });
  }

  @override
  void dispose() {
    _cameraController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AR Camera Demo'),
      ),
      body: Center(
        child: _cameraController.value.isInitialized
            ? ARCameraPreview(_cameraController)
            : Container(
                child: CircularProgressIndicator(),
              ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 这里可以添加一些AR功能的触发逻辑,例如添加滤镜或识别面部
          _cameraController.startFaceRecognition();
        },
        tooltip: 'Start AR',
        child: Icon(Icons.camera_alt),
      ),
    );
  }
}

// 假设 ARCameraController 是一个控制AR相机功能的类
class ARCameraController {
  ValueNotifier<ARCameraValue> value = ValueNotifier(ARCameraValue());

  Future<void> initialize() async {
    // 初始化相机和AR功能
    // 这里应包含实际的初始化代码,例如请求相机权限,配置AR引擎等
    await Future.delayed(Duration(seconds: 2)); // 模拟异步初始化过程
    value.value = ARCameraValue(isInitialized: true);
  }

  void dispose() {
    // 释放资源
    value.dispose();
  }

  void startFaceRecognition() {
    // 开始面部识别
    // 这里应包含实际的面部识别逻辑,例如调用AR引擎的API
    print("Face Recognition Started");
  }
}

// 假设 ARCameraValue 是一个包含相机状态的类
class ARCameraValue {
  bool isInitialized = false;

  ARCameraValue({required this.isInitialized});
}

// 假设 ARCameraPreview 是一个显示相机预览的Widget
class ARCameraPreview extends StatelessWidget {
  final ARCameraController cameraController;

  ARCameraPreview(this.cameraController);

  @override
  Widget build(BuildContext context) {
    // 这里应包含实际的相机预览实现
    // 例如,使用 TextureView 或其他方式来显示相机画面
    return Container(
      color: Colors.grey, // 占位颜色
      child: Center(child: Text('Camera Preview')), // 占位文本
    );
  }
}

注意事项

  1. 权限管理:确保在 Android 和 iOS 平台上请求了必要的相机权限。
  2. 插件选择:使用真实存在的、经过验证的 AR 插件,如 flutter_arkit(仅限 iOS)或 arcore_flutter_plugin(仅限 Android),或者查找支持跨平台的 AR 插件。
  3. 文档阅读:仔细阅读所选插件的官方文档,以了解如何正确初始化和使用其 API。

以上代码是一个简化的示例,用于演示如何在 Flutter 应用中集成 AR 相机功能。实际项目中,你可能需要根据所选插件的 API 进行调整。

回到顶部