实用指南:计算机视觉:基于YOLOv11 实例分割与OpenCV 在 Java 中的实现图像实例分割

news/2025/9/24 8:42:15/文章来源:https://www.cnblogs.com/ljbguanli/p/19108520

实用指南:计算机视觉:基于YOLOv11 实例分割与OpenCV 在 Java 中的实现图像实例分割

什么是实例分割

实例分割比目标检测更进一步,涉及识别图像中的单个对象并将其从图像其余部分中分割出来。

YOLO模型简介

YOLO(You Only Look Once)是最著名的目标检测系统之一。它具有极高的速度和准确性,是入门目标检测最便捷的途径之一。其文档极其完善,通过大量示例进行了详尽说明。它还拥有庞大的研究人员、开发者和爱好者社区,分享各种改进并为项目做出贡献。

Python中的YOLO使用示例

通过Python开始使用YOLO的集成过程非常顺畅,其快速开始实例分割实验的能力令人印象深刻。推理过程仅需4行代码即可完成:

from ultralytics import YOLO
# 加载YOLOv11模型
model = YOLO("yolo11n-seg.pt")
# 运行预测
results = model.predict('/path/to/image.jpg')
# 显示结果
results[0].show()

运行结果示例:
在这里插入图片描述

在这里插入图片描述

Java中集成YOLOv11的步骤

1. 项目配置

作为一名Java开发者,在简单的Java项目中尝试此功能的过程并不那么直接。特别是理解推理输出的后处理需要花费大量时间。

首先需要创建一个简单的Java Gradle或Maven项目,并添加OpenCV依赖:

Gradle配置(build.gradle)
plugins {
// 应用application插件以支持构建Java CLI应用程序
id 'application'
}
repositories {
// 使用Maven Central解析依赖
mavenCentral()
}
dependencies {
implementation 'org.openpnp:opencv:4.9.0-0'
...
Maven配置(pom.xml)
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-0</version>
</dependency>

2. 基础设置

在进入分割部分之前,先进行一些基础设置。使用OpenCV读取和显示图像,以确保配置正确。加载OpenCV库,从资源文件夹读取图像(示例中使用单张图像bike.jpg),并使用OpenCV HighGui显示:

package org.tutorial;
import nu.pattern.OpenCV;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
public class InstanceSegmentation
{
private static final String IMAGE_NAME = "bike.jpg";
public static void main(String[] args) {
OpenCV.loadLocally();
String imagePath = ResourceUtils.getResourcePath(IMAGE_NAME);
Mat image = Imgcodecs.imread(imagePath);
HighGui.imshow( "图像", image );
HighGui.waitKey(0);
HighGui.destroyAllWindows();
System.exit(0);
}
}

3. 辅助工具类

处理文件系统时,准备工具类可以专注于目标检测,而不必考虑从何处加载图像或模型。以下是ResourceUtils.java辅助类:

import java.net.URL;
public class ResourceUtils
{
public static String getResourcePath(String resourceName){
URL resourceUrl = App.class.
getClassLoader().getResource( resourceName );
if(resourceUrl == null){
throw new RuntimeException("未找到名为"+resourceName+ "的资源");
}
String resourcePath = resourceUrl.getPath();
if(resourcePath.isEmpty()) {
throw new RuntimeException("从资源URL获取路径时出错");
}
return resourcePath;
}
}

4. 模型准备

使用OpenCV的深度神经网络模块,需要将PyTorch或TensorFlow等框架中训练的模型转换为ONNX(开放神经网络交换)格式。

转换YOLO模型为ONNX格式

推荐通过Google Colab使用Python完成转换:

!pip install ultralytics
from ultralytics import YOLO
model = YOLO("yolo11n-seg.pt")
success = model.export(format="onnx")

YOLO模型(包括早期版本)默认在COCO(上下文常见对象)数据集上进行训练,该数据集包含80个类别,包括人、汽车、自行车、狗、猫等等。

完成转换后,下载yolov11n-seg.onnx模型并保存到Java项目的resources文件夹中。

5. 推理前的准备步骤

后续步骤包括:

  1. 为模型准备输入图像
  2. 加载模型
  3. 运行推理
  4. 从结果中提取分割信息
  5. 可视化结果
准备输入图像

为YOLOv11模型准备图像,包括调整大小(该YOLO模型的IMG_SIZE为640像素):

// 此步骤包括将BGR转换为RGB
Mat inputBlob = Dnn.blobFromImage(image, 1.0 / 255.0,
new Size(IMG_SIZE, IMG_SIZE),
// 这里我们提供卷积神经网络期望的空间尺寸
new Scalar(new double[]{
0.0, 0.0, 0.0
}),
true, false);

最后两个布尔标志位说明:

  • swapRB:指示是否需要对3通道图像交换首尾通道的标志位(在OpenCV中,默认图像格式是BGR而非更常见的RGB,因此设为true
  • crop:指示调整大小后是否对图像进行裁剪的标志位
加载模型并设置输入
String modelPath = ResourceUtils.getResourcePath(MODEL_NAME);
Net net = Dnn.readNetFromONNX(modelPath);
net.setInput(inputBlob);
运行推理
List<
String> outNames = net.getUnconnectedOutLayersNames();
List<
Mat> outputsList = new ArrayList<
>();
net.forward(outputsList, outNames);
  • net.getUnconnectedOutLayersNames():返回网络输出层的名称
  • outputsList:在模型前向传播后保存结果(实际输出)
  • net.forward:用于运行网络的前向传播,通过模型各层处理输入数据来计算输出结果

后处理过程

net.forward调用获得输出后,需要进行后处理以提取分割信息。

输出结果分析

扩展代码片段,打印outputsList中的预测结果:

List<
String> outNames = net.getUnconnectedOutLayersNames();
List<
Mat> outputsList = new ArrayList<
>();
net.forward(outputsList, outNames);
// 获取相关输出并打印出来
Mat boxOutputs = outputsList.get(0);
Mat maskOutputs = outputsList.get(1);
LOGGER.info("框输出: "+boxOutputs.toString());
LOGGER.info("掩码输出: "+maskOutputs.toString());

boxOutputs是边界框预测,形状为**[1, 116, 8400]**,包含8400个潜在检测的预测,每个检测有116个值:

  • 4个值用于边界框坐标(center_x, center_y, width, height)
  • 80个值用于类别概率(COCO数据集的80个类别)
  • 32个值用于掩码系数(与maskOutputs结合生成分割掩码)

矩阵转置处理

为了正确处理8400个预测(每个对应116个值),需要将矩阵转置为8400x116

Mat mat2D = boxOutputs.reshape(1, (int) boxOutputs.size().width);
// 第二个参数是行数
Core.transpose(mat2D, mat2D);

提取相关信息

从输出中提取信息的步骤:

  1. 遍历8400行中的每一行
  2. 对于每一行,提取80个类别概率并找到最大值
  3. 根据定义的阈值检查该最大值(例如,仅保留分数 > 0.6的预测)
  4. 提取掩码系数(从总共116个值中取出最后32个值)
  5. 为此检测生成掩码
var segmentationMasks = new ArrayList<
Mat>();
LOGGER.info("—-开始分析推理结果—-");
for (int i = 0; i < mat2D.rows(); i++)
{
Mat detectionMat = mat2D.row(i);
List<
Double> scores = new ArrayList<
>();
for (int j = 4; j < NUM_CLASSES+4; j++) {
scores.add(mat2D.get(i, j)[0]);
}
MaxScore maxScore = ScoreUtils.findMaxScore( scores );
if(maxScore.maxValue() <
0.6) {
continue;
}
// 提取掩码系数
Mat maskCoeffs = detectionMat.colRange(4 + NUM_CLASSES, 4 + NUM_CLASSES + 32);
// 为此检测生成掩码
Mat objectMask = generateMask(maskOutputs, maskCoeffs);
segmentationMasks.add(objectMask);
}

分数计算工具类

ScoreUtils用于从双精度数组中找出最大值:

record MaxScore (double maxValue, int indexOfMax) {
}
public class ScoreUtils
{
public static MaxScore findMaxScore(List<
Double> array) {
double max = array.get(0);
int indexOfMax = 0;
for (int i = 1; i < array.size(); i++) {
if (array.get(i) > max) {
max = array.get(i);
indexOfMax = i;
}
}
return new MaxScore( max, indexOfMax );
}
}

掩码系数提取

提取掩码系数的代码:

Mat maskCoeffs = detectionMat.colRange(4 + NUM_CLASSES, 4 + NUM_CLASSES + 32);

获取从索引4 + NUM_CLASSES(本例中为84)到NUM_CLASSES+32(本例中为116)的值。
在这里插入图片描述

生成掩码

查看for循环的最后两个步骤:

// 为此检测生成掩码
Mat objectMask = generateMask(maskOutputs, maskCoeffs);
segmentationMasks.add(objectMask);

还将研究如何将掩码叠加到原始图像上,详细检查maskOutputs,并在先前步骤中提取的32个掩码系数与maskOutputs中的32个原型掩码之间执行矩阵乘法。

结论

在快速实验目标检测、实例分割以及与大型语言模型(LLMs)集成方面,Java正变得越来越强大。本系列将帮助您了解借助OpenCV在这个生态系统中目前可以实现的功能。

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

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

相关文章

哪个公司做网站最好深圳网站建设拟解决问题

在IC设计项目的验证过程中&#xff0c;功能测试&#xff08;通过使用测试平台&#xff09;有助于定位设计错误或漏洞。这个验证过程有三个阶段&#xff1a;构建和启动测试平台、验证基本测试用例以及验证边界情况。 在前两个阶段&#xff0c;漏洞很容易被检测到&#xff0c;因…

百度网站地图北京专业网站制作公司

一、Spring Cloud&#xff08;Base工程构建&#xff09; 1.1 Spring Cloud 简述 1.1.1 Spring Cloud 版本推荐 在讲解 Spring Cloud 之前&#xff0c;首先推荐一下各个依赖的版本&#xff0c;以免出现版本错误 版本推荐 必须根据以上版本&#xff0c;否则可能会出现一些不…

品牌创意型网站建设山东省城乡建设厅官网

目录 1.背景介绍1.1. 项目背景1.2. 项目难点1.3. 项目环境 2. flask后端开发实现的功能3. flask部署和前后端对接3.1. flask运行配置和服务器部署3.2. flask前后端传参 4. 后端测试工具4.1. 工具介绍4.2. 工具使用 后记 1.背景介绍 1.1. 项目背景 就是前几个月临时接手了一个…

html网站开发心得体会大丰市市城乡建设局网站

来源&#xff1a;中国电子信息产业发展研究院10月19日&#xff0c;由北京市人民政府、工业和信息化部主办&#xff0c;工业和信息化部装备工业发展中心、中国电子信息产业发展研究院&#xff08;以下简称“赛迪研究院”&#xff09;等机构共同承办的“世界智能网联汽车大会”进…

互联网app下载手机优化加速有什么用

dubbo自定义了很多xml标签&#xff0c;例如&#xff0c;那么这些自定义标签是怎么与spring结合起来的呢&#xff1f;我们先看一个简单的例子。一 编写模型类1 packagecom.hulk.testdubbo.model;23 public classHero {4 privateString name;5 private intage;67 publicString ge…

北京网站设计济南兴田德润团队怎么样专门代写平台

点击上方蓝字关注我们&#xff08;本文阅读时间&#xff1a;4 分钟&#xff09;活动介绍▌MAUI 跨平台应用开发实战前端应用开发往往需要面对 iOS、Android、Windows 等多平台开发的问题。如能用一种开发工具进行多平台的开发&#xff0c;可以跨平台共享 UI 布局和设计&#xf…

电子商务公司名称大全简单大气wordpress优化软件

可以设置小程序跳转&#xff0c;引流也不错支持小程序后台流量主激励视频广告用户下载一次观看一次视频广告&#xff0c;收入非常可观支持小程序后台流量主banner广告支持全网短视频解析&#xff0c;苹果安卓通用支持后台无限生成卡密支持自定义文字广告支持图片广告支持小程序…

网站数据库模板下载90设计手机站

小张一年前入职&#xff0c;当时毕业已经一年了&#xff0c;一年换了4份工作。最少的才呆了一周。 小张的简历很正规&#xff0c;彩色打印&#xff0c;整整5页。技能篇写的很全&#xff0c;基本上市面上的技术都写到了&#xff0c;都是精通。面试的时候&#xff0c;表现也很好&…

Java实现双色球历史是否中奖查询

Java实现双色球历史是否中奖查询 在一些问答里,很多彩友都在问:如何查看自己的双色球号码在历史期次中有没有中过奖?作为开发者兼彩友,这个问题就简单了,决定解决一下这个问题,先上结果: 双色球历史是否中奖查询…

iframe引入界面有el-date-picker日期框,点击出现闪退问题处理 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

ABC424 游记(VP)

前五题没什么难度,第六题恰好会,运气好 6t 没寄。省流 前五题没什么难度,第六题恰好会,运气好 6t 没寄。9.23 内含剧透,请vp后再来。 不是题解!!!!!!! 赛前 下午下大雨没去图书馆,浪费了一下午,晚上准备…

Java实现大乐透历史是否中奖查询

Java实现大乐透历史是否中奖查询 在一些问答里,很多彩友都在问:如何查看自己的大乐透号码在历史期次中有没有中过奖?作为开发者兼彩友,这个问题就简单了,决定解决一下这个问题,先上结果: 大乐透历史是否中奖查询…

怎么弄网站做网站卖东西wordpress 怎样写函数

在Android开发中使用View制作一个引导动画发布时间&#xff1a;2020-11-20 16:46:16来源&#xff1a;亿速云阅读&#xff1a;98作者&#xff1a;Leah这篇文章将为大家详细讲解有关在Android开发中使用View制作一个引导动画&#xff0c;文章内容质量较高&#xff0c;因此小编分享…

网站如何做会员通用西安网站制作网站

第一种方案&#xff1a;使用CountDownLatch工具类 CountDownLatch&#xff1a;是Java多线程编程中的一个同步工具类&#xff08;计数锁&#xff09;&#xff0c;它允许一个或多个线程等待其他线程完成操作后再继续执行。其内部维护了一个计数器&#xff0c;当线程在执行任务完…

如何把网站做的和别人一样网站的具体内容

XSS漏洞&#xff08;跨站脚本&#xff09; 1.XSS 漏洞简介 ​ XSS又叫CSS&#xff08;Cross Site Script&#xff09;跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Script代码&#xff0c;当用户浏览该页之时&#xff0c;嵌入其中Web里面的Script代码会被执行&#xff0c;从…

新类型网站利用js做网站

1. 题目 2. 分析 合理地改造原数据&#xff0c;这样会使得代码逻辑大大简化。 为了让代码走相同的逻辑&#xff0c;这里需要在原数据后面追加一个price 0。这个price 0大大地简化了处理[1,2,3,4,5] 这类型数据的复杂度。 3. 代码 class Solution:def maxProfit(self, pri…

怎么做网站不用备案怀宁做网站

高斯模糊、加载监听、圆角图片这些相信大家都很熟悉&#xff0c;那如何实现这些效果&#xff0c;请大家参考本文进行学习。1、引用compile com.github.bumptech.glide:glide:3.7.02、加载图片2.1 基本加载Glide.with(context).load(url).into(imageView);2.2 设置加载中和加载失…

找项目seo网站设计多少钱

集合里面的 E是泛型 暂且认为是object转载于:https://www.cnblogs.com/classmethond/p/10011374.html

如何做聚合类网站业务员销售管理软件

1.题目 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以按任意…

潭州教育网站开发网站建设开发报价单

定义 标识符只能由字母、数字、下划线&#xff08;_&#xff09;和美元符号&#xff08;$&#xff09;组成。标识符必须以字母、下划线或美元符号开头&#xff0c;不能以数字开头。标识符对大小写敏感&#xff0c;例如"myVariable"和"myvariable"是不同的…