基于python+opencv的彩色图片主色提取——利用K-means聚类算法
- 一、K-means聚类算法
- 1.K-means算法原理
- 2. K-means聚类算法流程
- 3.sklearn库中sklearn.cluster.KMeans函数参数介绍
- 二、python算法实现
- 参考文献
一、K-means聚类算法
常用的背景主色提取方法有两种: 颜色直方图法和聚类分析法. 一般来说, 背景图像中包含巨大的颜色数目,且各颜色分量之间无显著相关性,通过颜色直方图很难快速而准确地提取背景主色. 而采用基于模糊理论的聚类分析, 利用颜色空间本身是建立在人对颜色的主观感觉基础之上, 且颜色归属的模糊性已经隐藏于颜色的量化过程中的这一特点, 可以快速而准确地提取复杂颜色空间的背景主色。
1.K-means算法原理
K-means 聚类分析的基本思路是: 要对类内颜色的每个像素点与其对应聚类中心的距离平方之和求最小, 即
式中,n 代表背景图片中一个像素的坐标,C(n) 代表该像素的颜色值,N 代表背景颜色数据样本,K 代表颜色分类数。k 代表每类颜色的聚类中心. rnk 为二分量,代表当前颜色是否属于第 k 类颜色:若 rnk=0,表示当前颜色不属于第 k 类;若 rnk = 1,表示当前颜色属于第 k 类。少数 K-means 聚类分析得到的可能是局部最优值,而不是迷彩设计所需的全局最优值. 为了克服这一缺陷,需要对背景图进行多次 Kmeans 聚类分析,以求得到的最优聚类中心为背景优势色。
2. K-means聚类算法流程
K-Means聚类算法的原理流程:
第一步:确定K值,聚类成K个类簇。
第二步:从数据中随机选择(或按照某种方式)K个数据点作为初始分类的中心。
第三步:分别计算数据中每个点到每个中心的距离,将每个点划分到离中心最近的类中
第四步:当每个中心都划分了一些点后,去每个类的均值,选出新的中心。
第五步:比较新的中心和之前的中心,如果新的中心和之前的中心之间的距离小于某阈值,或迭代次数超过某阈值,认为聚类已经收敛,终止。
第六步:否则继续迭代执行第三到五步,直到第五步满足。
3.sklearn库中sklearn.cluster.KMeans函数参数介绍
sklearn.cluster.KMeans(n_clusters=8, init=‘k-means++’, n_init=10, max_iter=300, tol=0.0001, precompute_distances=‘deprecated’, verbose=0, random_state=None, copy_x=True, n_jobs=‘deprecated’, algorithm=‘auto’)
n_clusters:整形,缺省值=8 ,生成的聚类数,即产生的质心(centroids)数。
init:有三个可选值:’k-means++’, ‘random’,或者传递一个ndarray向量。此参数指定初始化方法,默认值为 ‘k-means++’。
(1)‘k-means++’ 用一种特殊的方法选定初始质心从而能加速迭代过程的收敛(即上文中的k-means++介绍)
(2)‘random’ 随机从训练数据中选取初始质心。
(3)如果传递的是一个ndarray,则应该形如 (n_clusters, n_features) 并给出初始质心。
n_init:整形,缺省值=10,用不同的质心初始化值运行算法的次数,最终解是在inertia意义下选出的最优结果。
max_iter:整形,缺省值=300,执行一次k-means算法所进行的最大迭代数。
tol:float形,默认值= 1e-4 与inertia结合来确定收敛条件。
precompute_distances:三个可选值,‘auto’,True 或者 False。预计算距离,计算速度更快但占用更多内存。
(1)‘auto’:如果 样本数乘以聚类数大于 12million 的话则不预计算距离。This corresponds to about 100MB overhead per job using double precision.
(2)True:总是预先计算距离。
(3)False:永远不预先计算距离。
verbose:整形,默认值= 0,详细模式
random_state:整形或 numpy.RandomState 类型,可选用于初始化质心的生成器(generator)。如果值为一个整数,则确定一个seed。此参数默认值为numpy的随机数生成器。
copy_x:布尔型,默认值=True,当我们precomputing distances时,将数据中心化会得到更准确的结果。如果把此参数值设为True,则原始数据不会被改变。如果是False,则会直接在原始数据上做修改并在函数返回值时将其还原。但是在计算过程中由于有对数据均值的加减运算,所以数据返回后,原始数据和计算前可能会有细小差别。
n_jobs:整形数。指定计算所用的进程数。内部原理是同时进行n_init指定次数的计算。
(1)若值为 -1,则用所有的CPU进行运算。若值为1,则不进行并行运算,这样的话方便调试。
(2)若值小于-1,则用到的CPU数为(n_cpus + 1 + n_jobs)。因此如果 n_jobs值为-2,则用到的CPU数为总CPU数减1。
algorithm:三个值可选,“auto”, “full”, “elkan”, 默认为default=“auto”,表示使用K-means算法。“full”表示经典的EM-style算法。“elkan ”通过使用三角形不等式,对具有明确定义的簇的数据更有效。但是由于要分配一个额外的形状数组(n_samples, n_clusters),它的内存消耗更大。
二、python算法实现
第一步,在IDE中导入需要的库:
import cv2
import numpy as np
from skimage import io
from sklearn.cluster import KMeans
第二步,因为要用到fit(X[, y, sample_weight])来计算k-means聚类,所以读取图片后需要转换数据维度:
img=cv2.imread(r"C:\Users\Administrator\Desktop\color restoration\cao2.jpg")
# 转换数据维度
img1 = img.reshape((img.shape[0] * img.shape[1], img.shape[2]))
读取的图片如下所示,我们要提取的就是该图片中的主色。
第三步,K-means聚类
#聚类个数
k = 3
#构造聚类器
estimator = KMeans(n_clusters=k, max_iter=4000, init='k-means++', n_init=50)
#聚类
estimator.fit(img1)
#获取聚类中心
centroids = estimator.cluster_centers_
其中的聚类个数和其他参数都可以根据实际情况进行调整。
第四步,主色可视化
# 使用算法跑出的中心点,生成一个矩阵,为数据可视化做准备
result = []
result_width = 200
result_height_per_center = 80
# 获取图片色彩层数
n_channels = img1.shape[1]
for center_index in range(k):
result.append(np.full((result_width * result_height_per_center, n_channels), centroids[center_index], dtype=int))
result = np.array(result)
result = result.reshape((result_height_per_center * k, result_width, n_channels))
result=result.astype(np.uint8)
cv2.imshow('maincolor',result)
# 保存图片
io.imsave(r'C:\Users\Administrator\Desktop\color restoration\color\maincolor.jpg', result)
将提取的3个主色分别显示在80*200的长方形中,并将图片保存下来。最后提取的图片主色如下图: