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

预训练模型是一种已经使用训练数据集进行训练并包含执行模型所需所有参数的机器学习模型。这类模型常用于计算机视觉领域,比如可以在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多万款应用程序。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

短视频培训要多少钱?

在互联网时代&#xff0c;短视频已经成为一种流行的传播方式&#xff0c;不仅可以记录生活的美好瞬间&#xff0c;还可以作为一种职业技能&#xff0c;帮助个人或企业实现品牌推广和商业变现。因此&#xff0c;越来越多的人开始关注短视频制作培训&#xff0c;希望通过专业的学…

SQL语言自用(持续更新)(带例子)

目录 基础知识数据定义数据查询单表查询连接查询嵌套查询集合运算 实验例子数据定义数据查询单表查询查询的目标表达式为所有列、指定的列或指定的列的运算三种不同。使用DISTINCT保留字消除重复行。对查询结果排序和分组。集合分组使用集函数进行各项统计。 连接查询笛卡儿连接…

【QT入门】 Qt自定义控件与样式设计之QComboBox样式表介绍

往期回顾 【QT入门】 Qt自定义控件与样式设计之QLineEdit的qss使用-CSDN博客 【QT入门】Qt自定义控件与样式设计之QPushButton常用qss-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QPushButton实现鼠标悬浮按钮弹出对话框-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QComb…

LabVIEW和2D激光扫描的受电弓滑板磨耗精确测量

LabVIEW和2D激光扫描的受电弓滑板磨耗精确测量 在电气化铁路运输中&#xff0c;受电弓滑板的健康状况对于保障列车安全行驶至关重要。受电弓滑板作为连接电网与列车的直接介质&#xff0c;其磨损情况直接影响到电能的有效传输及列车的稳定运行。精确、快速测量受电弓滑板磨损情…

天池医疗AI大赛[第一季] Rank5解决方案

一、赛题说明 数据格式 本次大赛数据集包含数千份高危患者的低剂量肺部CT影像&#xff08;mhd格式&#xff09;数据&#xff0c;每个影像包含一系列胸腔的多个轴向切片。每个影像包含的切片数量会随着扫描机器、扫描层厚和患者的不同而有差异。原始图像为三维图像。这个三维图…

力扣经典150题(1)

文章目录 6.Z字形变换82.删除排序链表中的重复元素||61.旋转链表100.相同的树 6.Z字形变换 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时&#xff0c;排列如下&#xff1…

【讲解如何OpenCV入门】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

数据库之DQL操作(数据查询语言)

DQL英文全称是Data Query Language(数据查询语言)&#xff0c;数据查询语言&#xff0c;用来查询数据库中表的记录。查询关键字: SELECT。 本节介绍以下表为例&#xff1a; create table emp(id int comment 编号&#xff0c;workno varchar(10) comment 工号&#xff0c;nam…

基于SpringBoot+MyBatis-Plus的代码生成器

一、功能说明 数据源管理&#xff1a;实现多个数据库的表代码生成表管理&#xff1a;从数据源导入表&#xff0c;配置表和字段默认配置&#xff1a;配置项目默认信息&#xff0c;配置字段数据类型映射操作日志 功能截图 二、代码实现 基于velocity-engine模板代码生成 pack…

工单管理系统设计方案,工单系统的流程

工单管理系统是一种用于管理和跟踪工作流程的软件系统。它可以帮助企业和组织更好地分配任务、优化工作流程、提高生产效率和客户满意度。下面是一个基本的工单管理系统设计方案&#xff1a;需求分析  在设计工单管理系统之前&#xff0c;需要进行需求分析&#xff0c;确定系…

三极管原理特性介绍,课堂上可不这么讲!

原文来自微信公众号&#xff1a;工程师看海&#xff0c;与我联系&#xff1a;chunhou0820 看海原创视频教程&#xff1a;《运放秘籍》 大家好&#xff0c;我是工程师看海&#xff0c;原创文章欢迎点赞分享&#xff01; 今天介绍下三极管的特性&#xff0c;清晰易懂&#xff0c…

C语言进阶课程学习记录-第27课 - 数组的本质分析

C语言进阶课程学习记录-第27课 - 数组的本质分析 数组实验-数组元素个数的指定实验-数组地址与数组首元素地址实验-指针与数组地址的区别小结 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学习记录 数组 实验-数…

Ubuntu 22上安装Anaconda3。下载、安装、验证详细教程

在Ubuntu 22上安装Anaconda3&#xff0c;你可以遵循以下步骤&#xff1a; 更新系统存储库&#xff1a; 打开终端并运行以下命令来更新系统存储库&#xff1a; sudo apt update安装curl包&#xff1a; 下载Anaconda安装脚本通常需要使用curl工具。如果系统中没有安装curl&#x…

如何提升产品用户体验?4个工具+6张案例,让你快速吃透!

在数字时代的浪潮中&#xff0c;产品用户体验早已不再是简单的“好用”或“不好用”的评判标准&#xff0c;它不仅仅是功能的堆砌&#xff0c;更是情感的连接、智慧的体现。在这个竞争激烈的市场中&#xff0c;只有那些能够深入理解用户需求、精准把握用户心理的产品&#xff0…

HarmonyOS 开发-应用新功能引导实现案例

介绍 本文介绍如何使用high_light_guide三方库完成应用新版本功能导航。通过高亮区域与蒙版背景的明暗度对比&#xff0c;让用户快速锁定重点功能&#xff0c;了解版本变更和业务入口。 效果图预览 使用说明 点击页面上对应按钮或空白区域进入下一个提示&#xff0c;直至提示…

MiniApp SDK 是什么?

介绍 MiniApp SDK 是提供开发、部署、产品体验分析、上线全流程各种需求的解决方案。接入此 SDK&#xff0c;您就可以只关注于代码开发本身&#xff0c;剩余的所有事情都可以交由 SDK 及其依赖方解决。另外&#xff0c;能够有效降低多端开发的技术门槛和研发成本&#xff0c;提…

一篇文章学会进程替换

进程替换是什么 fork之后&#xff0c;父子进程各自执行父进程的代码的一部分&#xff0c;父子代码共享&#xff0c;数据写时拷贝各自一份。 但是&#xff0c;如果子进程不想执行父进程的代码&#xff0c;就想执行一个全新的代码呢&#xff1f; 这就需要用到 进程程序替换 所谓的…

MybatisPlus分页插件的使用

目录 &#x1f9c2;1.添加mybatisPlus依赖 &#x1f953;2.添加配置类 &#x1f32d;3.添加分页接口 &#x1f37f;4. 添加实现类 &#x1f95e;5.测试 1.添加mybatisPlus依赖 <!--mybatisPlus--><dependency><groupId>com.baomidou</groupId>&l…

linux中查看占用端口的进程方法

1、netstat -tlnp | grep 端口号 netstat -tlnp|grep 3306 其中&#xff1a;95115是进程号&#xff0c;mysqld是进程名称 2、ss -ltnp | grep 端口号 注意&#xff1a;-tlnp和-ltnp ss -ltnp|grep 3306其中&#xff1a;mysqld是进程名称&#xff0c;95115是进程id 3、lsof…

【Python 基础知识课程】Python的第一个程序

Python 简介 Python 是一种功能强大且用途广泛的编程语言&#xff0c;广泛用于数据科学、Web 开发、自动化等高需求领域。 幸运的是&#xff0c;对于初学者来说&#xff0c;它也是一种很好的学习语言&#xff0c;因为Python代码更容易阅读和编写。它的简单性使其成为初学者的完…