Flutter图像差异对比插件diff_image2的使用

发布于 1周前 作者 yibo5220 来自 Flutter

Flutter图像差异对比插件diff_image2的使用

diff_image2 是一个Dart包,用于获取两个具有相同宽度和高度的图像之间的百分比差异。它是 这个 项目的Dart版本,对可视化进行了改进,并且使用了Dart语言。

示例

简单用法示例

import 'package:diff_image2/diff_image.dart';
import 'package:image/image.dart';

final FIRST_IMAGE = 'https://seeklogo.com/images/F/flutter-logo-5086DD11C5-seeklogo.com.png';
final SECOND_IMAGE = 'https://seeklogo.com/images/A/android-western-logo-8F117A7F00-seeklogo.com.png';

void foo() async {
  try {
    var diff = await DiffImage.compareFromUrl(
      FIRST_IMAGE,
      SECOND_IMAGE,
    );
    print('The difference between images is: ${diff.value} %');
  } catch (e) {
    print(e);
  }
}

void goo(Image first, Image second) {
  try {
    var diff = DiffImage.compareFromMemory(
      first,
      second,
    );
    print('The difference between images is: ${diff.diffValue} %');
  } catch (e) {
    print(e);
  }
}

void main() {
  foo();
  /* These can be obtained with any method */
  Image first;
  Image second;
  // Here is possible to manipulate both images before passing them
  // to the function.
  goo(first, second);
}

更详细的示例

更详细的示例可以在 这里 找到。

功能

  1. 目前支持从URL、内存或存储中比较图像。

  2. compareFromUrl 的定义如下:

    static Future<DiffImgResult> compareFromUrl(
      dynamic firstImageSrc,
      dynamic secondImageSrc, {
      bool asPercentage = true,
      bool ignoreAlpha = true,
    }) async { ... }
    
  3. compareFromMemory 的定义如下:

    static DiffImgResult compareFromMemory(
      Image firstImage,
      Image secondImage, {
      bool asPercentage = true,
      bool ignoreAlpha = true,
    }) { ... }
    
  4. compareFromFile 的定义如下:

    static Future<DiffImgResult> compareFromFile(
      File firstImage,
      File secondImage, {
      bool asPercentage = true,
      bool ignoreAlpha = true,
    }) { ... }
    

    其中:

    • ignoreAlpha 允许决定是否在计算时考虑RGBA中的alpha通道。
    • asPercentage 设置输出格式(百分比或0-1之间)。

    这两种方法都返回一个 DiffImgResult,该模型包含两个元素:显示两个图像之间差异的图像和表示差异的数值(百分比或非百分比)。

  5. 一个名为 saveImage 的函数,用于保存显示 firstImagesecondImage 之间差异的png图像(目前不支持Dart Web)。

    static Future<File> saveImage({
      required Image image,
      required String name,
      String directory = '',
    }) { ... }
    

示例结果

第一张图像

Flutter Logo

第二张图像

Android Logo

差异百分比

  • 包含Alpha:35.67169421487167 %
  • 不包含Alpha:34.83905183744361 %

差异图像

DiffImg

建议和Bug

请在 问题跟踪器 中提交功能请求、建议和Bug。

运行示例

要运行示例,请执行以下命令:

pub run bin/main.dart

希望这些信息对你有帮助!如果你有任何问题或需要进一步的帮助,请随时提问。


更多关于Flutter图像差异对比插件diff_image2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter图像差异对比插件diff_image2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用diff_image2插件进行图像差异对比的示例代码。diff_image2插件允许你比较两张图像并显示它们之间的差异。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加diff_image2依赖:

dependencies:
  flutter:
    sdk: flutter
  diff_image2: ^x.y.z  # 请将x.y.z替换为最新版本号

然后运行flutter pub get来安装依赖。

2. 导入插件

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

import 'package:diff_image2/diff_image2.dart';

3. 使用插件

以下是一个完整的示例,展示了如何加载两张图像并使用diff_image2进行比较:

import 'package:flutter/material.dart';
import 'package:diff_image2/diff_image2.dart';
import 'dart:ui' as ui;
import 'dart:typed_data';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Image Diff Example'),
        ),
        body: ImageDiffScreen(),
      ),
    );
  }
}

class ImageDiffScreen extends StatefulWidget {
  @override
  _ImageDiffScreenState createState() => _ImageDiffScreenState();
}

class _ImageDiffScreenState extends State<ImageDiffScreen> {
  Uint8List? image1Bytes;
  Uint8List? image2Bytes;
  ui.Image? diffImage;

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

  Future<void> loadImages() async {
    // 加载第一张图像
    image1Bytes = await rootBundle.load('assets/image1.png');

    // 加载第二张图像
    image2Bytes = await rootBundle.load('assets/image2.png');

    // 将图像解码为ui.Image
    ui.Codec codec1 = await ui.instantiateImageCodec(image1Bytes!);
    ui.FrameInfo frameInfo1 = await codec1.getNextFrame();
    ui.Image image1 = frameInfo1.image;

    ui.Codec codec2 = await ui.instantiateImageCodec(image2Bytes!);
    ui.FrameInfo frameInfo2 = await codec2.getNextFrame();
    ui.Image image2 = frameInfo2.image;

    // 进行图像差异对比
    diffImage = await compute(diffImages, image1, image2);

    // 更新状态
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          if (diffImage != null)
            Image.fromImage(diffImage!, fit: BoxFit.cover, width: 300, height: 300),
          else
            CircularProgressIndicator(),
        ],
      ),
    );
  }
}

// 差异对比函数,使用compute进行异步计算
Future<ui.Image?> diffImages(ui.Image image1, ui.Image image2) async {
  final width = image1.width;
  final height = image1.height;
  final Uint32List pixels1 = await image1.toRaster().toUint32List();
  final Uint32List pixels2 = await image2.toRaster().toUint32List();

  final Uint8List diffPixels = Uint8List(width * height * 4);

  for (int i = 0; i < width * height; i++) {
    int pixel1 = pixels1[i];
    int pixel2 = pixels2[i];

    int r1 = (pixel1 >> 16) & 0xFF;
    int g1 = (pixel1 >> 8) & 0xFF;
    int b1 = pixel1 & 0xFF;

    int r2 = (pixel2 >> 16) & 0xFF;
    int g2 = (pixel2 >> 8) & 0xFF;
    int b2 = pixel2 & 0xFF;

    int dr = (r1 - r2).abs();
    int dg = (g1 - g2).abs();
    int db = (b1 - b2).abs();

    // 简单的差异计算,可以根据需要调整
    int alpha = (dr + dg + db) > 50 ? 255 : 0;

    diffPixels[i * 4] = alpha;
    diffPixels[i * 4 + 1] = 255; // Red channel for visualization
    diffPixels[i * 4 + 2] = 0;   // Green channel for visualization
    diffPixels[i * 4 + 3] = 0;   // Blue channel for visualization
  }

  final Uint8List rgbaBytes = Uint8List.fromList([
    width.toByte(),
    height.toByte(),
    ...Uint8List.fromList(List.filled(width * height * 4, 0)), // Placeholder for image data
  ]);

  rgbaBytes.setAll(2, diffPixels);

  final ByteData byteData = rgbaBytes.buffer.asByteData();
  final ui.Image diffImage = await ui.decodeImageFromData(byteData, width, height);

  return diffImage;
}

注意事项

  1. 图像资源:确保你的assets文件夹中包含image1.pngimage2.png两张图像,并在pubspec.yaml中声明它们:

    flutter:
      assets:
        - assets/image1.png
        - assets/image2.png
    
  2. 差异计算:上述示例中的差异计算非常基础,仅根据RGB值的差异设置透明度。你可以根据需要调整差异计算的逻辑。

  3. 性能:对于大图像或高分辨率图像,差异对比可能会消耗较多资源,可以考虑在后台线程或compute函数中进行处理。

希望这个示例能帮助你理解如何在Flutter项目中使用diff_image2插件进行图像差异对比。

回到顶部