使用相机包更改颤振中实时相机的色调和饱和度

问题描述 投票:0回答:1

使用相机包更改颤振中实时相机的色调和饱和度 我开发了带有相机包的 flutter 应用程序,可以预览实时相机并录制视频或拍摄照片并保存。我想更改预览的颜色和饱和度并将其应用于视频和相机。我怎样才能做到这一点/。

没有发现改变色调和饱和度

android ios flutter camera flutter-camera
1个回答
0
投票

这将必须是一个两步过程,除非您想重写相机包的部分内容。您可能能够从相机获取帧并直接处理它们,但我的猜测是,在 dart 中不可能在不出现重大性能问题的情况下做到这一点。

相反,第一步是实时更改预览以显示色调+饱和度变化。为此,您可以使用

ColorFilter
小部件来包装预览小部件。您将需要设置这些 ColorFilters 来执行您想要的操作;我建议您查看 Color Filter Generator pub 包,其中包含一系列不同矩阵的数学运算,包括色调、饱和度、亮度。

这是一个示例 - 您可以粘贴到 dartpad.dev 中查看它的外观。但要点是我使用

hueMatrix
saturationMatrix
方法来生成矩阵,然后将其传递给 ImageFilter 对象。如果您愿意,您甚至可以将hueMatrix 和saturationMatrix 合并为一个函数,但我将把它作为练习留给您完成。在示例中,我将过滤器应用于文本,但它对于相机预览应该同样有效。

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

// from https://github.com/hsbijarniya/colorfilter_generator
List<double> hueMatrix(double value) {
  value = value * pi;

  if (value == 0) {
    return [
      1,
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1,
      0,
    ];
  }

  var cosVal = cos(value);
  var sinVal = sin(value);
  var lumR = 0.213;
  var lumG = 0.715;
  var lumB = 0.072;

  return List<double>.from(<double>[
    (lumR + (cosVal * (1 - lumR))) + (sinVal * (-lumR)),
    (lumG + (cosVal * (-lumG))) + (sinVal * (-lumG)),
    (lumB + (cosVal * (-lumB))) + (sinVal * (1 - lumB)),
    0,
    0,
    (lumR + (cosVal * (-lumR))) + (sinVal * 0.143),
    (lumG + (cosVal * (1 - lumG))) + (sinVal * 0.14),
    (lumB + (cosVal * (-lumB))) + (sinVal * (-0.283)),
    0,
    0,
    (lumR + (cosVal * (-lumR))) + (sinVal * (-(1 - lumR))),
    (lumG + (cosVal * (-lumG))) + (sinVal * lumG),
    (lumB + (cosVal * (1 - lumB))) + (sinVal * lumB),
    0,
    0,
    0,
    0,
    0,
    1,
    0,
  ]).map((i) => i.toDouble()).toList();
}

// from https://github.com/hsbijarniya/colorfilter_generator
List<double> saturationMatrix(double value) {
  value = value * 100;

  if (value == 0) {
    return [
      1,
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1,
      0,
    ];
  }

  var x =
      ((1 + ((value > 0) ? ((3 * value) / 100) : (value / 100)))).toDouble();
  var lumR = 0.3086;
  var lumG = 0.6094;
  var lumB = 0.082;

  return List<double>.from(<double>[
    (lumR * (1 - x)) + x,
    lumG * (1 - x),
    lumB * (1 - x),
    0,
    0,
    lumR * (1 - x),
    (lumG * (1 - x)) + x,
    lumB * (1 - x),
    0,
    0,
    lumR * (1 - x),
    lumG * (1 - x),
    (lumB * (1 - x)) + x,
    0,
    0,
    0,
    0,
    0,
    1,
    0,
  ]).map((i) => i.toDouble()).toList();
}

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

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

class _MyAppState extends State<MyApp> {
  double hue = 0;
  double saturation = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            MyWidget(hue: hue, saturation: saturation),
            Text("Hue:"),
            Slider(
              value: hue / 2 + .5,
              onChanged: (val) => setState(() => hue = val * 2 - 1),
            ),
            Text("Saturation:"),
            Slider(
              value: saturation / 2 + .5,
              onChanged: (val) => setState(() => saturation = val * 2 - 1),
            )
          ],
        ),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  final double hue;
  final double saturation;

  const MyWidget({super.key, required this.hue, required this.saturation});

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return ColorFiltered(
      colorFilter: ColorFilter.matrix(hueMatrix(hue)),
      child: ColorFiltered(
        colorFilter: ColorFilter.matrix(
          saturationMatrix(saturation),
        ),
        child: Text(
          'Hello, World!',
          style: theme.textTheme.headlineMedium!
              .copyWith(color: theme.primaryColor),
        ),
      ),
    );
  }
}

这满足了你问题的第一部分;您现在可以预览显示视频的饱和度、色调或其他应用的内容。


第二部分将更加依赖于许多其他因素,例如您正在录制的格式、您正在对视频执行的操作等。但基本上,一旦您在相机上调用 stopVideoRecording ,您就会将获得一个包含视频数据的 XFile 对象。如果你拍照的话应该是类似的。

您也许可以使用

tapioca
等视频插件来编辑该文件以添加正确的色调,但我感觉它没有足够的功能。如果是这种情况,您可能需要包含一些第三方 android 特定的(以及 iOS 特定的,如果您正在使用它)包,然后从 flutter 调用它们来编辑实际的色调和饱和度以及其他任何内容视频文件,然后等待其处理,然后执行您要对该文件执行的任何其他操作。

对于图像,您将有一个类似的过程,只不过它可能会更容易,因为有更多可用的插件,并且可能能够为您进行照片处理 - 图像编辑器可能会解决这个问题,因为它似乎支持应用颜色矩阵。

© www.soinside.com 2019 - 2024. All rights reserved.