Rust图像处理库kmeans_colors的使用:高效K均值聚类算法实现图像色彩量化与调色板生成
Rust图像处理库kmeans_colors的使用:高效K均值聚类算法实现图像色彩量化与调色板生成
kmeans-colors是一个使用k-means++初始化的k-means聚类算法来计算图像中k种平均颜色的Rust库。
基本用法
k-means聚类的工作原理是从图像中随机猜测k种颜色(称为质心)开始。对于每个步骤,遍历图像中的每个像素以找到颜色最接近它的质心。然后,质心计算所有接近它们的颜色的平均值并移动到该颜色。这个过程重复进行,直到质心停止移动或达到最大步数。
kmeans_colors -i gfx/pink.jpg -k 2 -o pink2
调色板生成
kmeans_colors -i gfx/mountains.jpg --no-file --palette
kmeans_colors -i gfx/pink.jpg --no-file --palette --proportional
kmeans_colors -i gfx/flowers.jpg --no-file --palette --proportional --sort
完整示例代码
use kmeans_colors::{get_kmeans, Kmeans, Sort};
use palette::{Lab, Pixel, Srgb};
use image::{open, RgbImage};
fn main() {
// 打开图像文件
let img = open("input.jpg").unwrap().to_rgb8();
// 将图像像素转换为Lab颜色空间
let lab: Vec<Lab> = img.pixels()
.map(|p| Srgb::new(
p[0] as f32 / 255.0,
p[1] as f32 / 255.0,
p[2] as f32 / 255.0
).into())
.collect();
// 设置k-means参数
let k = 8; // 要提取的颜色数量
let max_iter = 20; // 最大迭代次数
let converge = 1.0; // 收敛因子
let runs = 3; // 运行次数
// 执行k-means聚类
let kmeans = get_kmeans(
&lab,
k,
max_iter,
converge,
runs,
0 // 随机种子
);
// 获取聚类结果
let result = kmeans.result;
let dominant_colors = result.centroids;
// 按颜色频率排序
let sorted = Sort::sort_indexed_colors(&result.indices, &dominant_colors);
// 打印主要颜色
for (i, color) in sorted.centroids.iter().enumerate() {
let rgb: Srgb = Srgb::from(*color);
let pixel = rgb.into_format().into_raw();
println!(
"Color {}: #{:02x}{:02x}{:02x} - {:.2}%",
i+1,
(pixel[0] * 255.0) as u8,
(pixel[1] * 255.0) as u8,
(pixel[2] * 255.0) as u8,
sorted.percentage[i] * 100.0
);
}
// 生成量化图像
let mut quantized = RgbImage::new(img.width(), img.height());
for (i, &idx) in result.indices.iter().enumerate() {
let rgb: Srgb = Srgb::from(dominant_colors[idx]);
let pixel = rgb.into_format().into_raw();
let x = i as u32 % img.width();
let y = i as u32 / img.width();
quantized.put_pixel(x, y, image::Rgb([
(pixel[0] * 255.0) as u8,
(pixel[1] * 255.0) as u8,
(pixel[2] * 255.0) as u8
]));
}
// 保存结果
quantized.save("quantized.png").unwrap();
}
特性
- 从图像创建调色板
- Lab色彩空间或RGB色彩空间计算
- 查找与输入颜色最接近的颜色
- 用自定义颜色替换颜色
- 可调整的迭代次数和重复次数
- 打印平均颜色
- 打印图像中每种颜色的百分比
- 透明度支持
- kmeans++中心初始化
- 支持多图像输入进行批量处理
- 指定随机种子以获得可重现的结果
安装
在Cargo.toml中添加:
[dependencies.kmeans_colors]
version = "0.6"
default-features = false
许可证
MIT或Apache-2.0
1 回复
Rust图像处理库kmeans_colors的使用:高效K均值聚类算法实现图像色彩量化与调色板生成
kmeans_colors
是一个基于Rust的高效图像处理库,专门用于实现K均值聚类算法进行图像色彩量化和调色板生成。该库提供了简单易用的API,能够帮助开发者快速实现图像色彩压缩、主题色提取等功能。
主要特性
- 高效的K均值聚类算法实现
- 支持多种色彩空间(RGB, Lab等)
- 并行处理加速计算
- 可定制的聚类参数
- 轻量级且无依赖
安装方法
在Cargo.toml中添加依赖:
[dependencies]
kmeans_colors = "0.5"
image = "0.24" # 用于图像加载和保存
基本使用方法
1. 从图像中提取调色板
use kmeans_colors::{get_kmeans, Kmeans, Calculate};
use image::{io::Reader, RgbImage};
fn main() {
// 加载图像
let img = Reader::open("input.jpg")
.unwrap()
.decode()
.unwrap()
.into_rgb8();
// 将图像像素转换为Vec<[f32;3]>
let pixels: Vec<[f32; 3]> = img.pixels()
.map(|p| [p[0] as f32, p[1] as f32, p[2] as f32])
.collect();
// 运行K均值聚类算法
let k = 8; // 聚类数量
let max_iter = 20; // 最大迭代次数
let converge = 1.0; // 收敛阈值
let kmeans = get_kmeans(
&pixels,
k,
max_iter,
converge,
Kmeans::init_kmeanplusplus,
&Calculate::default(),
);
// 获取聚类中心(调色板)
let palette = kmeans.centroids;
println!("提取的调色板颜色:");
for color in palette {
println!("RGB: {:?}", color);
}
}
2. 图像色彩量化
use kmeans_colors::{get_kmeans, Kmeans, Calculate};
use image::{io::Reader, RgbImage, Rgb};
fn main() {
// 加载图像
let mut img = Reader::open("input.jpg")
.unwrap()
.decode()
.unwrap()
.into_rgb8();
let pixels: Vec<[f32; 3]> = img.pixels()
.map(|p| [p[0] as f32, p[1] as f32, p[2] as f32])
.collect();
let k = 8;
let kmeans = get_kmeans(
&pixels,
k,
20,
1.0,
Kmeans::init_kmeanplusplus,
&Calculate::default(),
);
// 将每个像素替换为最近的聚类中心颜色
let result = kmeans.map_to極d(&pixels);
// 更新图像
for (i, pixel) in img.pixels_mut().enumerate() {
let rgb = result[i];
*pixel = Rgb([
rgb[0] as u8,
rgb[1] as u8,
rgb[2] as u8,
]);
}
// 保存结果
img.save("output.jpg").unwrap();
}
3. 使用Lab色彩空间获得更准确的结果
use kmeans_colors::{get_kmeans_hsv, Kmeans, Calculate};
use palette::{Srgb, IntoColor};
fn main() {
// 假设我们已经有了像素数据
let pixels: Vec<[f32; 3]> = /* ... */;
// 转换为Lab色彩空间
let lab_pixels: Vec<_> = pixels.iter()
.map(|&rgb| {
let srgb = Srgb::new(rgb[0], rgb[1], rgb[2]);
srgb.into_color::<palette::Lab>().to_components()
})
.collect();
let k = 5;
let kmeans = get_kmeans(
&lab_pixels,
k,
20,
1.0,
Kmeans::init_kmeanplusplus,
&Calculate::default(),
);
// 处理结果...
}
高级用法
自定义初始化方法
use kmeans_colors::{get_kmeans, Kmeans, Calculate};
fn custom_init(pixels: &[[f32; 3]], k: usize) -> Vec<[f32; 3]> {
// 实现自定义的聚类中心初始化逻辑
// 例如随机选择k个像素作为初始中心
use rand::seq::SliceRandom;
let mut rng = rand::thread_rng();
pixels.choose_multiple(&mut rng, k)
.cloned()
.collect()
}
let kmeans = get_kmeans(
&pixels,
k,
max_iter,
converge,
custom_init,
&Calculate::default(),
);
并行处理加速
use kmeans_colors::{get_kmeans_par, Kmeans, Calculate};
let kmeans = get_kmeans_par( // 注意这里使用_par版本
&pixels,
k,
max_iter,
converge,
Kmeans::init_kmeanplusplus,
&Calculate::default(),
);
性能优化建议
- 对于大图像,可以先缩小图像尺寸再进行聚类
- 调整
max_iter
和converge
参数平衡速度与精度 - 使用Lab色彩空间可能获得更符合人眼感知的结果
- 启用并行处理加速计算
kmeans_colors
库为Rust开发者提供了强大而高效的图像色彩处理能力,特别适合需要图像主题色提取、色彩压缩等功能的场景。
完整示例代码
下面是一个完整的示例,展示了如何使用kmeans_colors库从图像中提取调色板并进行色彩量化:
use kmeans_colors::{get_kmeans_par, Kmeans, Calculate};
use image::{io::Reader, RgbImage, Rgb};
use palette::{Srgb, IntoColor};
use std::time::Instant;
fn main() {
// 1. 加载图像
let start = Instant::now();
let mut img = Reader::open("input.jpg")
.expect("无法打开图像文件")
.decode()
.expect("无法解码图像")
.into_rgb8();
println!("图像加载耗时: {:?}", start.elapsed());
// 2. 准备像素数据
let pixels: Vec<[f32; 3]> = img.pixels()
.map(|p| [p[0] as f32, p[1] as f32, p[2] as f32])
.collect();
// 3. 转换为Lab色彩空间(更符合人眼感知)
let lab_start = Instant::now();
let lab_pixels: Vec<_> = pixels.iter()
.map(|&rgb| {
Srgb::new(rgb[0], rgb[1], rgb[2])
.into_color::<palette::Lab>()
.to_components()
})
.collect();
println!("色彩空间转换耗时: {:?}", lab_start.elapsed());
// 4. 运行K均值聚类算法
let k = 8; // 要提取的颜色数量
let max_iter = 20; // 最大迭代次数
let converge = 1.0; // 收敛阈值
let kmeans_start = Instant::now();
let kmeans = get_kmeans_par(
&lab_pixels,
k,
max_iter,
converge,
Kmeans::init_kmeanplusplus,
&Calculate::default(),
);
println!("K均值聚类耗时: {:?}", kmeans_start.elapsed());
// 5. 获取调色板(RGB格式)
let palette = kmeans.centroids.iter()
.map(|&lab| {
let lab = palette::Lab::from_components(lab);
let rgb = Srgb::from_color(lab);
[rgb.red, rgb.green, rgb.blue]
})
.collect::<Vec<_>>();
println!("\n提取的调色板颜色(RGB):");
for (i, color) in palette.iter().enumerate() {
println!("颜色{}: [{:.1}, {:.1}, {:.1}]", i+1, color[0], color[1], color[2]);
}
// 6. 图像色彩量化
let quant_start = Instant::now();
let result = kmeans.map_to_centroids(&lab_pixels);
// 更新图像像素
for (i, pixel) in img.pixels_mut().enumerate() {
let rgb = palette[result[i].cluster as usize];
*pixel = Rgb([
(rgb[0] * 255.0).round() as u8,
(rgb[1] * 255.0).round() as u8,
(rgb[2] * 255.0).round() as u8,
]);
}
println!("色彩量化耗时: {:?}", quant_start.elapsed());
// 7. 保存结果
img.save("output.png").expect("无法保存图像");
println!("\n总耗时: {:?}", start.elapsed());
}
这个完整示例包含了以下功能:
- 图像加载与预处理
- RGB到Lab色彩空间的转换
- 使用并行K均值聚类算法提取调色板
- 将结果转换回RGB色彩空间
- 图像色彩量化处理
- 性能计时和结果输出
你可以根据需要调整聚类数量k、最大迭代次数等参数来获得不同的效果。