您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# Python+OpenCV中如何利用K-Means 聚类进行色彩量化
## 1. 引言
在数字图像处理领域,色彩量化(Color Quantization)是一种重要的技术手段,它通过减少图像中颜色的数量来实现数据压缩、视觉效果优化等目的。本文将详细介绍如何利用Python+OpenCV结合K-Means聚类算法实现高效的色彩量化。
## 2. 色彩量化基础概念
### 2.1 什么是色彩量化
色彩量化是指将一幅图像中使用的颜色数目减少的过程。典型应用包括:
- 将24位真彩色图像转换为8位索引图像
- 图像压缩存储
- 艺术效果生成
- 减少计算复杂度
### 2.2 K-Means算法原理
K-Means是一种经典的聚类算法,其基本步骤为:
1. 随机选择K个初始中心点
2. 将每个数据点分配到最近的中心点
3. 重新计算每个簇的中心点
4. 重复步骤2-3直到收敛
在色彩量化中,我们将每个像素的RGB值作为数据点,通过K-Means找到代表性的颜色中心。
## 3. 环境准备与数据加载
### 3.1 安装必要库
```bash
pip install opencv-python numpy matplotlib
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 加载图像
image = cv2.imread('input.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 转换为RGB格式
# 显示原始图像
plt.figure(figsize=(10, 6))
plt.imshow(image)
plt.title('Original Image')
plt.axis('off')
plt.show()
# 将图像数据转换为适合K-Means的格式
pixel_values = image.reshape((-1, 3))
pixel_values = np.float32(pixel_values) # 转换为float32
def color_quantization(image, k):
# 获取图像尺寸和通道数
(h, w, c) = image.shape
# 将图像数据转换为2D数组
pixel_values = image.reshape((-1, 3))
pixel_values = np.float32(pixel_values)
# 定义K-Means参数
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2)
_, labels, centers = cv2.kmeans(
pixel_values,
k,
None,
criteria,
10,
cv2.KMEANS_RANDOM_CENTERS
)
# 转换回8位值
centers = np.uint8(centers)
# 将每个像素映射到最近的质心
quantized_image = centers[labels.flatten()]
quantized_image = quantized_image.reshape((h, w, c))
return quantized_image, centers
# 设置不同的K值进行实验
k_values = [2, 4, 8, 16, 32, 64]
results = {}
for k in k_values:
quantized_img, colors = color_quantization(image, k)
results[k] = (quantized_img, colors)
plt.figure(figsize=(15, 10))
for i, k in enumerate(k_values, 1):
plt.subplot(2, 3, i)
plt.imshow(results[k][0])
plt.title(f'K={k}')
plt.axis('off')
plt.tight_layout()
plt.show()
def plot_color_palette(colors):
palette = np.zeros((100, len(colors)*100, 3), dtype=np.uint8)
for i, color in enumerate(colors):
palette[:, i*100:(i+1)*100, :] = color
plt.imshow(palette)
plt.axis('off')
plt.figure(figsize=(15, 5))
for i, k in enumerate(k_values, 1):
plt.subplot(1, len(k_values), i)
plot_color_palette(results[k][1])
plt.title(f'K={k}')
plt.tight_layout()
plt.show()
对于大图像,可以采样部分像素进行聚类:
def sampled_quantization(image, k, sample_ratio=0.2):
h, w = image.shape[:2]
sample_size = int(h * w * sample_ratio)
indices = np.random.choice(h * w, sample_size, replace=False)
samples = image.reshape((-1, 3))[indices]
samples = np.float32(samples)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2)
_, labels, centers = cv2.kmeans(
samples, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS
)
# 对整个图像进行标签预测
pixel_values = image.reshape((-1, 3))
pixel_values = np.float32(pixel_values)
distances = np.linalg.norm(
pixel_values[:, np.newaxis] - centers, axis=2
)
labels = np.argmin(distances, axis=1)
centers = np.uint8(centers)
quantized_image = centers[labels]
quantized_image = quantized_image.reshape((h, w, 3))
return quantized_image, centers
使用K-Means++初始化策略:
_, labels, centers = cv2.kmeans(
pixel_values,
k,
None,
criteria,
10,
cv2.KMEANS_PP_CENTERS # 使用K-Means++初始化
)
def extract_dominant_colors(image, k=5):
quantized, colors = color_quantization(image, k)
# 计算每种颜色的比例
counts = np.bincount(labels.flatten())
percentages = counts / counts.sum()
# 按比例排序
sorted_idx = np.argsort(percentages)[::-1]
return colors[sorted_idx], percentages[sorted_idx]
dominant_colors, percentages = extract_dominant_colors(image, 5)
plt.figure(figsize=(10, 2))
for i, (color, percent) in enumerate(zip(dominant_colors, percentages)):
plt.fill_between([i, i+1], 0, 1, color=color/255)
plt.text(i+0.5, 0.5, f"{percent:.1%}",
ha='center', va='center', color='white')
plt.xlim(0, 5)
plt.axis('off')
plt.title('Dominant Colors with Percentages')
plt.show()
def posterize(image, k=8):
quantized, _ = color_quantization(image, k)
# 边缘检测
gray = cv2.cvtColor(quantized, cv2.COLOR_RGB2GRAY)
edges = cv2.Canny(gray, 100, 200)
# 合成风格化图像
stylized = quantized.copy()
stylized[edges != 0] = [0, 0, 0] # 添加黑色边缘
return stylized
stylized = posterize(image, 8)
plt.imshow(stylized)
plt.title('Posterized Image with Edges')
plt.axis('off')
plt.show()
from sklearn.cluster import MiniBatchKMeans
from collections import Counter
def median_cut(image, k):
# 实现略,可与K-Means结果比较
pass
方法 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
K-Means | 聚类效果较好,可控制颜色数 | 计算量较大 | 精确控制颜色数 |
Median Cut | 计算速度快 | 颜色分布可能不均匀 | 快速量化 |
Octree | 内存效率高 | 实现复杂 | 大图像处理 |
本文详细介绍了使用Python+OpenCV结合K-Means算法实现色彩量化的完整流程。关键点包括: 1. 图像数据的正确预处理 2. K-Means参数的合理设置 3. 量化结果的评估与可视化
未来改进方向: - 结合空间信息进行聚类 - 自适应确定最佳K值 - 与其他图像处理技术结合
附录:完整代码示例
# 完整色彩量化示例
import cv2
import numpy as np
import matplotlib.pyplot as plt
def main():
# 1. 加载图像
image = cv2.imread('input.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 2. 色彩量化
k = 16
quantized, colors = color_quantization(image, k)
# 3. 显示结果
plt.figure(figsize=(15, 5))
plt.subplot(1, 3, 1)
plt.imshow(image)
plt.title('Original')
plt.axis('off')
plt.subplot(1, 3, 2)
plt.imshow(quantized)
plt.title(f'Quantized (K={k})')
plt.axis('off')
plt.subplot(1, 3, 3)
plot_color_palette(colors)
plt.title('Color Palette')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == '__main__':
main()
”`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。