首页Python【Python小程序】使用...

【Python小程序】使用sklearn通过KMeans聚类算法压缩图像

本系列文章配套代码获取有以下两种途径:

  • 通过百度网盘获取:
链接: https://pan.baidu.com/s/1i9F6oV1J5oZnIsOASDs0gQ?pwd=mnsj 提取码: mnsj 
  • 前往GitHub获取
https://github.com/returu/Python_mini_program





使用Scikit-learn(sklearn)的聚类算法,特别是K-means聚类,对图片进行压缩是一个有效的技术。这种方法可以减少图片中的颜色数量,从而降低图片的文件大小,同时尽量保持图片的视觉质量。

基本思路是将图片中的颜色聚类为K个簇,然后用每个簇的中心颜色来替代簇内所有颜色的像素,从而达到压缩图片的目的。
以下是一个使用K-means聚类算法对图片进行压缩的具体步骤:
  • 加载图片:

使用PIL库加载图片并转换为numpy数组。

  • 压缩图片:

使用K-means算法对像素进行聚类,将图片中的颜色聚类为n_colors个簇。然后使用聚类中心的颜色替换原始图片的颜色,得到压缩后的图片。

  • 保存图片:

将压缩后的图片保存为新的文件。

  • 显示图片:

使用Matplotlib显示原始图片和压缩后的图片进行对比。

  • 注意事项:
image_path:图片路径。

n_colors表示想要压缩到的颜色数量,数值越小,压缩效果越明显,但图片质量也会下降。

示例代码如下:

import numpy as np  
from sklearn.cluster import KMeans  
import matplotlib.pyplot as plt  
from PIL import Image  

def load_image(image_path):  
    """  
    加载图片并转换为numpy数组  
    """  
    image = Image.open(image_path)  

    # 检查图像是否为灰度图像  
    if image.mode == 'L':  
        # 如果是灰度图像,则直接转换为numpy数组  
        image_np = np.array(image)  
    else:  
        # 如果是彩色图像,则转换为RGB并获取numpy数组  
        image = image.convert('RGB')  
        image_np = np.array(image)  

    return image_np  


def compress_image(image_np, n_colors):  
    """  
    使用K-means算法压缩图片  
    """  
    if len(image_np.shape) == 2:  
        # 灰度图像  
        h, w = image_np.shape  
        image_reshaped = image_np.reshape(-1, 1)  # 将图片数据转换为二维数组(h*w, 1)
        # 使用K-means算法进行聚类
        kmeans = KMeans(n_clusters=n_colors, random_state=42)  
        kmeans.fit(image_reshaped)
        # 获取聚类标签 
        labels = kmeans.labels_  
        # 获取聚类中心(即新的颜色)
        centers = kmeans.cluster_centers_
        # 用聚类中心的颜色替换原始图片的颜色
        compressed_image = centers[labels].reshape(h, w).astype(np.uint8)  
    else:  
        # 彩色图像  
        h, w, c = image_np.shape # 获取图片的尺寸 
        image_reshaped = image_np.reshape(-1, 3)  # 将图片数据转换为二维数组(h*w, c)
        # 使用K-means算法进行聚类 
        kmeans = KMeans(n_clusters=n_colors, random_state=42)  
        kmeans.fit(image_reshaped)  
        # 获取聚类标签 
        labels = kmeans.labels_  
        # 获取聚类中心(即新的颜色)  
        centers = kmeans.cluster_centers_  
        # 用聚类中心的颜色替换原始图片的颜色  
        compressed_image = centers[labels].reshape(h, w, c).astype(np.uint8)  

    return compressed_image  

def save_image(image_np, output_path):  
    """  
    将numpy数组保存为图片  
    """  
    image = Image.fromarray(image_np)  
    image.save(output_path)  

def main(image_path, output_path, n_colors):  
    # 加载图片  
    image_np = load_image(image_path)  
    # 压缩图片  
    compressed_image = compress_image(image_np, n_colors)  
    # 保存压缩后的图片  
    save_image(compressed_image, output_path)  

    # 显示原始图片和压缩后的图片  
    original_image = Image.open(image_path)  
    original_image_np = np.array(original_image)  

    fig, ax = plt.subplots(1, 2, figsize=(12, 6))  

    if len(original_image_np.shape) == 2:  
        # 灰度图像  
        ax[0].imshow(original_image_np, cmap='gray')  
        ax[1].imshow(compressed_image, cmap='gray')  
    else:  
        # 彩色图像  
        ax[0].imshow(original_image_np)  
        ax[1].imshow(compressed_image)  

    ax[0].set_title("Original Image")  
    ax[0].axis('off')  

    ax[1].set_title(f"Compressed Image with {n_colors} colors")  
    ax[1].axis('off')  

    plt.show()

# 示例使用  
image_path = 'test.jpg'  # 替换为你的图片路径  
output_path = 'compressed_image.jpg'  
n_colors = 16  # 选择要压缩到的颜色数量(对于灰度图像,这将是灰度级别数)  

main(image_path, output_path, n_colors)

压缩效果如下所示:


本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments