问题描述:把给定图片,用图片中最主要的三种颜色来表示该图片

k-means思想:

  1、选择k个点作为初始中心

  2、将每个点指派到最近的中心,形成k个簇cluster

  3、重新计算每个簇的中心

  4、如果簇中心发生明显变化或未达到最大迭代次数,则回到step2

  问题:初始点不对的时候,容易收敛到局部最优值

  解决办法:

    1、选择k个点作为初始中心——canopy,模拟退火,贝叶斯准则

    2、将每个点指派到最近的中心,形成k个簇cluster

    3、重新计算每个簇的中心

    4、如果簇中心发生了明显的变化或未达到最大迭代次数,则回到step2

  例子:给你一幅图像,找出其中最主要的三种颜色,并将图片用三种最主要的颜色表示出来

# -*- coding: utf-8 -*-
# https://github.com/ZeevG/python-dominant-image-colour
# commented by heibanke from PIL import Image
import random
import numpy class Cluster(object):
"""
pixels: 主要颜色所依据的像素点
centroid: 主要颜色的RGB值
"""
def __init__(self):
self.pixels = []
self.centroid = None
#cluster有两个属性,centroid表示聚类中心,pixels表示依附于该聚类中心的那些像素点
#每个聚类中心都是一个单独的Cluster对象
def addPoint(self, pixel):
self.pixels.append(pixel) def setNewCentroid(self):
"""
通过pixels均值重新计算主要颜色
"""
R = [colour[0] for colour in self.pixels]
G = [colour[1] for colour in self.pixels]
B = [colour[2] for colour in self.pixels] R = sum(R) / len(R)
G = sum(G) / len(G)
B = sum(B) / len(B) self.centroid = (R, G, B)
self.pixels = [] return self.centroid class Kmeans(object): def __init__(self, k=3, max_iterations=5, min_distance=5.0, size=400):
"""
k: 主要颜色的分类个数
max_iterations: 最大迭代次数
min_distance: 当新的颜色和老颜色的距离小于该最小距离时,提前终止迭代
size: 用于计算的图像大小
"""
self.k = k
self.max_iterations = max_iterations
self.min_distance = min_distance
self.size = (size, size) def run(self, image):
self.image = image
#生成缩略图,节省运算量
self.image.thumbnail(self.size)
self.pixels = numpy.array(image.getdata(), dtype=numpy.uint8)
self.clusters = [None]*self.k
self.oldClusters = None
#在图像中随机选择k个像素作为初始主要颜色
randomPixels = random.sample(self.pixels, self.k) for idx in range(self.k):
self.clusters[idx] = Cluster()#生成idx个Cluster的对象
self.clusters[idx].centroid = randomPixels[idx]#每个centroid是随机采样得到的 iterations = 0 #开始迭代
while self.shouldExit(iterations) is False:
self.oldClusters= [cluster.centroid for cluster in self.clusters]
print iterations #对pixel和self.clusters中的主要颜色分别计算距离,将pixel加入到离它最近的主要颜色所在的cluster中
for pixel in self.pixels:
self.assignClusters(pixel)
#对每个cluster中的pixels,重新计算新的主要颜色
for cluster in self.clusters:
cluster.setNewCentroid() iterations += 1 return [cluster.centroid for cluster in self.clusters] def assignClusters(self, pixel):
shortest = float('Inf')
for cluster in self.clusters:
distance = self.calcDistance(cluster.centroid, pixel)
if distance < shortest:
shortest = distance
nearest = cluster#nearest实际上是cluster的引用,不是复制
nearest.addPoint(pixel) def calcDistance(self, a, b):
result = numpy.sqrt(sum((a - b) ** 2))
return result def shouldExit(self, iterations): if self.oldClusters is None:
return False
#计算新的中心和老的中心之间的距离
for idx in range(self.k):
dist = self.calcDistance(
numpy.array(self.clusters[idx].centroid),
numpy.array(self.oldClusters[idx])
)
if dist < self.min_distance:
return True if iterations <= self.max_iterations:
return False return True # The remaining methods are used for debugging
def showImage(self):
"""
显示原始图像
"""
self.image.show() def showCentroidColours(self):
"""
显示主要颜色
"""
for cluster in self.clusters:
image = Image.new("RGB", (200, 200), cluster.centroid)
image.show() def showClustering(self):
"""
将原始图像的像素完全替换为主要颜色后的效果
"""
localPixels = [None] * len(self.image.getdata()) #enumerate用于既需要遍历元素下边也需要得到元素值的情况,用for循环比较麻烦
for idx, pixel in enumerate(self.pixels):
shortest = float('Inf') #正无穷
for cluster in self.clusters:
distance = self.calcDistance(
cluster.centroid,
pixel
)
if distance < shortest:
shortest = distance
nearest = cluster localPixels[idx] = nearest.centroid w, h = self.image.size
localPixels = numpy.asarray(localPixels)\
.astype('uint8')\
.reshape((h, w, 3)) colourMap = Image.fromarray(localPixels)
return colourMap if __name__=="__main__":
from PIL import Image
import os k_image=Kmeans(k=3) #默认参数
path = './pics/'
fp = open('file_color.txt','w')
for filename in os.listdir(path):
print path+filename
try:
color = k_image.run(Image.open(path+filename))
# w_image = k_image.showClustering()
w_image = k_image.showCentroidColours()
w_image.save(path+'mean_'+filename,'jpeg')
fp.write('The color of '+filename+' is '+str(color)+'\n')
except:
print "This file format is not support"
fp.close()

处理前的图片:

  

  处理后的图片:

  

参考:http://blog.zeevgilovitz.com/detecting-dominant-colours-in-python/

k-means处理图片的更多相关文章

  1. KNN 与 K - Means 算法比较

    KNN K-Means 1.分类算法 聚类算法 2.监督学习 非监督学习 3.数据类型:喂给它的数据集是带label的数据,已经是完全正确的数据 喂给它的数据集是无label的数据,是杂乱无章的,经过 ...

  2. 软件——机器学习与Python,聚类,K——means

    K-means是一种聚类算法: 这里运用k-means进行31个城市的分类 城市的数据保存在city.txt文件中,内容如下: BJ,2959.19,730.79,749.41,513.34,467. ...

  3. 快速查找无序数组中的第K大数?

    1.题目分析: 查找无序数组中的第K大数,直观感觉便是先排好序再找到下标为K-1的元素,时间复杂度O(NlgN).在此,我们想探索是否存在时间复杂度 < O(NlgN),而且近似等于O(N)的高 ...

  4. 网络费用流-最小k路径覆盖

    多校联赛第一场(hdu4862) Jump Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  5. numpy.ones_like(a, dtype=None, order='K', subok=True)返回和原矩阵一样形状的1矩阵

    Return an array of ones with the same shape and type as a given array. Parameters: a : array_like Th ...

  6. 当我们在谈论kmeans(2)

        本稿为初稿,后续可能还会修改:如果转载,请务必保留源地址,非常感谢! 博客园:http://www.cnblogs.com/data-miner/ 其他:建设中- 当我们在谈论kmeans(2 ...

  7. scikit-learn包的学习资料

    http://scikit-learn.org/stable/modules/clustering.html#k-means http://my.oschina.net/u/175377/blog/8 ...

  8. HDU 3584 Cube (三维 树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3584 Cube Problem Description Given an N*N*N cube A,  ...

  9. Torch7学习笔记(二)nn Package

    神经网络Package [目前还属于草稿版,等我整个学习玩以后会重新整理] 模块Module module定义了训练神经网络需要的所有基础方法,并且是可以序列化的抽象类. module有两种状态变量: ...

  10. 2016中国大学生程序设计竞赛 - 网络选拔赛 J. Alice and Bob

    Alice and Bob Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) ...

随机推荐

  1. Spring3 MVC请求参数获取的几种方法[转载]

    http://www.cnblogs.com/leiOOlei/p/3658147.html 一.      通过@PathVariabl获取路径中的参数 @RequestMapping(value= ...

  2. R(5): sql 数据处理

    sqldf程序包是R语言中实用的数据管理辅助工具,但最新版本的包在处理中文时出现乱码,待解决 Usage:  sqldf(x, stringsAsFactors = FALSE,  row.names ...

  3. CentOS Linux解决Device eth0 does not seem to be present 但是没有发现eth1

    http://www.linuxidc.com/Linux/2012-12/76248.htm 此标题已经是有人写过的了.但是为什么拿来重写? 我复制完,没有发现有eth1这个网卡 为什么呢?需要选中 ...

  4. 【ActiveMQ入门-5】ActiveMQ学习-Queue与Topic的比较

    Queue与Topic的比较 1.JMS Queue执行load balancer语义: 一条消息仅能被一个consumer收到. 如果在message发送的时候没有可用的consumer,那么它将被 ...

  5. 敏感词文本文件 filtered_words.txt,里面的内容为以下内容,当用户输入敏感词语时,则打印出 Freedom,否则打印出 Human Rights

    敏感词文件内容: 代码: def filtered_words(path='filtered_words.txt'): words = [] with open(path, 'r', encoding ...

  6. ThinkJava-多态

    8.2.1 方法调用绑定 解决的办法就是后期绑定,它的含义就是在运行时根据对象的类型进行绑定.后期绑定也 叫做动态绑定或运行时绑定.如果一种语言想实现后期绑定,就必须具有某种机制,以便在运 行时能判断 ...

  7. VMware vCenter Server安装

    SQL Server 2008 R2安装包:http://blog.sina.com.cn/s/blog_4aedf6370101j9tz.html SQL Server安装指导:http://www ...

  8. linux shell 命令常用快捷键

    下面是一些shell的常用快捷键,快捷键玩熟悉了在一定程度上是可以提高工作效率滴… Ctrl + a 切换到命令行开始 Ctrl + e 切换到命令行末尾 Ctrl + l 清除屏幕内容 Ctrl + ...

  9. [转载] ./configure,make,make install的作用

    1.configure,这一步一般用来生成 Makefile,为下一步的编译做准备,你可以通过在 configure 后加上参数来对安装进行控制,比如代码:./configure –prefix=/u ...

  10. Centos7安装docker(转!)

    时间在自己的运动中也会碰到挫折,遇到障碍,所以某一段时间也会滞留在哪一个房间里 <百年孤独> 转自:https://www.cnblogs.com/yufeng218/p/8370670. ...