图像处理------K-Means算法演示

简介: <p style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;"><span style="font-size: 18px;">一:数学原理</span></p><p style="color: rgb(51, 51, 51); font-family: Arial; font

一:数学原理

K-Means算法的作者是MacQueen, 基本的数学原理很容易理解,假设有一个像素

数据集P。我们要根据值不同将它分为两个基本的数据集合Cluster1, Cluster2,使

用K-Means算法大致如下:

假设两个Cluster的RGB值分别为112,225,244和23,34,99则像素集合中的像素点

a(222,212,234), b(198,205,229), c(25,77,52),d(34,55,101)计算每个像素点与这

两个cluster中心点的欧几里德距离,则像素点a, b属于前面一个cluster, c,d属于

后面一个cluster。然后在根据(222+198)/2, (212+205)/2, (234+52)/2更新cluster

的RGB值,对后一个cluster做同样处理。然后再计算每个像素点到cluster中心点

的欧几里德距离。最终值没有变化则得到分类Cluster点集合。

二:算法基本流程


三:算法关键代码解析

初始化cluster中心点代码如下:

[java]  view plain copy
  1. Random random = new Random();  
  2. for (int i = 0; i < numOfCluster; i++)  
  3. {  
  4.     int randomNumber1 = random.nextInt(width);  
  5.     int randomNumber2 = random.nextInt(height);  
  6.     index = randomNumber2 * width + randomNumber1;  
  7.     ClusterCenter cc = new ClusterCenter(randomNumber1, randomNumber2, inPixels[index]);  
  8.     cc.setcIndex(i);  
  9.     clusterCenterList.add(cc);   
  10. }  

初始化所有像素点代码如下:

[java]  view plain copy
  1. // create all cluster point  
  2. for (int row = 0; row < height; ++row)  
  3. {  
  4.     for (int col = 0; col < width; ++col)  
  5.     {  
  6.         index = row * width + col;  
  7.         int color = inPixels[index];  
  8.         pointList.add(new ClusterPoint(row, col, color));  
  9.   
  10.     }  
  11. }  

计算两个像素点之间欧几里德距离的代码如下:

[java]  view plain copy
  1. // int pa = (p.getPixelColor() >> 24) & 0xff;  
  2. int pr = (p.getPixelColor() >> 16) & 0xff;  
  3. int pg = (p.getPixelColor() >> 8) & 0xff;  
  4. int pb = p.getPixelColor() & 0xff;  
  5. // int ca = (c.getPixelColor() >> 24) & 0xff;  
  6. int cr = (c.getPixelColor() >> 16) & 0xff;  
  7. int cg = (c.getPixelColor() >> 8) & 0xff;  
  8. int cb = c.getPixelColor() & 0xff;  
  9.   
  10. return Math.sqrt(Math.pow((pr - cr), 2.0) + Math.pow((pg - cg), 2.0) + Math.pow((pb - cb), 2.0));  
重新计算Cluster中心点RGB值的代码如下:

[java]  view plain copy
  1. private double[] reCalculateClusterCenters() {  
  2.       
  3.     // clear the points now  
  4.     for(int i=0; i<clusterCenterList.size(); i++)  
  5.     {  
  6.          clusterCenterList.get(i).setNumOfPoints(0);  
  7.     }  
  8.       
  9.     // recalculate the sum and total of points for each cluster  
  10.     double[] redSums = new double[3];  
  11.     double[] greenSum = new double[3];  
  12.     double[] blueSum = new double[3];  
  13.     for(int i=0; i<pointList.size(); i++)  
  14.     {  
  15.         int cIndex = (int)pointList.get(i).getClusterIndex();  
  16.         clusterCenterList.get(cIndex).addPoints();  
  17.         int ta = (pointList.get(i).getPixelColor() >> 24) & 0xff;  
  18.         int tr = (pointList.get(i).getPixelColor() >> 16) & 0xff;  
  19.         int tg = (pointList.get(i).getPixelColor() >> 8) & 0xff;  
  20.         int tb = pointList.get(i).getPixelColor() & 0xff;  
  21.         ta = 255;  
  22.         redSums[cIndex] += tr;  
  23.         greenSum[cIndex] += tg;  
  24.         blueSum[cIndex] += tb;  
  25.     }  
  26.       
  27.     double[] oldClusterCentersColors = new double[clusterCenterList.size()];  
  28.     for(int i=0; i<clusterCenterList.size(); i++)  
  29.     {  
  30.         double sum  = clusterCenterList.get(i).getNumOfPoints();  
  31.         int cIndex = clusterCenterList.get(i).getcIndex();  
  32.         int red = (int)(greenSum[cIndex]/sum);  
  33.         int green = (int)(greenSum[cIndex]/sum);  
  34.         int blue = (int)(blueSum[cIndex]/sum);  
  35.         System.out.println("red = " + red + " green = " + green + " blue = " + blue);  
  36.         int clusterColor = (255 << 24) | (red << 16) | (green << 8) | blue;  
  37.         clusterCenterList.get(i).setPixelColor(clusterColor);  
  38.         oldClusterCentersColors[i] = clusterColor;  
  39.     }  
  40.       
  41.     return oldClusterCentersColors;  
  42. }  

四:运行效果


五:K-Means算法源代码

[java]  view plain copy
  1. package com.gloomyfish.segmentation.kmeans;  
  2.   
  3. import java.awt.image.BufferedImage;  
  4. import java.util.ArrayList;  
  5. import java.util.List;  
  6. import java.util.Random;  
  7.   
  8. import com.gloomyfish.filter.study.AbstractBufferedImageOp;  
  9. import com.gloomyfish.segmentation.fuzzycmeans.ClusterPoint;  
  10.   
  11. public class KMeansProcessor extends AbstractBufferedImageOp {  
  12.     private List<ClusterCenter> clusterCenterList;  
  13.     private List<ClusterPoint> pointList;  
  14.       
  15.     private int numOfCluster;  
  16.       
  17.     public KMeansProcessor(int clusters)  
  18.     {  
  19.         this.numOfCluster = clusters;  
  20.         pointList = new ArrayList<ClusterPoint>();  
  21.         this.clusterCenterList = new ArrayList<ClusterCenter>();  
  22.     }  
  23.   
  24.     @Override  
  25.     public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
  26.         // initialization the pixel data  
  27.         int width = src.getWidth();  
  28.         int height = src.getHeight();  
  29.         int[] inPixels = new int[width*height];  
  30.         src.getRGB( 00, width, height, inPixels, 0, width );  
  31.         int index = 0;  
  32.           
  33.         //Create random points to use a the cluster center  
  34.         Random random = new Random();  
  35.         for (int i = 0; i < numOfCluster; i++)  
  36.         {  
  37.             int randomNumber1 = random.nextInt(width);  
  38.             int randomNumber2 = random.nextInt(height);  
  39.             index = randomNumber2 * width + randomNumber1;  
  40.             ClusterCenter cc = new ClusterCenter(randomNumber1, randomNumber2, inPixels[index]);  
  41.             cc.setcIndex(i);  
  42.             clusterCenterList.add(cc);   
  43.         }  
  44.           
  45.         // create all cluster point  
  46.         for (int row = 0; row < height; ++row)  
  47.         {  
  48.             for (int col = 0; col < width; ++col)  
  49.             {  
  50.                 index = row * width + col;  
  51.                 int color = inPixels[index];  
  52.                 pointList.add(new ClusterPoint(row, col, color));  
  53.   
  54.             }  
  55.         }  
  56.           
  57.         // initialize the clusters for each point  
  58.         double[] clusterDisValues = new double[clusterCenterList.size()];  
  59.         for(int i=0; i<pointList.size(); i++)  
  60.         {  
  61.             for(int j=0; j<clusterCenterList.size(); j++)  
  62.             {  
  63.                 clusterDisValues[j] = calculateEuclideanDistance(pointList.get(i), clusterCenterList.get(j));  
  64.             }  
  65.             pointList.get(i).setClusterIndex(getCloserCluster(clusterDisValues));  
  66.         }  
  67.           
  68.         // calculate the old summary  
  69.         // assign the points to cluster center  
  70.         // calculate the new cluster center  
  71.         // computation the delta value  
  72.         // stop condition--  
  73.         double[] oldClusterCenterColors = reCalculateClusterCenters();  
  74.         while(true)  
  75.         {  
  76.             stepClusters();  
  77.             double[] newClusterCenterColors = reCalculateClusterCenters();  
  78.             if(isStop(oldClusterCenterColors, newClusterCenterColors))  
  79.             {                 
  80.                 break;  
  81.             }   
  82.             else  
  83.             {  
  84.                 oldClusterCenterColors = newClusterCenterColors;  
  85.             }  
  86.         }  
  87.           
  88.         //update the result image  
  89.         dest = createCompatibleDestImage(src, null );  
  90.         index = 0;  
  91.         int[] outPixels = new int[width*height];         
  92.         for (int j = 0; j < pointList.size(); j++)  
  93.         {  
  94.             for (int i = 0; i < clusterCenterList.size(); i++)  
  95.             {  
  96.                 ClusterPoint p = this.pointList.get(j);  
  97.                 if (clusterCenterList.get(i).getcIndex() == p.getClusterIndex())  
  98.                 {  
  99.                     int row = (int)p.getX(); // row  
  100.                     int col = (int)p.getY(); // column  
  101.                     index = row * width + col;  
  102.                     outPixels[index] = clusterCenterList.get(i).getPixelColor();  
  103.                 }  
  104.             }  
  105.         }  
  106.           
  107.         // fill the pixel data  
  108.         setRGB( dest, 00, width, height, outPixels );  
  109.         return dest;  
  110.     }  
  111.       
  112.     private boolean isStop(double[] oldClusterCenterColors, double[] newClusterCenterColors) {  
  113.         for(int i=0; i<oldClusterCenterColors.length; i++)  
  114.         {  
  115.             System.out.println("cluster " + i + " old : " + oldClusterCenterColors[i] + ", new : " + newClusterCenterColors[i]);  
  116.             if(oldClusterCenterColors[i]  != newClusterCenterColors[i])   
  117.             {  
  118.                 return false;  
  119.             }  
  120.         }  
  121.         System.out.println();  
  122.         return true;  
  123.     }  
  124.   
  125.     /** 
  126.      * update the cluster index by distance value 
  127.      */  
  128.     private void stepClusters()   
  129.     {  
  130.         // initialize the clusters for each point  
  131.         double[] clusterDisValues = new double[clusterCenterList.size()];  
  132.         for(int i=0; i<pointList.size(); i++)  
  133.         {  
  134.             for(int j=0; j<clusterCenterList.size(); j++)  
  135.             {  
  136.                 clusterDisValues[j] = calculateEuclideanDistance(pointList.get(i), clusterCenterList.get(j));  
  137.             }  
  138.             pointList.get(i).setClusterIndex(getCloserCluster(clusterDisValues));  
  139.         }  
  140.           
  141.     }  
  142.   
  143.     /** 
  144.      * using cluster color of each point to update cluster center color 
  145.      *  
  146.      * @return 
  147.      */  
  148.     private double[] reCalculateClusterCenters() {  
  149.           
  150.         // clear the points now  
  151.         for(int i=0; i<clusterCenterList.size(); i++)  
  152.         {  
  153.              clusterCenterList.get(i).setNumOfPoints(0);  
  154.         }  
  155.           
  156.         // recalculate the sum and total of points for each cluster  
  157.         double[] redSums = new double[3];  
  158.         double[] greenSum = new double[3];  
  159.         double[] blueSum = new double[3];  
  160.         for(int i=0; i<pointList.size(); i++)  
  161.         {  
  162.             int cIndex = (int)pointList.get(i).getClusterIndex();  
  163.             clusterCenterList.get(cIndex).addPoints();  
  164.             int ta = (pointList.get(i).getPixelColor() >> 24) & 0xff;  
  165.             int tr = (pointList.get(i).getPixelColor() >> 16) & 0xff;  
  166.             int tg = (pointList.get(i).getPixelColor() >> 8) & 0xff;  
  167.             int tb = pointList.get(i).getPixelColor() & 0xff;  
  168.             ta = 255;  
  169.             redSums[cIndex] += tr;  
  170.             greenSum[cIndex] += tg;  
  171.             blueSum[cIndex] += tb;  
  172.         }  
  173.           
  174.         double[] oldClusterCentersColors = new double[clusterCenterList.size()];  
  175.         for(int i=0; i<clusterCenterList.size(); i++)  
  176.         {  
  177.             double sum  = clusterCenterList.get(i).getNumOfPoints();  
  178.             int cIndex = clusterCenterList.get(i).getcIndex();  
  179.             int red = (int)(greenSum[cIndex]/sum);  
  180.             int green = (int)(greenSum[cIndex]/sum);  
  181.             int blue = (int)(blueSum[cIndex]/sum);  
  182.             System.out.println("red = " + red + " green = " + green + " blue = " + blue);  
  183.             int clusterColor = (255 << 24) | (red << 16) | (green << 8) | blue;  
  184.             clusterCenterList.get(i).setPixelColor(clusterColor);  
  185.             oldClusterCentersColors[i] = clusterColor;  
  186.         }  
  187.           
  188.         return oldClusterCentersColors;  
  189.     }  
  190.       
  191.       
  192.   
  193.     /** 
  194.      *  
  195.      * @param clusterDisValues 
  196.      * @return 
  197.      */  
  198.     private double getCloserCluster(double[] clusterDisValues)  
  199.     {  
  200.         double min = clusterDisValues[0];  
  201.         int clusterIndex = 0;  
  202.         for(int i=0; i<clusterDisValues.length; i++)  
  203.         {  
  204.             if(min > clusterDisValues[i])  
  205.             {  
  206.                 min = clusterDisValues[i];  
  207.                 clusterIndex = i;  
  208.             }  
  209.         }  
  210.         return clusterIndex;  
  211.     }  
  212.   
  213.     /** 
  214.      *  
  215.      * @param point 
  216.      * @param cluster 
  217.      * @return distance value 
  218.      */  
  219.     private double calculateEuclideanDistance(ClusterPoint p, ClusterCenter c)   
  220.     {  
  221.         // int pa = (p.getPixelColor() >> 24) & 0xff;  
  222.         int pr = (p.getPixelColor() >> 16) & 0xff;  
  223.         int pg = (p.getPixelColor() >> 8) & 0xff;  
  224.         int pb = p.getPixelColor() & 0xff;  
  225.         // int ca = (c.getPixelColor() >> 24) & 0xff;  
  226.         int cr = (c.getPixelColor() >> 16) & 0xff;  
  227.         int cg = (c.getPixelColor() >> 8) & 0xff;  
  228.         int cb = c.getPixelColor() & 0xff;  
  229.           
  230.         return Math.sqrt(Math.pow((pr - cr), 2.0) + Math.pow((pg - cg), 2.0) + Math.pow((pb - cb), 2.0));  
  231.     }  
  232.   
  233. }  
相关文章
|
数据采集 机器学习/深度学习 算法
|
2月前
|
canal 算法 vr&ar
【图像处理】基于电磁学优化算法的多阈值分割算法研究(Matlab代码实现)
【图像处理】基于电磁学优化算法的多阈值分割算法研究(Matlab代码实现)
121 1
|
12月前
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
1150 6
|
数据采集 机器学习/深度学习 算法
【优秀设计案例】基于K-Means聚类算法的球员数据聚类分析设计与实现
本文通过K-Means聚类算法对NBA球员数据进行聚类分析,旨在揭示球员间的相似性和差异性,为球队管理、战术决策和球员评估提供数据支持,并通过特征工程和结果可视化深入理解球员表现和潜力。
642 1
【优秀设计案例】基于K-Means聚类算法的球员数据聚类分析设计与实现
|
数据采集 算法 数据可视化
基于Python的k-means聚类分析算法的实现与应用,可以用在电商评论、招聘信息等各个领域的文本聚类及指标聚类,效果很好
本文介绍了基于Python实现的k-means聚类分析算法,并通过微博考研话题的数据清洗、聚类数量评估、聚类分析实现与结果可视化等步骤,展示了该算法在文本聚类领域的应用效果。
612 1
|
9月前
|
监控 算法 安全
内网桌面监控软件深度解析:基于 Python 实现的 K-Means 算法研究
内网桌面监控软件通过实时监测员工操作,保障企业信息安全并提升效率。本文深入探讨K-Means聚类算法在该软件中的应用,解析其原理与实现。K-Means通过迭代更新簇中心,将数据划分为K个簇类,适用于行为分析、异常检测、资源优化及安全威胁识别等场景。文中提供了Python代码示例,展示如何实现K-Means算法,并模拟内网监控数据进行聚类分析。
245 10
|
数据采集 资源调度 算法
【数据挖掘】十大算法之K-Means K均值聚类算法
K-Means聚类算法的基本介绍,包括算法步骤、损失函数、优缺点分析以及如何优化和改进算法的方法,还提到了几种改进的K-Means算法,如K-Means++和ISODATA算法。
1692 4
|
数据采集 算法 数据可视化
基于K-Means聚类算法对球员数据的聚类分析,可以自主寻找最优聚类数进行聚类
本文介绍了一个基于K-Means聚类算法的NBA球员数据分析项目,该项目通过采集和分析球员的得分、篮板、助攻等统计数据,使用轮廓系数法和拐点法确定最优聚类数,将球员分为不同群组,并提供了一个可视化界面以便直观比较不同群组的球员表现。
284 0
基于K-Means聚类算法对球员数据的聚类分析,可以自主寻找最优聚类数进行聚类
|
机器学习/深度学习 算法 数据挖掘
基于改进K-means的网络数据聚类算法matlab仿真
**摘要:** K-means聚类算法分析,利用MATLAB2022a进行实现。算法基于最小化误差平方和,优点在于简单快速,适合大数据集,但易受初始值影响。文中探讨了该依赖性并通过实验展示了随机初始值对结果的敏感性。针对传统算法的局限,提出改进版解决孤点影响和K值选择问题。代码中遍历不同K值,计算距离代价,寻找最优聚类数。最终应用改进后的K-means进行聚类分析。
292 10
|
算法 数据可视化 搜索推荐
基于python的k-means聚类分析算法,对文本、数据等进行聚类,有轮廓系数和手肘法检验
本文详细介绍了基于Python实现的k-means聚类分析算法,包括数据准备、预处理、标准化、聚类数目确定、聚类分析、降维可视化以及结果输出的完整流程,并应用该算法对文本数据进行聚类分析,展示了轮廓系数法和手肘法检验确定最佳聚类数目的方法。
592 0

热门文章

最新文章

下一篇
oss云网关配置