App基于手机壳颜色换肤?完全做不到吗?这不就“做”出来了!
程序员桌面必备杯垫.JPG KMeans 算法 k -平均算法 (英文: k -means clustering)源于信号处理中的一种向量量化方法,现在则更多地作为一种聚类分析方法流行于数据挖掘领域。 k -平均聚类的目的是:把 n 个点(可以是样本的一次观察或一个实例)划分到 k 个聚类中,使得每个点都属于离他最近的均值(此即聚类中心)对应的聚类,以之作为聚类的标准。这个问题将归结为一个把数据空间划分为Voronoi cells的问题。 进群:548377875 ??即可获取数十套PDF哦! 算法实现 public?List // initialization the pixel data int?width = processor.getWidth(); int?height = processor.getHeight(); byte[] R = processor.getRed(); byte[] G = processor.getGreen(); byte[] B = processor.getBlue(); //Create random points to use a the cluster center Random random =?new?Random(); int?index = 0; for?(int?i = 0; i < numOfCluster; i++) { int?randomNumber1 = random.nextInt(width); int?randomNumber2 = random.nextInt(height); index = randomNumber2 * width + randomNumber1; ClusterCenter cc =?new?ClusterCenter(randomNumber1,randomNumber2,R[index]&0xff,G[index]&0xff,B[index]&0xff); cc.cIndex = i; clusterCenterList.add(cc); } // create all cluster point for?(int?row = 0; row < height; ++row) { for?(int?col = 0; col < width; ++col) { index = row * width + col; pointList.add(new?ClusterPoint(row,col,B[index]&0xff)); } } // initialize the clusters for each point double[] clusterDisValues =?new?double[clusterCenterList.size()]; for(int?i=0; i { for(int?j=0; j { clusterDisValues[j] = calculateEuclideanDistance(pointList.get(i),clusterCenterList.get(j)); } pointList.get(i).clusterIndex = (getCloserCluster(clusterDisValues)); } // calculate the old summary // assign the points to cluster center // calculate the new cluster center // computation the delta value // stop condition-- double[][] oldClusterCenterColors = reCalculateClusterCenters(); int?times = 10; while(true) { stepClusters(); double[][] newClusterCenterColors = reCalculateClusterCenters(); if(isStop(oldClusterCenterColors,newClusterCenterColors)) { break; } else { oldClusterCenterColors = newClusterCenterColors; } if(times > 10) { break; } times++; } //update the result image List for(ClusterCenter cc : clusterCenterList) { colors.add(cc.color); } return?colors; } private?boolean?isStop(double[][] oldClusterCenterColors,?double[][] newClusterCenterColors) { boolean stop = false; for?(int?i = 0; i < oldClusterCenterColors.length; i++) { if?(oldClusterCenterColors[i][0] == newClusterCenterColors[i][0] && oldClusterCenterColors[i][1] == newClusterCenterColors[i][1] && oldClusterCenterColors[i][2] == newClusterCenterColors[i][2]) { stop = true; break; } } return?stop; } /** * update the cluster index by distance value */ private?void?stepClusters() { // initialize the clusters for each point double[] clusterDisValues =?new?double[clusterCenterList.size()]; for(int?i=0; i { for(int?j=0; j { clusterDisValues[j] = calculateEuclideanDistance(pointList.get(i),clusterCenterList.get(j)); } pointList.get(i).clusterIndex = (getCloserCluster(clusterDisValues)); } } /** * using cluster color of each point to update cluster center color * * @return */ private?double[][] reCalculateClusterCenters() { // clear the points now for(int?i=0; i { clusterCenterList.get(i).numOfPoints = 0; } // recalculate the sum and total of points for each cluster double[] redSums =?new?double[numOfCluster]; double[] greenSum =?new?double[numOfCluster]; double[] blueSum =?new?double[numOfCluster]; for(int?i=0; i { int?cIndex = (int)pointList.get(i).clusterIndex; clusterCenterList.get(cIndex).numOfPoints++; int?tr = pointList.get(i).pixelColor.red; int?tg = pointList.get(i).pixelColor.green; int?tb = pointList.get(i).pixelColor.blue; redSums[cIndex] += tr; greenSum[cIndex] += tg; blueSum[cIndex] += tb; } double[][] oldClusterCentersColors =?new?double[clusterCenterList.size()][3]; for(int?i=0; i { double?sum = clusterCenterList.get(i).numOfPoints; int?cIndex = clusterCenterList.get(i).cIndex; int?red = (int)(greenSum[cIndex]/sum); int?green = (int)(greenSum[cIndex]/sum); int?blue = (int)(blueSum[cIndex]/sum); clusterCenterList.get(i).color =?new?Scalar(red,green,blue); oldClusterCentersColors[i][0] = red; oldClusterCentersColors[i][0] = green; oldClusterCentersColors[i][0] = blue; } return?oldClusterCentersColors; } /** * * @param clusterDisValues * @return */ private?double?getCloserCluster(double[] clusterDisValues) { double?min = clusterDisValues[0]; int?clusterIndex = 0; for(int?i=0; i { if(min > clusterDisValues[i]) { min = clusterDisValues[i]; clusterIndex = i; } } return?clusterIndex; } /** * * @param p * @param c * @return distance value */ private?double?calculateEuclideanDistance(ClusterPoint p,ClusterCenter c) { int?pr = p.pixelColor.red; int?pg = p.pixelColor.green; int?pb = p.pixelColor.blue; int?cr = c.color.red; int?cg = c.color.green; int?cb = c.color.blue; return?Math.sqrt(Math.pow((pr - cr),2.0) + Math.pow((pg - cg),2.0) + Math.pow((pb - cb),2.0)); } 在 Android 中使用该算法来提取主色: demo1.png (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |