基于java实现图片中任意封闭区域识别

4 篇文章 0 订阅

需求:
在浏览器中给用户呈现一张图片,用户点击图片中的某些标志物,需要系统给出标志物的信息反馈,达到一个交互的作用。
比如下图中,点击某个封闭区域时候,需要告知用户点击的区域名称及图形形状特性等等。
原始图片
实现思路模仿 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;
	}
}
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值