python颜色识别算法_纯Python编写K-means算法,提取图片中的主体颜色
在文章
今天我用Python手写了一个K-means算法,来完成同样的功能。
聚类属于数据挖掘中的一种非常重要学习流派,并即为将无标签样本数据中具有相似特征的数据划分为同一类别;亦即"物以类聚、人以群分"。
K-means算法在聚类分析中具有极强的简明性和高效性。其基本原理是通过预设k个初始质心来确定各类别,并通过不断重新计算并更新各数据集的质心位置来实现对数据分布的最佳逼近。
代码有点长,关键代码我会进行分析,其余代码没必要进行分析。
首先,我们定义一个计算距离的方法,我采用的是欧氏距离。
def get_euclidean_distance(_pixel, _center):
"""
获得欧氏距离
:param _pixel: 像素
:param _center: 中心
:return: 欧氏距离
"""
d_pow_2 = 0
for _channel_index in range(n_channels):
d_pow_2 += pow(_pixel[_channel_index] - _center[_channel_index], 2)
return np.sqrt(d_pow_2)
然后定义一个方法来计算中心,方便之后进行迭代。
def get_nearest_center(_pixel):
"""
获得最近的中心
:param _pixel: 像素
:return: 最近的中心的index
"""
min_center_d = get_euclidean_distance(_pixel, centers[0])
min_center_index = 0
for _center_index in range(1, k):
d = get_euclidean_distance(_pixel, centers[_center_index])
if d < min_center_d:
min_center_d = d
min_center_index = _center_index
return min_center_index
下面的模块用于计算新的中心,体现了K-means的关键思想。
def cal_new_center():
"""
如果存在一些中心缺乏最近邻居,则意味着我们选择了两个具有相同色调的中心(尽管这种情况发生的可能性非常低),因此我们需要重新选择。
:return: 新的中心
"""
归零
center_counts = np.zeros(k, dtype=int)
_centers = np.zeros((k, n_channels), dtype=int)
对每个类逐通道求和
for _pixel_index in range(n_pixels):
center_counts[labels[_pixel_index]] += 1
for _channel_index in range(n_channels):
_centers[labels[_pixel_index]][_channel_index] += img[_pixel_index][_channel_index]
对每个中心算出均值
for _center_index in range(k):
if center_counts[_center_index] > 0:
for _channel_index in range(n_channels):
_centers[_center_index][_channel_index] /= center_counts[_center_index]
else:
要是中心选重了就重新再选一个(虽然概率很小)
_centers[_center_index] = img[random.randint(0, n_pixels - 1)]
Output 'Warning: Center %d has no pixel, please reselect the center position randomly...' % _center_index.
return _centers
该段代码已完成K-means核心功能的实现。其余的代码主要负责图像像素数据的遍历处理,并根据K-means聚类结果生成相应的输出结果。已上传至GitHub平台。
我使用这张图片进行了测试,设置的中心点K=4
通过运行代码生成的结果来看,似乎能够看出这四种颜色基本上就是图片中的颜色。
这种方法跑的比较慢,有很多可以优化的地方,后续有时间再慢慢优化。
计划采集海量图像并进行分析,并建立一套基于颜色相似度的图像分类体系。采用Google的技术框架来完成基于图像颜色特征的分类任务
