基于轮廓系数法的K-means聚类颜色应用中噪点与线条问题排查
问题:K-means聚类后颜色替换存在噪点与边界问题
我结合K-means聚类算法与轮廓系数法确定数据集的最优k值,目标是为生成的聚类分配不同颜色。但在颜色分配时,发现聚类内部存在噪点和淡线,推测是由数据集中占比极低的颜色导致。
已实现过滤占比低于特定阈值的聚类,但调整后输出仍存在噪点,尤其在聚类边界处更为明显。相关图片如下:
- 原始图片:

- 聚类后图片:

- 颜色修改后图片:

聚类生成代码
def optimal_k_using_silhouette(image): lab_image = cv2.cvtColor(image, cv2.COLOR_BGR2Lab) data = sample_pixels(lab_image) range_n_clusters = list(range(2, 7)) silhouette_avgs = [] for n_clusters in range_n_clusters: clusterer = KMeans(n_clusters=n_clusters, random_state=10, n_init=10) cluster_labels = clusterer.fit_predict(data) silhouette_avg = silhouette_score(data, cluster_labels) silhouette_avgs.append(silhouette_avg) best_k = range_n_clusters[np.argmax(silhouette_avgs)] best_clusterer = KMeans(n_clusters=best_k, random_state=10, n_init=10).fit(data) valid_clusters = get_valid_clusters(best_clusterer, lab_image.reshape(-1, 3)) best_clusterer.cluster_centers_ = best_clusterer.cluster_centers_[valid_clusters] best_clusterer.n_clusters = len(valid_clusters) return best_clusterer
颜色修改实现代码
@app.route("/modify_colors", methods=["POST"]) def modify_colors(): modified_colors = [] for i in range(len(session['colors_bgr'])): r = int(request.form.get(f'color_{i}_r')) g = int(request.form.get(f'color_{i}_g')) b = int(request.form.get(f'color_{i}_b')) modified_colors.append((b, g, r)) segmented_image_path = "static/segmented_image.png" segmented_img, alpha_channel = upscale_and_smooth(segmented_image_path, desired_width=1600) print("Segmented Image Shape:", segmented_img.shape) replaced_image = replace_colors(segmented_img, session['colors_bgr'], modified_colors) print("Replaced Image Shape:", replaced_image.shape) # Blend the images at the borders replaced_image = blend_at_borders(segmented_img, replaced_image) if alpha_channel is not None: replaced_image = cv2.merge([replaced_image, alpha_channel]) cv2.imwrite('static/segmented_image_modified.png', replaced_image) session['segmented_image_path'] = 'static/segmented_image_modified.png' # Update the path in session return render_template('result_modified.html', image_path=session['segmented_image_path'])
解决思路与优化建议
1. 聚类前的图像预处理
- 对原始图像做高斯模糊(
cv2.GaussianBlur),用3x3或5x5核过滤高频噪点,避免K-means将孤立噪点识别为独立聚类。 - 结合HSV空间的饱和度通道,过滤低饱和度像素(如饱和度<20),这类像素多为灰度干扰或噪点,可减少无效聚类的生成。
2. 聚类后的后处理
- 形态学操作:用
cv2.morphologyEx执行闭运算(膨胀+腐蚀)填补聚类内部的小空洞,再执行开运算(腐蚀+膨胀)去除边界的孤立噪点,核大小选3x3或5x5矩形核。 - 连通域分析:用
cv2.connectedComponentsWithStats提取每个聚类的连通区域,过滤掉面积小于阈值的小区域,只保留主体聚类区域。
3. 颜色替换逻辑优化
- 基于聚类标签图操作:聚类后保存每个像素的聚类标签矩阵(而非彩色分割图),颜色替换时直接根据标签映射新颜色,避免因颜色匹配误差产生噪点。
- 边缘保留平滑:对替换后的图像用
cv2.bilateralFilter做双边滤波,在保留聚类边界的同时平滑内部噪点,或使用导向滤波进一步优化边界过渡。
4. 聚类过程细节调整
- 采样像素时采用均匀网格采样,避免随机采样导致的噪点像素占比过高,确保采样覆盖图像所有区域。
- 过滤小聚类时,结合聚类的像素分布集中度(如计算聚类内像素的方差),避免误删边缘的有效小区域。
内容的提问来源于stack exchange,提问作者Osama Bin Shamim
相关产品推荐
相关产品推荐

