基于java实现图片中任意封闭区域识别
需求:
在浏览器中给用户呈现一张图片,用户点击图片中的某些标志物,需要系统给出标志物的信息反馈,达到一个交互的作用。
比如下图中,点击某个封闭区域时候,需要告知用户点击的区域名称及图形形状特性等等。

实现思路模仿 window系统中画图工具的区域填充工具。
当我们给一个封闭区域填充色彩的时候,整个区域都将得到填充相同的颜色,此区域封闭即可,这样我们将一张图片中的不同区域填充不同的色彩,得到如下的图片:

后续只需要通过xy坐标得到颜色,在通过颜色得到对应的图片相关信息即可。应用时候的复杂度为O(1)
实现代码如下:
import javax.imageio.ImageIO;import static org.assertj.core.api.Assertions.useDefaultDateFormatsOnly;import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class ImageRGBMatrix {//边界的颜色static final int flagColor = 237;//需要填充的色彩static int setColor = 20+(0xFF << 8);public static void main(String[] args) {try {// 读取图片BufferedImage image = ImageIO.read(new File("C:\\Users\\hxd\\Desktop\\pdy.png"));int width = image.getWidth();int height = image.getHeight();初始化特征矩阵//int[][] characteristicMatrix = new int[width][height];// 遍历图片的每个像素for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {// 获取(x, y)位置的像素int pixel = image.getRGB(x, y);// 获取RGB分量short red = (short) ((pixel >> 16) & 0xFF);
// short green = (short) ((pixel >> 8) & 0xFF);
// short blue = (short) (pixel & 0xFF);characteristicMatrix[x][y] = red;}}///初始化特征矩阵完成////基于点进行矩阵区域填充/List<Point> ps = new ArrayList<>();ps.add(new Point(116,140,"1","A",0));ps.add(new Point(427,116,"2","B",0));ps.add(new Point(203,426,"3","C",0));ps.add(new Point(661,382,"4","D",0));ps.add(new Point(543,609,"5","E",0));Map<Integer,Point> color2Points = new HashMap<>(); for (Point p : ps) {int my = p.getY();int mx = p.getX();setColor += 40;p.setColor(setColor);color2Points.put(setColor, p);//初始上for (int y = my; y > -1 && characteristicMatrix[mx][y] !=flagColor; y--) {characteristicMatrix[mx][y] = setColor;}//初始下for (int y = my+1; y < height && characteristicMatrix[mx][y] !=flagColor; y++) {characteristicMatrix[mx][y] = setColor;}//记录是否有新增加的点boolean isAdd = true;while(isAdd) {//一旦没有扩充新鲜点,则退出//横向扩充isAdd = leftRigthScan(width, height, characteristicMatrix);if(isAdd) {//轴向扩充isAdd = upDownScan(width, height, characteristicMatrix);}}}///基于点进行矩阵区域填充完成////开始实在使用,找到具体的点在哪个区域/ List<Point> pp = new ArrayList<>();pp.add(new Point(116,140));pp.add(new Point(116,145));pp.add(new Point(596,358));for (Point p : pp) {int color = characteristicMatrix[p.getX()][p.getY()];System.out.println(color2Points.get(color));}///开始实在使用,找到具体的点在哪个区域完成////可视化输出,仅仅是让给人看看填充是否正确,对实际使用没有作用/BufferedImage image1 = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {image1.setRGB(x,y,characteristicMatrix[x][y]);}}ImageIO.write(image1, "png", new File("d:\\pdypdypdy.png"));///可视化输出,仅仅是让给人看看填充是否正确,对实际使用没有作用/} catch (IOException e) {e.printStackTrace();}}/*** 纵向扫描* 从左到右一列一列的扫描:* 从上到下扫描y列: (y在变化)* 1、如果是非着色的点,则继续下移。如果是着色点,执行2、3两步骤。如果超出数组边界则开始下一列* 2、基于此着色点向上侧扩张,直到上侧点是边界点或者下标超出数组下界0;* 3、基于此着色点向下侧扩张,直到下侧点是边界点或者下标超出数组上界height;更新扫描点为当前最下侧扩张点 继续第1步执行。;* * * @param width* @param height* @param characteristicMatrix* @return*/private static boolean upDownScan(int width, int height, int[][] characteristicMatrix) {boolean isAdd = false;//看横向的线for (int x = 0; x < width; x++) {int y = 0;while(y < height) {for (; y < height; y++) {if(characteristicMatrix[x][y] == setColor) {break ;}}if(y < height) {//此列有//处理上边for (int uy = y-1; uy > -1 && characteristicMatrix[x][uy] !=flagColor; uy--) {if(characteristicMatrix[x][uy] != setColor) {characteristicMatrix[x][uy] = setColor;isAdd = true;}}//处理下边for (y = y+1; y < height && characteristicMatrix[x][y] !=flagColor; y++) {if(characteristicMatrix[x][y] != setColor) {characteristicMatrix[x][y] = setColor;isAdd = true;}}}}}return isAdd;}//左右横向扫描/*** 左右横向扫描* 从上到下一行一行的开始扫描扩张。* 从左到右扫描x行:* 1、如果是非着色的点,则继续右移。如果是角色点,执行2、3两步骤。如果超出数组边界则开始下一行* 2、基于此着色点向左侧扩张,直到左侧点是边界点或者下标超出数组下界0;* 3、基于此着色点向右侧扩张,直到右侧点是边界点或者下标超出数组上界width;更新扫描点为当前最右侧扩张点 继续第1步执行。;* * @param width* @param height* @param characteristicMatrix* @return*/protected static boolean leftRigthScan(int width, int height, int[][] characteristicMatrix) {boolean isAdd = false;for (int y = 0; y < height; y++) {int x = 0;while(x < width) {for (; x < width; x++) {if(characteristicMatrix[x][y] == setColor) {break ;}}if(x < width) {//此行有//处理左边for (int lx = x-1; lx > -1 && characteristicMatrix[lx][y] !=flagColor; lx--) {if(characteristicMatrix[lx][y] != setColor) {characteristicMatrix[lx][y] = setColor;isAdd = true;}}//处理右边for (x = x+1; x < width && characteristicMatrix[x][y] !=flagColor; x++) {if(characteristicMatrix[x][y] != setColor) {characteristicMatrix[x][y] = setColor;isAdd = true;}}}}}return isAdd;}
}
相关文章:
基于java实现图片中任意封闭区域识别
需求: 在浏览器中给用户呈现一张图片,用户点击图片中的某些标志物,需要系统给出标志物的信息反馈,达到一个交互的作用。 比如下图中,点击某个封闭区域时候,需要告知用户点击的区域名称及图形形状特性等等。…...
闭包是什么?有什么特性?对页面有什么影响?
闭包是指在一个函数内部定义的函数,并且该函数可以访问到外部函数的变量。闭包可以将外部函数的变量保持在内存中,并且不会被释放。 闭包具有以下特性: 1. 函数内部定义的函数可以访问外部函数的变量。 2. 外部函数的变量可以保持在内存中&a…...
MS Excel: 高亮当前行列 - 保持原有格式不被改变
本文使用条件格式VBA的方法实现高亮当前行列,因为纯VBA似乎会清除原有的高亮格式。效果如下:本文图省事就使用同一种颜色了。 首先最重要的,【选中你期望高亮的单元格区域】,比如可以全选当前sheet的全部区域 然后点击【开始】-【…...
langchain学习(十三)
一、将其他chain的输入作为新chain的输出,三种方式 1、采用连接符"|",推荐 2、采用lamba表达式输入 3、采用pipe方法 from langchain_community.chat_models import ChatOllama from langchain_core.output_parsers import StrOutputParse…...
【Nginx】深入解析Nginx配置文件
Nginx(发音为“engine-ex”)是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。由于其高并发性、低资源消耗和模块化设计,Nginx在全球范围内被广泛使用。本文将深入解析Nginx配置文件,帮助读者了…...
深入了解Nginx(一):Nginx核心原理
一、Nginx核心原理 本节为大家介绍Nginx的核心原理,包含Reactor模型、Nginx的模块化设计、Nginx的请求处理阶段. (本文源自微博客,且已获得授权) 1.1、Reactor模型 Nginx对高并发IO的处理使用了Reactor事件驱动模型。Reactor模型的基本组件包含时间收集…...
产品经理-流程图结构图(四)
1. 流程图 1.1 概念 为了达到特定的目标而进行的一系列有逻辑性的操作步骤,由两个及以上的步骤,完成一个完整的行为的过程,可称之为流程 1.2 产品经理为什么需要绘制流程图? 保证产品的使用逻辑合理顺畅向项目组其他成员清晰的…...
15、Spring系统-AOP
ProxyFactory选择cglib或jdk动态代理原理 ProxyFactory在生成代理对象之前需要决定到底是使用JDK动态代理还是CGLIB技术: 代理对象创建过程 JdkDynamicAopProxy 在构造JdkDynamicAopProxy对象时,会先拿到被代理对象自己所实现的接口,并且…...
服务器感染了. rmallox勒索病毒,如何确保数据文件完整恢复?
导言: 近年来,随着信息技术的飞速发展,网络安全问题日益凸显。其中,勒索病毒作为一种严重的网络威胁,对个人和企业数据造成了巨大的威胁。本文将重点介绍.rmallox勒索病毒的特点、传播途径以及应对策略,旨…...
[每日一练]按日期分组销售产品的最优解法
该题目来自于力扣的pandas题库,链接如下: 1484. 按日期分组销售产品 - 力扣(LeetCode) 题目要求: 表 Activities: ---------------------- | 列名 | 类型 | ---------------------- | sell_…...
免费wordpress中文主题
免费大图wordpress主题 首页是一张大图的免费wordpress主题模板。简洁实用,易上手。 https://www.jianzhanpress.com/?p5857 免费WP模板下载 顶部左侧导航条的免费WP模板,后台简洁,新手也可以下载使用。 https://www.jianzhanpress.com/…...
单链表经典算法题理解
目录 1. 前言: 2. 移除链表元素 3. 反转链表 4. 合并两个有序链表 5. 链表的中间节点 6. 环形链表的约瑟夫问题 7. 分割链表 1. 前言: 当我们学习了单链表之后,我能可以尝试的刷一下题了,以下分享一下几道题的解法 2. 移…...
STM32的时钟介绍
目录 前言1. 简介1.1 时钟是用来做什么的1.2 时钟产生的方式 2. 时钟树的组成2.1 时钟源2.1.1 内部时钟2.1.2 外部时钟 2.2 PLL锁相环2.3 SYSCLK2.4 AHB和HCLK2.5 APB和PCLK2.6 总结 3. STM32时钟的如何进行工作4.我的疑问4.1 使用MSI和HSI有什么区别吗?4.2 MSI的频…...
FindBI学习总结
大数据分析BI工具:用户只需简单拖拽便能制作出丰富多样的数据可视化信息 关注点: 快速入门、数据加工、构建图表和分析数据、数据分析进阶 1、界面介绍 目录–仪表板–数据准备 仪表板目录–预览区域 快速上手: 1、数据准备2、制作仪表板3、分…...
k8s——Pod详解
一、Pod基础概念 1.1 Pod定义 Pod是kubernetes中最小的资源管理组件,Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是围绕着Pod来进行支撑和扩展Pod功能的,例如,用于管理Pod运行…...
Visual Studio 的调试
目录 引言 一、调试的基本功能 设置断点 启动调试 检查变量 逐步执行代码 调用堆栈 使用即时窗口 二、调试技巧 条件断点 日志断点 数据断点 异常调试 三、调试高级功能 远程调试 多线程调试 内存调试 性能调试 诊断工具 四、调试策略与最佳实践 系统化的…...
mysql语句大全及用法
MySQL是一种广泛使用的开源关系型数据库管理系统,它支持标准的SQL(Structured Query Language)语言,用于数据库的查询和操作。以下是一些基本的MySQL语句及其用法的概述: 连接MySQL数据库 mysql -h主机地址 -P端口号…...
如何找出真正的交易信号?Anzo Capital昂首资本总结7个
匕首是一种新兴的价格走势形态,虽然不常见,但具有较高的统计可靠性。它通常预示着趋势的持续发展。该模式涉及到同时参考两个不同的时间周期进行交易,一个是短期,另一个是长期,比如一周时间框架与一天时间框架、一天时…...
JavaScript-内存分配
内存空间 内存分为栈和堆 栈:由操作系统自动释放存放的变量值和函数值等。简单数据类型存放在栈中 栈会由低到高先入后出 堆:存储引用类型 (对象) 对象会先将数据存放在堆里面,堆的地址放在栈里面...
理论知识.质数打表
啊,哈喽,小伙伴们大家好。我是#张亿,今天呐,学的是理论知识.质数打表 为什么需要质数打表 我们已经学习了如何判断一个数是不是质数了,但是还不够。假设要判断很多很多个数是不是质数的时候,之前的学习的…...
如何评价目前主流的AI论文生成软件?哪一款最好用?
目前主流 AI 论文工具已形成清晰的中文全流程、英文国际、文献 / 润色专项三大阵营,PaperRed、毕业之家是中文论文全流程首选,ChatGPT-4o、Claude 3.7适合英文与深度逻辑,Kimi、Elicit专攻文献处理。没有绝对 “最好”,只有最适配…...
揭秘Synopsys EDA中的AI黑科技:DSO.ai如何改变传统芯片设计流程
揭秘Synopsys EDA中的AI黑科技:DSO.ai如何重塑芯片设计范式 当芯片制程迈入3纳米时代,单个晶体管尺寸已接近物理极限,设计复杂度却呈指数级增长。传统EDA工具如同手持计算尺的工程师面对摩天大楼蓝图——方法论需要根本性变革。这正是DSO.ai诞…...
Multisim 13.0 仿真 LC 振荡器:从起振到稳定,手把手教你分析波形与频率稳定度
Multisim 13.0 仿真 LC 振荡器:从起振到稳定,手把手教你分析波形与频率稳定度 在电子工程领域,LC振荡器作为基础电路之一,其设计与分析能力是每位硬件工程师的必修课。Multisim作为业界广泛使用的电路仿真软件,为我们…...
QQ空间数据备份工具:GetQzonehistory本地化数据留存方案
QQ空间数据备份工具:GetQzonehistory本地化数据留存方案 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 在数字化时代,个人社交数据的长期保存与管理成为重要需求…...
智能家居系统部署终极指南:5分钟搞定全流程配置
智能家居系统部署终极指南:5分钟搞定全流程配置 【免费下载链接】operating-system :beginner: Home Assistant Operating System 项目地址: https://gitcode.com/gh_mirrors/op/operating-system Home Assistant Operating System(原HassOS&…...
教育软件控制突破:JiYuTrainer的内核级反控制解决方案
教育软件控制突破:JiYuTrainer的内核级反控制解决方案 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 副标题:技术原理、实现路径与教育场景应用指南 一、…...
Win10系统代理服务器拒绝连接?3步搞定网络恢复(附图文详解)
Win10代理服务器连接故障排查指南:从原理到实战解决方案 当Windows 10突然弹出"代理服务器拒绝连接"的错误提示时,很多用户会感到手足无措。这种情况通常发生在系统更新后、网络环境变更时,或是某些应用程序擅自修改了系统设置。本…...
边缘端模型部署卡壳?这7个Python量化工具配置错误正在悄悄拖垮你的IoT项目,立即排查!
第一章:边缘端Python量化部署的典型瓶颈诊断在边缘设备(如树莓派、Jetson Nano、RK3588等)上部署量化后的Python模型时,性能表现常显著低于预期。根本原因并非模型精度下降,而是运行时环境与硬件约束引发的隐性瓶颈。精…...
Python MCP服务部署成本飙升?5个被90%团队忽略的隐性开销及实时监控方案
第一章:Python MCP服务部署成本飙升的真相与警示Python MCP(Model Control Plane)服务在微服务架构中承担模型注册、版本调度、A/B测试路由等关键职责。近期大量团队反馈其云上部署成本在两周内激增300%以上,远超业务增长曲线。深…...
实时与非实时操作系统核心技术对比与应用解析
实时与非实时操作系统技术解析1. 操作系统分类概述现代计算机系统根据任务调度机制的不同,主要分为实时操作系统(RTOS)和分时操作系统两大类。这两类系统在任务调度、资源分配和响应机制等方面存在本质区别,适用于不同的应用场景。1.1 实时操作系统定义实…...
