图像处理之六边形网格分割效果

简介: 图像处理之六边形网格分割效果

一:原理

根据输入参数blockSize的大小,将图像分块,决定每块的中心通过该像素块内所有

像素之和的均值与该块内部每个像素比较,RGB值之间几何距离最小为新的中心,迭

代更新运算,直到达到输入参数声明的最大循环次数为止,然后输出结果图像即可。

二:程序实现

类MyCluster,存储每个像素块中心的信息,计算中心位置。

类SuperPixelsFilter, 滤镜实现,完成六边形网格分割的主要功能,其中距离计算,基

于欧几里德距离公式。

三:效果

原图:

效果:


四:完全源代码

package com.gloomyfish.image.cluster.effect;
 
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
import com.gloomyfish.filter.study.AbstractBufferedImageOp;
 
public class SuperPixelsFilter extends AbstractBufferedImageOp {
 
  private double[] distances;
  private int[] labels; 
  private MyCluster[] clusters;
  private int maxClusteringLoops = 50;
  
  private double blockSize;
  private double modifier;
  
  public SuperPixelsFilter()
  {
    blockSize = 16;
    modifier = 130;
  }
  
  public double getBlockSize() {
    return blockSize;
  }
 
  public void setBlockSize(double blockSize) {
    this.blockSize = blockSize;
  }
 
  public double getModifier() {
    return modifier;
  }
 
  public void setModifier(double modifier) {
    this.modifier = modifier;
  }
    
  @Override
  public BufferedImage filter(BufferedImage src, BufferedImage dest) {
    int width = src.getWidth();
        int height = src.getHeight();
 
        if ( dest == null )
            dest = createCompatibleDestImage( src, null );
 
        int[] inPixels = new int[width*height];
        getRGB( src, 0, 0, width, height, inPixels );
        int index = 0;
        // initialization
        distances = new double[width*height];
        labels = new int[width*height];
        Arrays.fill(distances, Integer.MAX_VALUE);
        Arrays.fill(labels, -1);
        initClusters(width, height, inPixels, blockSize, modifier);
        // loop to get all block/cells, image segmentation
        int loops = 0;
        boolean pixelChangedCluster = true;
        while (pixelChangedCluster&&loops<maxClusteringLoops) { 
            pixelChangedCluster = false;
            loops++;
            // for each cluster center C  
            for (int i=0;i<clusters.length;i++) { 
              MyCluster c = clusters[i];
                // for each pixel i in 2S region around 
                // cluster center 
                int xs = Math.max((int)(c.avg_x-blockSize),0);
                int ys = Math.max((int)(c.avg_y-blockSize),0);
                int xe = Math.min((int)(c.avg_x+blockSize),width);
                int ye = Math.min((int)(c.avg_y+blockSize),height);
                for (int y=ys;y<ye;y++) { 
                    for (int x=xs;x<xe;x++) { 
                        int pos = x+width*y;
                        int tr = (inPixels[pos] >> 16) & 0xff;
                        int tg = (inPixels[pos] >> 8) & 0xff;
                        int tb = inPixels[pos] & 0xff;
                        double D = c.distance(x, y, tr, 
                                                    tg, 
                                                    tb, 
                                                    blockSize, modifier, width, height);
                        if ((D<distances[pos])&&(labels[pos]!=c.id)) { 
                            distances[pos]         = D;
                            labels[pos]            = c.id;
                            pixelChangedCluster = true;
                        } 
                    } // end for x 
                } // end for y 
            } // end for clusters 
            // reset clusters 
            for (index=0;index<clusters.length;index++) { 
                clusters[index].reset();
            } 
            // add every pixel to cluster based on label 
            for (int y=0;y<height;y++) { 
                for (int x=0;x<width;x++) { 
                    int pos = x+y*width;
                    int tr = (inPixels[pos] >> 16) & 0xff;
                    int tg = (inPixels[pos] >> 8) & 0xff;
                    int tb = inPixels[pos] & 0xff;
                    clusters[labels[pos]].addPixel(x, y, 
                            tr, tg, tb);
                } 
            } 
            
            // calculate centers 
            for (index=0;index<clusters.length;index++) { 
                clusters[index].calculateCenter();
            } 
        } 
        
        // Create output image with pixel edges  
        for (int y=1;y<height-1;y++) { 
            for (int x=1;x<width-1;x++) { 
                int id1 = labels[x+y*width];
                int id2 = labels[(x+1)+y*width];
                int id3 = labels[x+(y+1)*width];
                if (id1!=id2||id1!=id3) { 
                  int pos = x+y*width;
                  inPixels[pos] = (255 << 24) | (0 << 16) | (0 << 8) | 0; 
                } 
            } 
        } 
 
        setRGB( dest, 0, 0, width, height, inPixels );
        return dest;
  }
  
  public void initClusters(int width, int height, int[] input, 
            double S, double m) { 
    List<MyCluster> temp = new ArrayList<MyCluster>();
    boolean even = false;
    double xstart = 0;
    int id = 0;
    for (double y = S / 2; y < height; y += S) {
      // 创建六边形网格
      if (even) {
        xstart = S / 2.0;
        even = false;
      } else {
        xstart = S;
        even = true;
      }
      for (double x = xstart; x < width; x += S) {
        int index = (int) (x + y * width);
                int tr = (input[index] >> 16) & 0xff;
                int tg = (input[index] >> 8) & 0xff;
                int tb = input[index] & 0xff;
        MyCluster c = new MyCluster(id, tr, tg, tb,
            (int) x, (int) y, S, m);
        temp.add(c);
        id++;
      }
    }
    clusters = new MyCluster[temp.size()];
    for (int i = 0; i < temp.size(); i++) {
      clusters[i] = temp.get(i);
    } 
} 
 
}

MyCluster类代码:

package com.gloomyfish.image.cluster.effect;
 
public class MyCluster {
 
  int id;
  double inv = 0; // inv variable for optimization
  double pixelCount; // pixels in this cluster
  double avg_red; // average red value
  double avg_green; // average green value
  double avg_blue; // average blue value
  double sum_red; // sum red values
  double sum_green; // sum green values
  double sum_blue; // sum blue values
  double sum_x; // sum x
  double sum_y; // sum y
  double avg_x; // average x
  double avg_y; // average y
 
  public MyCluster(int id, int in_red, int in_green, int in_blue, int x,
      int y, double S, double m) {
    // inverse for distance calculation
    this.inv = 1.0 / ((S / m) * (S / m));
    this.id = id;
    addPixel(x, y, in_red, in_green, in_blue);
    // calculate center with initial one pixel
    calculateCenter();
  }
 
  public void reset() {
    avg_red = 0;
    avg_green = 0;
    avg_blue = 0;
    sum_red = 0;
    sum_green = 0;
    sum_blue = 0;
    pixelCount = 0;
    avg_x = 0;
    avg_y = 0;
    sum_x = 0;
    sum_y = 0;
  }
 
  /*
   * Add pixel color values to sum of previously added color values.
   */
  void addPixel(int x, int y, int in_red, int in_green, int in_blue) {
    sum_x += x;
    sum_y += y;
    sum_red += in_red;
    sum_green += in_green;
    sum_blue += in_blue;
    pixelCount++;
  }
 
  public void calculateCenter() {
    // Optimization: using "inverse"
    // to change divide to multiply
    double inv = 1 / pixelCount;
    avg_red = sum_red * inv;
    avg_green = sum_green * inv;
    avg_blue = sum_blue * inv;
    avg_x = sum_x * inv;
    avg_y = sum_y * inv;
  }
 
  double distance(int x, int y, int red, int green, int blue, double S,
      double m, int w, int h) {
    // power of color difference between
    // given pixel and cluster center
    double dx_color = (avg_red - red) * (avg_red - red)
        + (avg_green - green) * (avg_green - green) + (avg_blue - blue)
        * (avg_blue - blue);
    // power of spatial difference between
    // given pixel and cluster center
    double dx_spatial = (avg_x - x) * (avg_x - x) + (avg_y - y)
        * (avg_y - y);
    // Calculate approximate distance D
    // double D = dx_color+dx_spatial*inv;
    // Calculate squares to get more accurate results
    double D = Math.sqrt(dx_color) + Math.sqrt(dx_spatial * inv);
    return D;
  }
}1.

五:参考这里

该滤镜是SuperPixel算法的简单应用,多数时候,我们可能更熟悉


K-Means等图像分割算法,其实SuperPixel是图像分割算法之一。


告示一下:


博客从这个月恢复更新,请大家继续关注,之前消失了一年,完


成了本人的第一本关于图像处理的书初稿写作,谢谢大家厚爱

相关文章
|
消息中间件 负载均衡 调度
Docker swarm实现基于Consul和Haproxy的RabbitMQ高可用集群
基于Consul服务发现和Haproxy实现的RabbitMQ高可用的负载均衡集群
|
5月前
|
存储 供应链 前端开发
如何开发一套仓库管理系统?(附架构图+流程图+代码参考)
仓库管理系统(WMS)是现代物流与供应链管理的重要工具。本文介绍WMS的系统架构、功能模块、业务流程设计及开发实现,帮助企业提升库存管理效率,降低错误率,实现自动化操作,提供实用的开发方案。
|
存储 Linux
linux查看系统版本、内核信息、操作系统类型版本
linux查看系统版本、内核信息、操作系统类型版本
1052 9
|
小程序 开发者
微信小程序之网络数据请求 wx:request的简单使用
这篇文章介绍了微信小程序中如何使用wx.request进行网络数据请求,包括请求的配置、请求的格式以及如何在开发阶段关闭请求的合法检验。
微信小程序之网络数据请求 wx:request的简单使用
|
存储 安全 云计算
云计算核心概念与关键技术简介
本文介绍了云计算的基本概念、技术基础、服务模式(IaaS、PaaS、SaaS)及其关键技术,如虚拟化、容器技术、云存储和多租户管理等。云计算通过按需付费、灵活扩展、高可用性等特点,显著降低了企业的IT成本,加速了业务创新,推动了各行各业的智能化转型。
4920 0
|
机器学习/深度学习 算法 Go
【博士每天一篇文献-算法】Progressive Neural Networks
本文介绍了渐进式网络(Progressive Neural Networks),一种深度强化学习架构,通过在训练过程中学习预训练模型间的侧向连接实现跨任务知识迁移,有效利用迁移学习优势同时避免灾难性遗忘,并通过强化学习任务验证了架构性能。
653 1
|
存储 人工智能 搜索推荐
[AI Mem0] 结合Mem0编写有状态AI应用,让应用更智能、更个性化
[AI Mem0] 结合Mem0编写有状态AI应用,让应用更智能、更个性化
|
缓存 前端开发 JavaScript
优化前端性能:提升网页加载速度的10个技巧
在当今互联网时代,网页加载速度已成为用户体验的重要指标之一。本文将介绍10个有效的前端优化技巧,帮助开发人员提升网页加载速度,提升用户体验,包括减少HTTP请求、压缩资源、优化图像等方面的实用建议。
|
NoSQL Redis Windows
windows安装redis
windows安装redis
174 0
|
数据库连接 程序员 C#
C#(WPF)连接SQLite数据库,利用ViewModel显示数据
对于入门c#(WPF)的初级程序猿
1743 0
C#(WPF)连接SQLite数据库,利用ViewModel显示数据