图像处理之基于泛红算法的二值图像内部区域填充

简介: 图像处理之基于泛红算法的二值图像内部区域填充

图像处理之基于泛红算法的二值图像内部区域填充


一:基本原理


在二值图像处理中有个常用的操作叫做Hole Fill意思是填充所有封闭区域的内部,这种算法在二值图像基础上的对象识别与提取有很大作用。基于泛红填充算法实现二值图像内部区域填充是一直快速填充算法。




因为泛红填充通常需要指定从一个点开始,填满整个封闭区域,对一张二值图像来说,我们最好的办法是把背景当成一个封闭区域,从上向下从左到右查到第一个背景像素点,基于扫描线算法实现全部填充成一个非0,255之外的一个像素值,我这里是127。填充完成之后再一次从左到右,从上向下检查每个像素值如果是127的则为背景像素,否则全部设为前景像素。这样就完成二值图像每个封闭区域内部填充。




二:算法实现步骤


1.      读取二值图像


2.      基于扫描线算法对背景像素区域进行泛红填充,填充值为127


3.      循环每个像素对值为127的设为背景像素,其它值设为前景像素


4.      返回填充之后的二值图像像素数据


三:代码实现

package com.gloomyfish.basic.imageprocess;
 
public class FloodFillAlgorithm extends AbstractByteProcessor {
  private int foreground;
  private int background;
  private byte[] data;
  private int width;
  private int height;
 
  // stack data structure
  private int maxStackSize = 500; // will be increased as needed
  private int[] xstack = new int[maxStackSize];
  private int[] ystack = new int[maxStackSize];
  private int stackSize;
 
  public FloodFillAlgorithm(byte[] data) {
    this.data = data;
    this.foreground = 0;
    this.background = 255 - this.foreground;
  }
 
  public int getColor(int x, int y) {
    int index = y * width + x;
    return data[index] & 0xff;
  }
 
  public void setColor(int x, int y, int newColor) {
    int index = y * width + x;
    data[index] = (byte) newColor;
  }
 
  public void floodFillScanLineWithStack(int x, int y, int newColor, int oldColor) {
    if (oldColor == newColor) {
      System.out.println("do nothing !!!, filled area!!");
      return;
    }
    emptyStack();
 
    int y1;
    boolean spanLeft, spanRight;
    push(x, y);
 
    while (true) {
      x = popx();
      if (x == -1)
        return;
      y = popy();
      y1 = y;
      while (y1 >= 0 && getColor(x, y1) == oldColor)
        y1--; // go to line top/bottom
      y1++; // start from line starting point pixel
      spanLeft = spanRight = false;
      while (y1 < height && getColor(x, y1) == oldColor) {
        setColor(x, y1, newColor);
        if (!spanLeft && x > 0 && getColor(x - 1, y1) == oldColor)// just
                                      // keep
                                      // left
                                      // line
                                      // once
                                      // in
                                      // the
                                      // stack
        {
          push(x - 1, y1);
          spanLeft = true;
        } else if (spanLeft && x > 0 && getColor(x - 1, y1) != oldColor) {
          spanLeft = false;
        }
        if (!spanRight && x < width - 1 && getColor(x + 1, y1) == oldColor) // just
                                          // keep
                                          // right
                                          // line
                                          // once
                                          // in
                                          // the
                                          // stack
        {
          push(x + 1, y1);
          spanRight = true;
        } else if (spanRight && x < width - 1 && getColor(x + 1, y1) != oldColor) {
          spanRight = false;
        }
        y1++;
      }
    }
 
  }
 
  private void emptyStack() {
    while (popx() != -1) {
      popy();
    }
    stackSize = 0;
  }
 
  final void push(int x, int y) {
    stackSize++;
    if (stackSize == maxStackSize) {
      int[] newXStack = new int[maxStackSize * 2];
      int[] newYStack = new int[maxStackSize * 2];
      System.arraycopy(xstack, 0, newXStack, 0, maxStackSize);
      System.arraycopy(ystack, 0, newYStack, 0, maxStackSize);
      xstack = newXStack;
      ystack = newYStack;
      maxStackSize *= 2;
    }
    xstack[stackSize - 1] = x;
    ystack[stackSize - 1] = y;
  }
 
  final int popx() {
    if (stackSize == 0)
      return -1;
    else
      return xstack[stackSize - 1];
  }
 
  final int popy() {
    int value = ystack[stackSize - 1];
    stackSize--;
    return value;
  }
 
  @Override
  public void process(int width, int height) {
    this.width = width;
    this.height = height;
 
    for (int y = 0; y < height; y++) {
      if (getColor(0, y) == background)
        floodFillScanLineWithStack(0, y, 127, 255);
      if (getColor(width - 1, y) == background)
        floodFillScanLineWithStack(width - 1, y, 127, 255);
    }
    for (int x = 0; x < width; x++) {
      if (getColor(x, 0) == background)
        floodFillScanLineWithStack(x, 0, 127, 255);
      if (getColor(x, height - 1) == background)
        floodFillScanLineWithStack(x, height - 1, 127, 255);
    }
    
    int p = 0;
    for (int i = 0; i < data.length; i++) {
      p = data[i]&0xff;
      if (p == 127)
        data[i] = (byte)255;
      else
        data[i] = (byte)0;
    }
  }
 
}

四:运行结果

使用代码,要先读取二值图像数据到data字节数组

FloodFillAlgorithm ffa = new FloodFillAlgorithm(data);
    ffa.process(width, height);
目录
打赏
0
0
0
0
81
分享
相关文章
基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
本项目展示了256×256图像通过双线性插值放大至512×512的效果,无水印展示。使用Matlab 2022a和Vivado 2019.2开发,提供完整代码及详细中文注释、操作视频。核心程序实现图像缩放,并在Matlab中验证效果。双线性插值算法通过FPGA高效实现图像缩放,确保质量。
基于Retinex算法的图像去雾matlab仿真
本项目展示了基于Retinex算法的图像去雾技术。完整程序运行效果无水印,使用Matlab2022a开发。核心代码包含详细中文注释和操作步骤视频。Retinex理论由Edwin Land提出,旨在分离图像的光照和反射分量,增强图像对比度、颜色和细节,尤其在雾天条件下表现优异,有效解决图像去雾问题。
基于信息论的高动态范围图像评价算法matlab仿真
本项目基于信息论开发了一种高动态范围(HDR)图像评价算法,并通过MATLAB 2022A进行仿真。该算法利用自然图像的概率模型,研究图像熵与成像动态范围的关系,提出了理想成像动态范围的计算公式。核心程序实现了图像裁剪处理、熵计算等功能,展示了图像熵与动态范围之间的关系。测试结果显示,在[μ-3σ, μ+3σ]区间内图像熵趋于稳定,表明系统动态范围足以对景物成像。此外,还探讨了HDR图像亮度和对比度对图像质量的影响,为HDR图像评价提供了理论基础。
基于Affine-Sift算法的图像配准matlab仿真
本项目展示了Affine-SIFT算法的运行效果(无水印),适用于图像配准任务,能够处理旋转、缩放、平移及仿射变换。程序基于MATLAB2022A开发,包含完整代码与操作视频。核心步骤为:先用SIFT提取特征点,再通过仿射变换实现高精度对准。
使用 PAI-DSW x Free Prompt Editing图像编辑算法,开发个人AIGC绘图小助理
使用 PAI-DSW x Free Prompt Editing图像编辑算法,开发个人AIGC绘图小助理
【MM2024】阿里云 PAI 团队图像编辑算法论文入选 MM2024
阿里云人工智能平台 PAI 团队发表的图像编辑算法论文在 MM2024 上正式亮相发表。ACM MM(ACM国际多媒体会议)是国际多媒体领域的顶级会议,旨在为研究人员、工程师和行业专家提供一个交流平台,以展示在多媒体领域的最新研究成果、技术进展和应用案例。其主题涵盖了图像处理、视频分析、音频处理、社交媒体和多媒体系统等广泛领域。此次入选标志着阿里云人工智能平台 PAI 在图像编辑算法方面的研究获得了学术界的充分认可。
【MM2024】阿里云 PAI 团队图像编辑算法论文入选 MM2024
【MM2024】面向 StableDiffusion 的多目标图像编辑算法 VICTORIA
阿里云人工智能平台 PAI 团队与华南理工大学合作在国际多媒体顶级会议 ACM MM2024 上发表 VICTORIA 算法,这是一种面向 StableDiffusion 的多目标图像编辑算法。VICTORIA 通过文本依存关系来修正图像编辑过程中的交叉注意力图,从而确保关系对象的一致性,支持用户通过修改描述性提示一次性编辑多个目标。
织物图像的配准和拼接算法的MATLAB仿真,对比SIFT,SURF以及KAZE
本项目展示了织物瑕疵检测中的图像拼接技术,使用SIFT、SURF和KAZE三种算法。通过MATLAB2022a实现图像匹配、配准和拼接,最终检测并分类织物瑕疵。SIFT算法在不同尺度和旋转下保持不变性;SURF算法提高速度并保持鲁棒性;KAZE算法使用非线性扩散滤波器构建尺度空间,提供更先进的特征描述。展示视频无水印,代码含注释及操作步骤。
基于LK光流提取算法的图像序列晃动程度计算matlab仿真
该算法基于Lucas-Kanade光流方法,用于计算图像序列的晃动程度。通过计算相邻帧间的光流场并定义晃动程度指标(如RMS),可量化图像晃动。此版本适用于Matlab 2022a,提供详细中文注释与操作视频。完整代码无水印。

热门文章

最新文章