Skip to content

Instantly share code, notes, and snippets.

@linkgod
Created June 22, 2020 12:31
Show Gist options
  • Save linkgod/d0aa7766823fe5762484aa41580055a1 to your computer and use it in GitHub Desktop.
Save linkgod/d0aa7766823fe5762484aa41580055a1 to your computer and use it in GitHub Desktop.
function getRGBCluster(k = 3, rRange = 255, gRange = 255, bRange = 255) {
function equal(means, newMeans) {
return means.every((mean, index) =>
mean[0] === newMeans[index][0]
&& mean[1] === newMeans[index][1]
&& mean[2] === newMeans[index][2]
)
}
function assignment(data, means) {
const clusters = Array(means.length).fill().map(() => [])
// 对每个点进行分类
data.forEach(point => {
let minIndex = 0;
means.reduce((prev, mean, index) => {
const distance = euclideanDistance(point, mean);
if (distance < prev) {
minIndex = index;
return distance
}
return prev;
}, Number.MAX_VALUE)
clusters[minIndex].push(point);
});
const newMeans = clusters.map(cluster => average(cluster))
return newMeans;
}
// 获取所有的颜色,调整步长可以减少样本集合的数量
function getColors(rRange, gRange, bRange) {
const colors = [];
let [r, g, b] = [];
for (r = 0; r <= rRange; r += 1) {
for (g = 0; g <= gRange; g += 1) {
for (b = 0; b <= bRange; b += 1) {
colors.push([r, g, b]);
}
}
}
return colors;
}
function getMeans(k, originData) {
const means = [];
const data = [].concat(originData);
while(k--) {
const index = Math.floor(Math.random() * data.length);
means.push(data[index]);
data.splice(index, 1);
}
return means;
}
// 计算欧几里得距离
function euclideanDistance(point1, point2) {
return Math.sqrt(
Math.pow(point1[0] - point2[0], 2)
+ Math.pow(point1[1] - point2[1], 2)
+ Math.pow(point1[2] - point2[2], 2)
)
}
// 计算平均点
function average(colors) {
return colors
.reduce(
(sum, color) => [sum[0] + color[0], sum[1] + color[1], sum[2] + color[2]],
[0, 0, 0]
)
.map(sum => sum / colors.length)
}
const colors = getColors(rRange, gRange, bRange);
let means = getMeans(k, colors);
console.log(`means:`, means)
let newMeans = assignment(colors, means);
console.log(`newMeans:`, newMeans)
let count = 0;
while(!equal(means, newMeans)) {
means = newMeans;
newMeans = assignment(colors, means);
count += 1;
}
return newMeans;
}
console.log(getRGBCluster(3, 100, 100, 100));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment