«Это 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) Получив изображение, нужно сделать следующее:
- Загрузите изображение BGR:
img = cv2.imread('example.jpg')
- использовать
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 цветов, заменив значение каждого пикселя соответствующим значением центра, и результат выполнения программы будет следующим:
Отображает распределение цветов после квантования цвета
Вышеупомянутая программа может быть расширена для отображения квантованного цветового распределения, которое показывает количество пикселей, назначенных каждому центру кластера. просто расширить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 дают более реалистичные изображения.