ML Kit:通过Mendix 集成人脸识别算法

news2024/11/27 1:45:57

预训练模型是一种已经使用训练数据集进行训练并包含执行模型所需所有参数的机器学习模型。这类模型常用于计算机视觉领域,比如可以在Mendix Studio Pro中导入ONNX模型后,可以在微流程中执行该模型。

image.png

本文讲述如何在Mendix应用程序中集成特定的人脸检测模型。其中一个重要步骤是添加所需的预处理和后处理步骤,并以Java代码形式实现。这里提供了详细的Java代码示例:Mendix ML Kit Demo

Face Detection model

我们想要使用的ML模型是ONNX模型库中的一个轻量级人脸检测模型。这里有两个模型可供选择,它们在输入分辨率上有所不同。我们选择了RFB-640模型,它需要一个分辨率为640x480像素的RGB图像。该模型的输出是两个列表,包含了边界框和相应的得分。一个边界框由其左侧、顶部、右侧和底部的边界位置定义。

在Mendix中映射模型

在Mendix文档中已经很好地描述了导入和调用ONNX ML模型的几个简单步骤。面部识别模型为调用模型生成了以下输入和输出映射。

image.png

为了在Mendix中调用模型,我们创建一个输入实体的实例,并将其传递给Call ML model 的微流组件。

image.png

如我们所见,这里的输入和输出数据需要一种特殊格式。为了转换这些数据,需要进行一些预处理和后处理。

预处理和后处理

对于这个特定问题,Mendix中没有标准的处理方法。因此,这里的处理是通过两个Java动作完成的,这些动作完成了大部分工作。

image.png

映射输入数据

图像必须以包含形状为[1,3,480,640]的张量的二进制数据传递。您可以在这里了解更多关于张量和形状的信息:TensorFlow Core中的张量简介

要运行模型,需要进行以下步骤:

  • 将输入图像缩放到640x480像素的RGB格式。
  • 将图像转换为具有匹配形状和标准化值的矩阵。
  • 将矩阵编码成可以传递给ML模型的格式。

图像读取和缩放

为了缩放图像,我们将使用OpenCV库及其Java封装。由于OpenCV需要本地库,我们将遵循与Mendix ML学习套件相同的方法,使用打包有本地库的库。

在我们可以使用任何OpenCV功能之前,我们需要加载共享库。这可以在静态代码段中完成。

// BEGIN EXTRA CODE
static {
  nu.pattern.OpenCV.loadShared(); //OpenCV initialization
}

我们可以读取输入图像并使用OpenCV的resize方法进行转换。

// read the image into a matrix
InputStream istream = com.mendix.core.Core.getFileDocumentContent(getContext(), sourceImage.getMendixObject());
MatOfByte matOfByte = new MatOfByte(istream.readAllBytes());
Mat sourceImage = Imgcodecs.imdecode(matOfByte, Imgcodecs.IMREAD_COLOR);

// resize the image to the target size
Mat rim = new Mat();
Imgproc.resize(sourceImage, rim, new Size(640,480));

将图像转换为矩阵

下一步是将图像转换为矩阵并标准化值。人脸检测模型期望输入数据缩放到[-1;1]的范围。这种转换可以使用以下代码完成。

float[][][][] inputArray = new float[1][3][480][640];
for(int i = 0; i < 480; i++) {
 for(int j = 0; j < 640; j++) {
  for(int k = 0; k <= 2; k++) {
   double[] rawValue = rim.get(i, j);
   float normalizedValue = ((float) (rawValue[Math.abs(k - 2)] - 127) / 128);
   inputArray[0][k][i][j] = normalizedValue;
  }
 }
}

为处理编码矩阵

现在必须将结果的inputArray矩阵传递给模型。Mendix ML Kit已经提供了一些辅助函数,用于对这些数据进行base64编码。这个Java动作的结果被写入模型的输入对象。

InputStream is = MLKit.toInputStream(inputArray);
String base64data = MLKit.toBase64(is);

映射输出数据(后处理)

模型生成了两个多维矩阵(得分和边界框),它们以base64编码的二进制形式。为了处理这些输出,我们使用一个后处理Java动作。对于解码原始数据,我们可以再次使用MLKit的辅助函数。

float[][][] _box = new float[1][17640][4];
InputStream isb = MLKit.fromBase64(rfb640Output.getBoxes());
MLKit.toArray(isb, _box);

对于解码计算出的得分,使用相同的代码。输出数据的形状是[1,17640,4]。这意味着模型总是生成17640个潜在面孔的候选者。为了识别最终的检测到的面孔列表,需要进行一些额外的过滤,这不是模型本身完成的。

过滤模型输出

后处理包括两个步骤。第一步是根据它们的得分过滤结果,并将候选者限制在较小的集合中。sortedCandidateIdx的结果是指向候选者的一组索引。

List<Integer> sortedCandidateIdx = IntStream.range(0, 17640)
.filter(idx -> score[idx][1] > detectionThreshold)
.boxed().sorted(new Comparator<Integer>() {
    @Override
    public int compare(Integer idx1, Integer idx2) {
    return Float.compare(score[idx2][1] ,score[idx1][1]);
  }
}).limit(candidates).collect(Collectors.toList());

得分是指定框中含有面孔的可能性的指示器。这些候选者现在是输入图像中检测到的面孔的有效检测。然而,这些框将有显著的重叠。

image.png

如果您不加过滤地使用这些数据,就会有多个框指示图像同一区域中检测到的面孔,如上所示。作为最终输出,我们希望每个面孔有一个单独的框。

非最大抑制

用于过滤这些框的方法称为非最大抑制(NMS),它使用IoU(交集与并集的比率)来确定重叠的框。这个过程的Java等效代码如下:

for (Integer idx1 : sortedCandidateIdx) {
  if (!finalCandidates.isEmpty()) {
    boolean hasIoUAboveThreshold = false;
    for (Integer idx2 : finalCandidates) {
      float l = Math.min(box[idx1][0], box[idx2][0]);
      float t = Math.min(box[idx1][1], box[idx2][1]);
      float r = Math.max(box[idx1][2], box[idx2][2]);
      float b = Math.max(box[idx1][3], box[idx2][3]);
      if (l>=r || t>=b) continue;
      
      float intersection = (r-l)*(b-t);
      float area1 = (box[idx1][2]-box[idx1][0])*(box[idx1][3]-box[idx1][1]);
      float area2 = (box[idx2][2]-box[idx2][0])*(box[idx2][3]-box[idx2][1]);
      
      float iou = intersection / (area1 + area2 - intersection + 0.0000001f);
      if (iou<iouThreshold) continue;
      hasIoUAboveThreshold=true;
      break;
    }
    if (hasIoUAboveThreshold) continue;
  }
  finalCandidates.add(idx1);
}

采用此方法,最终的候选者现在清晰地分隔成4个不同的部分。

image.png

使用结果数据

此时的实际结果数据仍然是一组在归一化空间[0,1]x[0,1]中的框坐标。我们可以使用OpenCV的方法将结果绘制到源图像上,如这里所示,或者我们可以将信息传递给任何连续的过程。

for (Integer idx : finalCandidates) {
  Rect rec = new Rect(new Point(box[idx][0] * width, box[idx][1] * height), new Point(box[idx][2] * width, box[idx][3] * height));
  Imgproc.rectangle(sourceImage, rec, color, linethickness);   
};

结论

通过Mendix ML工具包,导入和运行预训练的ONNX模型变得更加简单。Mendix为映射输入和输出数据到实际模型提供了我们已经习惯的接口类型。

您仍然需要数据预处理和后处理的专业知识。其中一些步骤在类似问题中是通用的,很有可能会有更多可以直接使用的方法。

所需的一些操作是挑战性的,但模型的集成到平台中使得快速进展和在几天内获得工作解决方案变得容易。

参考资料

1. Using ML Kit

2. Mendix ML Kit Demo

3. OpenCV modules

4. GitHub - OpenCV

关于Mendix

作为西门子Xcelerator平台的低代码引擎,Mendix正在迅速成为推动企业数字化发展的首选应用程序开发平台。Mendix让企业能够以前所未有的速度构建应用程序、促进IT团队与业务专家之间开展有意义的协作,并帮助IT团队保持对整个应用程序环境的控制。作为一直被领先的行业分析师视为“领军者和远见者”的低代码平台,Mendix是云原生的、开放的、可扩展的、敏捷的,并且经过实践验证。从人工智能和增强现实,到智能自动化和原生移动,Mendix和西门子Xcelerator已成为“数字优先”企业的中坚力量。Mendix已被46个国家的4,000多家企业采用,并建立了由30多万名开发人员组成的活跃社区,这些开发人员使用该平台创建了20多万款应用程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1578322.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

fakebook-攻防世界

题目 先目录扫描一下 dirseach 打开flag.php是空白的 访问robots.txt,访问user.php.bak <?php class UserInfo { public $name ""; public $age 0; public $blog ""; public function __construct($name, $age, $blog) { …

缓存雪崩以及解决思路

缓存雪崩&#xff1a;缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机&#xff0c;导致大量请求到达数据库&#xff0c;带来巨大压力。 解决方案&#xff1a; 给不同的Key的TTL添加随机值 利用Redis集群提高服务的可用性 给缓存业务添加降级限流策略 给业务…

6.10物联网RK3399项目开发实录-驱动开发之SPI接口的使用(wulianjishu666)

嵌入式实战开发例程&#xff0c;珍贵资料&#xff0c;开发必备&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1149x7q_Yg6Zb3HN6gBBAVA?pwdhs8b SPI 使用 SPI 简介 SPI 是一种高速的&#xff0c;全双工&#xff0c;同步串行通信接口&#xff0c;用于连接微控制器、…

【CTF】rip--堆栈的简单认识

前言 最近在学二进制&#xff0c;准备拿BUUCTF的pwn试试手&#xff0c;还在摸索的阶段&#xff0c;有什么思路出错的地方还请指出。 解题思路 下载文件到kali&#xff0c;查看文件为 64-bit的ELF&#xff08;ELF为Linux下的可执行文件&#xff0c;相当于Windows的exe&#xff0…

ES6-数组、对象、函数扩展、Symbol

01- let声明变量 块级作用域 var是全局变量&#xff0c;let只作用于块级作用域内 每一次都是让一个新的i的值没有被释放掉不允许重复声明变量不提升&#xff08;声明没有提前&#xff09;暂存性死区不与顶层对象挂钩 02-const常量 常量必须初始化&#xff0c;初始化以后就不…

Linux addr2line介绍

打开linux调试选项 嵌入式 linux 经常要编译 linux 内核&#xff0c;默认情况下编译出的内核镜像是不带调试信息的&#xff0c;这样&#xff0c;当内核 crash 打印 PC 指针和堆栈信息时&#xff0c;我们需要反汇编来确认出错位置&#xff0c;不直观。 如果内核开启了调试选项&…

HarmonyOS实战开发-如何实现跨应用数据共享实例。

介绍 本示例实现了一个跨应用数据共享实例&#xff0c;分为联系人&#xff08;数据提供方&#xff09;和联系人助手&#xff08;数据使用方&#xff09;两部分&#xff1a;联系人支持联系人数据的增、删、改、查等功能&#xff1b;联系人助手支持同步联系人数据&#xff0c;当…

动态支付策略:Go 语言中策略模式的妙用

关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等&#xff0c;您的关注将是我的更新动力&#xff01; 在现代软件架构中&#xff0c;支付功能是不可或缺的一环。无论是在线购物还是虚拟服务&#xff0c;支付策略的选择直接影响用户体…

GitHub教程:最新如何从GitHub上下载文件(下载单个文件或者下载整个项目文件)之详细步骤讲解(图文教程)

&#x1f42f; GitHub教程&#xff1a;最新如何从GitHub上下载文件(下载单个文件或者下载整个项目文件)之详细步骤讲解(图文教程) &#x1f4c1; 文章目录 &#x1f42f; GitHub教程&#xff1a;最新如何从GitHub上下载文件(下载单个文件或者下载整个项目文件)之详细步骤讲解(图…

Android Framework学习笔记(2)----系统启动

Android系统的启动流程 启动过程中&#xff0c;用户可控部分是framework的init流程。init是系统中的第一个进程&#xff0c;其它进程都是它的子进程。 启动逻辑源码参照&#xff1a;system/core/init/main.cpp 关键调用顺序&#xff1a;main->FirstStageMain->SetupSel…

AI“复活”:慰藉心灵还是触碰禁忌?一文看懂技术与伦理的较量|TodayAI

随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;其应用领域也越来越广泛&#xff0c;不仅仅局限于数据分析、机器人自动化等传统领域&#xff0c;更是延伸到了一些人们曾经认为只存在于科幻小说中的领域。近年来&#xff0c;使用AI技术“复活”逝者的概念&a…

免费云服务器汇总,最长永久免费使用

随着云计算技术的快速发展&#xff0c;越来越多的企业和个人开始将业务迁移到云端。云服务器作为云计算的重要组成部分&#xff0c;以其灵活、高效、可扩展等特点受到广泛关注。然而&#xff0c;许多人在初次接触云服务器时&#xff0c;可能会对高昂的价格望而却步。为了帮助大…

替换空格(替换特定字符)

&#x1f600;前言 在字符串处理中&#xff0c;经常会遇到需要替换特定字符的情况。本文将介绍一道经典的字符串替换问题&#xff1a;将字符串中的空格替换成 “%20”。我们将探讨一种高效的解决方法&#xff0c;通过倒序遍历字符串来实现原地替换&#xff0c;避免额外空间的开…

电网的正序参数和等值电路(三)

本篇为本科课程《电力系统稳态分析》的笔记。 本篇这一章的第三篇笔记。上一篇传送门。 标幺制和电网等值电路 标幺制 标幺值的定义 标幺值是一种相对值&#xff0c;是某种物理量的有名值和所选定的与有名值同单位的基准值之比&#xff0c;即&#xff1a; 标幺值 有名值…

第四百四十八回

文章目录 1. 知识回顾2. 使用方法3. 代码与功能3.1 示例代码3.2 功能说明 4. 内容总结 我们在上一章回中介绍了"overlay_tooltip简介"相关的内容&#xff0c;本章回中将介绍OverlayTooltip用法.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 知识回顾 我们在上…

Mysql底层原理五:如何设计、用好索引

1.索引的代价 空间上的代价 时间上的代价 每次对表中的数据进⾏增、删、改操作时&#xff0c;都需要去修改各个B树索引。⽽且我们讲过&#xff0c;B树每层节点都是按照索引列的值从⼩到⼤的顺序排序⽽组成了双 向链表。不论是叶⼦节点中的记录&#xff0c;还是内节点中的记录&a…

Win10下VirtualBox启动任何一个虚拟机马上出现蓝屏死机(终止代码:SYSTEM_SERVICE_EXCEPTION)

环境: Win10专业版 VirtualBox5.1.28 问题描述: Win10下VirtualBox启动任何一个虚拟机马上出现蓝屏死机(终止代码:SYSTEM_SERVICE_EXCEPTION),之前都一直没问题 检查下面功能是否开启 已启用 Credential Guard/Device Guard。 已启用 Windows 沙箱 已启用虚拟机平台…

二维码门楼牌管理应用平台:实现精细化、智能化场所管理

文章目录 前言一、二维码门楼牌管理应用平台的构建二、场所任务的精细化管理三、消防检查与整改的智能化管理四、二手交易登记的便捷化管理五、未来展望 前言 随着城市管理的日益精细化&#xff0c;二维码门楼牌管理应用平台应运而生。通过这一平台&#xff0c;场所负责人可以…

2024-04-08 NO.6 Quest3 自定义交互事件

文章目录 1 交互事件——更改 Cube 颜色2 交互事件——创建 Cube2.1 非代码方式2.2 代码方式 ​ 在开始操作前&#xff0c;我们导入上次操作的场景&#xff0c;相关介绍在 《2024-04-08 NO.5 Quest3 手势追踪进行 UI 交互-CSDN博客》 文章中。 1 交互事件——更改 Cube 颜色 …

知识管理系统|基于Springboot和vue的知识管理系统设计与实现(源码+数据库+文档)

知识管理 目录 基于Springboot和vue的知识管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、前台&#xff1a; 5.2.2 文章信息 5.3.1 论坛交流 2、后台 用户管理 5.1.2 文章分类 5.2.1 资料分类 四、数据库设计 五、核心代码 六、论文参考 七、最…