写点什么

App 基于手机壳颜色换肤?先尝试一下用 KMeans 来提取图像中的主色

用户头像
Android架构
关注
发布于: 1 小时前

double[] clusterDisValues = new double[clusterCenterList.size()];for(int i=0; i<pointList.size(); i++){for(int j=0; j<clusterCenterList.size(); 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(oldClusterCenterColor


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


s, newClusterCenterColors)){ break;}else{oldClusterCenterColors = newClusterCenterColors;}if(times > 10) {break;}times++;}


//update the result imageList<Scalar> colors = new ArrayList<Scalar>();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 pointdouble[] clusterDisValues = new double[clusterCenterList.size()];for(int i=0; i<pointList.size(); i++){for(int j=0; j<clusterCenterList.size(); 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 nowfor(int i=0; i<clusterCenterList.size(); i++){clusterCenterList.get(i).numOfPoints = 0;}


// recalculate the sum and total of points for each clusterdouble[] redSums = new double[numOfCluster];double[] greenSum = new double[numOfCluster];double[] blueSum = new double[numOfCluster];for(int i=0; i<pointList.size(); 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<clusterCenterList.size(); 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<clusterDisValues.length; 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 中使用该算法来提取主色:




完整的算法实现可以在:github.com/imageproces… 找到,它是一个典型的 KMeans 算法。


我们的算法中,K 默认值是 5,当然也可以自己指定。


以上算法目前在 demo 上耗时蛮久,不过可以有优化空间。例如,可以使用 RxJava 在 computation 线程中做复杂的计算操作然后切换回 ui 线程。亦或者可以使用类似 Kotlin 的 Coroutines 来做复杂的计算操作然后切换回 ui 线程。总结

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
App基于手机壳颜色换肤?先尝试一下用 KMeans 来提取图像中的主色