Квантование цвета с кластеризацией K-средних

искусственный интеллект компьютерное зрение
Квантование цвета с кластеризацией K-средних

«Это 21-й день моего участия в ноябрьском испытании обновлений. Подробную информацию о мероприятии см.:Вызов последнего обновления 2021 г."

предисловие

K-MeansЦель алгоритма кластеризации состоит в том, чтобыnВыборки разделены (кластеризованы) какKкластеры, мы можем использоватьOpenCVкоторый предоставилcv2.kmeans()реализация функцииK-MeansАлгоритм кластеризации, который работает, находя центры кластеров и группируя входные выборки вокруг кластеров. В этой статье мы узнаем, как воспользоватьсяK-MeansКластеризация выполняет квантование цвета, чтобы уменьшить количество цветов в изображении.

Квантование цвета с кластеризацией K-средних

Проблема квантования цвета может быть определена как процесс уменьшения количества цветов в изображении. Квантование цветов имеет решающее значение для отображения изображений на устройствах, которые могут отображать только ограниченные цвета из-за ограничений памяти и т. д. Поэтому отображение цветов на этих устройствах часто требует компромисса между точностью и уменьшением количества цветов.K-MeansПри кластеризации для квантования цвета компромисс между ними достигается путем установкиKпараметры.

использоватьK-MeansАлгоритм кластеризации используется для выполнения квантования цвета, а данные центра кластера состоят из 3 признаков, которые соответствуют значениям B, G и R каждого пикселя изображения. Итак, ключ в том, чтобы преобразовать изображение в данные:

data = np.float32(image).reshape((-1, 3))

Чтобы увидеть, как компрометируются точность и количество цветов, мы выполняем процесс кластеризации с разными значениями K (3, 5, 10, 20 и 40), чтобы увидеть, как изменится результирующее изображение, если мы хотим иметь только 3 цвета ( K = 3) Получив изображение, нужно сделать следующее:

  1. Загрузите изображение BGR:
    img = cv2.imread('example.jpg')
    
  2. использоватьcolor_quantization()Функция выполняет квантование цвета:
    def color_quantization(image, k):
        # 将图像转换为数据
        data = np.float32(image).reshape((-1, 3))
        # 算法终止条件
        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0)
        # K-Means 聚类
        ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
        # 簇中心
        center = np.uint8(center)
        # 将具有 k 颜色中心的图像转换为 uint8
        result = center[label.flatten()]
        result = result.reshape(img.shape)
        return result
    color_3 = color_quantization(img, 3)
    

color_quantization()функция, ключевым моментом является использованиеcv2.kmeans()метод. Наконец, можно построить изображение из k цветов, заменив значение каждого пикселя соответствующим значением центра, и результат выполнения программы будет следующим:

利用 K-Means 聚类进行色彩量化

利用 K-Means 聚类进行色彩量化

Отображает распределение цветов после квантования цвета

Вышеупомянутая программа может быть расширена для отображения квантованного цветового распределения, которое показывает количество пикселей, назначенных каждому центру кластера. просто расширитьcolor_quantization()Функция была изменена, чтобы включить желаемую функциональность:

import collections
def color_quantization(image, k):
    # 将图像转换为数据
    data = np.float32(image).reshape((-1, 3))
    # 算法终止条件
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0)
    # K-Means 聚类
    ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
    # 簇中心
    center = np.uint8(center)
    # 将具有 k 颜色中心的图像转换为 uint8
    result = center[label.flatten()]
    result = result.reshape(img.shape)
    # 统计分配给每个聚类中心的像素数
    counter = collections.Counter(label.flatten())
    print(counter)
    # 计算输入图像的总像素数
    total = img.shape[0] * img.shape[1]
    # 为色彩分布图像指定宽度和高度:
    desired_width = img.shape[1]
    
    desired_height = 70
    desired_height_colors = 50
    # 初始化色彩分布图像
    color_distribution = np.ones((desired_height, desired_width, 3), dtype='uint8') * 255
    start = 0

    for key, value in counter.items():
        # 归一化
        value_normalized = value / total * desired_width
        end = start + value_normalized
        # 绘制与当前颜色对应的矩形
        cv2.rectangle(color_distribution, (int(start), 0), (int(end), desired_height_colors), center[key].tolist(), -1)
        start = end

    return np.vstack((color_distribution, result))

В приведенном выше коде используйтеcollections.Counter()для подсчета количества пикселей, назначенных каждому центру кластера:

counter = collections.Counter(label.flatten())

Например, если K = 10, вы можете получить следующие результаты:

Counter({7: 37199, 3: 36302, 0: 29299, 5: 23987, 6: 23895, 1: 20077, 9: 19814, 8: 18427, 4: 16221, 2: 14779})

После построения изображения распределения цветов соедините его с квантованным изображением цвета:

np.vstack((color_distribution, result))

Вывод программы выглядит так:

显示色彩量化后的色彩分布

Как видно из приведенного выше рисунка, при использованииK-MeansРезультат изменения параметра k (10, 20, 30, 40, 50, 60 и 70) после применения цветового квантования к алгоритму кластеризации.Большие значения k дают более реалистичные изображения.