1. 项目概述
拼豆艺术作为一种新兴的手工创作形式,近年来在手工爱好者圈层中迅速走红。与传统像素画不同,拼豆作品通过有限颜色的塑料豆粒排列组合,形成各种图案和造型。在这个过程中,如何将原始图像转换为适合拼豆制作的有限色板方案,成为了创作者面临的核心技术挑战。
我最近开发了一套专门针对拼豆艺术的图像颜色聚类算法,通过结合K-Means和层次聚类的优势,实现了从真彩图像到有限色板的智能转换。这个方案特别考虑了手工制作场景中的实际需求,比如色板限制、相邻色区分度等问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心算法原理
2.1 颜色空间选择
在图像处理领域,选择合适的颜色空间对聚类效果至关重要。经过多次实验对比,我最终采用了LAB颜色空间而非常规的RGB空间,原因在于:
- LAB空间的色度(L)与颜色信息(AB)分离,更符合人类视觉感知
- 在LAB空间中,欧式距离与人眼感知的颜色差异更接近
- 特别适合处理拼豆常见的红、黄、蓝等高饱和度颜色
转换公式如下:
python复制def rgb_to_lab(rgb_image):
# 先将RGB转换到0-1范围
rgb_normalized = rgb_image / 255.0
# 使用OpenCV进行转换
lab_image = cv2.cvtColor(rgb_normalized, cv2.COLOR_RGB2LAB)
return lab_image
2.2 改进的K-Means聚类
传统K-Means算法直接应用于颜色量化时存在几个问题:
- 对初始中心点敏感
- 容易陷入局部最优
- 无法自动确定最佳聚类数量
我的改进方案包括:
初始中心点优化:
python复制def initialize_centers(pixels, k):
# 使用K-Means++算法初始化
centers = [pixels[np.random.randint(pixels.shape[0])]]
for _ in range(1, k):
dists = np.array([min([np.linalg.norm(x-c)**2 for c in centers]) for x in pixels])
probs = dists / dists.sum()
cumprobs = probs.cumsum()
r = np.random.rand()
centers.append(pixels[np.where(cumprobs >= r)[0][0]])
return np.array(centers)
聚类数量自适应:
通过轮廓系数评估不同K值的效果,自动选择最优聚类数:
python复制from sklearn.metrics import silhouette_score
def find_optimal_k(pixels, max_k=10):
best_k = 2
best_score = -1
for k in range(2, max_k+1):
kmeans = KMeans(n_clusters=k, init='k-means++')
labels = kmeans.fit_predict(pixels)
score = silhouette_score(pixels, labels)
if score > best_score:
best_score = score
best_k = k
return best_k
3. 层次聚类的应用
3.1 后处理优化
在初步K-Means聚类后,我引入层次聚类进行后处理优化:
- 将每个聚类中心视为一个节点
- 计算所有中心点之间的色差距离
- 使用Ward方法进行层次聚类
- 根据拼豆实际色板合并相似颜色
python复制from scipy.cluster.hierarchy import linkage, fcluster
def hierarchical_refinement(centers, threshold=15.0):
# 计算色差距离矩阵
Z = linkage(centers, method='ward', metric='euclidean')
# 根据阈值划分簇
clusters = fcluster(Z, t=threshold, criterion='distance')
# 合并相似颜色
new_centers = []
for c in np.unique(clusters):
mask = (clusters == c)
if mask.sum() > 0:
new_centers.append(centers[mask].mean(axis=0))
return np.array(new_centers)
3.2 色板约束处理
实际拼豆制作中,可用的颜色数量受限于厂商提供的色板。我的算法特别考虑了这一点:
- 建立常用拼豆色板的LAB颜色数据库
- 将聚类结果映射到最近的可用色板颜色
- 确保最终使用的颜色都是实际可获得的
python复制def map_to_palette(colors, palette_db):
mapped = []
for color in colors:
# 计算与色板中所有颜色的距离
distances = np.linalg.norm(palette_db - color, axis=1)
# 选择距离最近的色板颜色
mapped.append(palette_db[np.argmin(distances)])
return np.array(mapped)
4. 完整实现流程
4.1 预处理阶段
python复制def preprocess_image(image_path, target_size=800):
# 读取图像
img = cv2.imread(image_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 调整大小保持宽高比
h, w = img.shape[:2]
scale = target_size / max(h, w)
img = cv2.resize(img, (int(w*scale), int(h*scale)))
# 转换为LAB颜色空间
lab_img = rgb_to_lab(img)
# 准备像素数据
pixels = lab_img.reshape((-1, 3)).astype(np.float32)
return img, pixels
4.2 主处理流程
python复制def bead_color_quantization(image_path, palette_db, max_colors=10):
# 预处理
orig_img, pixels = preprocess_image(image_path)
# 确定最佳K值
optimal_k = find_optimal_k(pixels, max_k=max_colors)
# K-Means聚类
kmeans = KMeans(n_clusters=optimal_k, init=initialize_centers(pixels, optimal_k))
labels = kmeans.fit_predict(pixels)
centers = kmeans.cluster_centers_
# 层次聚类优化
refined_centers = hierarchical_refinement(centers)
# 映射到实际色板
final_colors = map_to_palette(refined_centers, palette_db)
# 生成量化图像
quantized = final_colors[labels].reshape(orig_img.shape)
quantized_rgb = cv2.cvtColor(quantized.astype(np.uint8), cv2.COLOR_LAB2RGB)
return quantized_rgb, final_colors
5. 实际应用效果
5.1 效果对比
通过实际测试,这套算法相比传统方法有几个明显优势:
- 在16色限制下,能保留更多图像细节
- 自动避免生成过于相似的颜色
- 确保所有颜色都来自实际可用的拼豆色板
- 对高对比度区域的处理更加自然
5.2 性能优化
针对大尺寸图像的处理优化:
- 采用随机采样策略减少计算量
- 使用MiniBatchKMeans替代标准K-Means
- 实现多线程处理
python复制from sklearn.cluster import MiniBatchKMeans
def fast_kmeans(pixels, k, sample_size=10000):
if len(pixels) > sample_size:
indices = np.random.choice(len(pixels), size=sample_size, replace=False)
sample = pixels[indices]
else:
sample = pixels
kmeans = MiniBatchKMeans(n_clusters=k, init='k-means++', batch_size=256)
kmeans.fit(sample)
# 用少量样本预测全部数据
if len(pixels) > sample_size:
labels = kmeans.predict(pixels)
else:
labels = kmeans.labels_
return labels, kmeans.cluster_centers_
6. 常见问题与解决方案
6.1 颜色偏差问题
现象:最终结果与预期色相有偏差
解决方案:
- 检查LAB颜色空间转换是否正确
- 验证色板数据库的准确性
- 调整层次聚类的合并阈值
6.2 边缘锯齿问题
现象:色块边缘出现明显锯齿
优化方案:
python复制def smooth_edges(quantized_img, orig_img, strength=0.3):
# 将原始图像转换为灰度
gray = cv2.cvtColor(orig_img, cv2.COLOR_RGB2GRAY)
# 边缘检测
edges = cv2.Canny(gray, 50, 150)
# 混合原始图像和量化图像
blended = cv2.addWeighted(quantized_img, 1-strength, orig_img, strength, 0)
# 只在边缘区域混合
result = np.where(edges[...,None]!=0, blended, quantized_img)
return result
6.3 性能瓶颈
优化技巧:
- 对超大图像先降采样处理再还原
- 使用GPU加速计算(如CuPy替代NumPy)
- 缓存常用色板的聚类结果
7. 扩展应用
这套算法不仅适用于拼豆艺术,还可应用于:
- 十字绣图案设计
- 马赛克艺术创作
- 像素画风格转换
- UI设计中的配色方案生成
通过调整参数和色板数据库,可以轻松适配不同应用场景的需求。比如针对十字绣场景,可以增加对DMC绣线色板的专门支持。
