k-means实现图像颜色分割及压缩

from sklearn.datasets import make_blobs#多
from sklearn.cluster import KMeans
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.image import imread


#ladybug.png

image = imread('strawberry.jpg')
##image.shape#三个参数不行,不满足kmeansAPI输入要求

X = image.reshape(-1,3)#-1,代表前两个参数相乘#分为三列#三维变二维?
##X.shape#多
print('读取图片完成')

##kmeans = KMeans(n_clusters = 8,random_state=42).fit(X)#8簇,随机种子42?fit啥意思?#fit使用X作为训练数据拟合模型,这步训练慢,因为图像数据大
print('完成')

##kmeans.cluster_centers_#每个簇的中心位置,训练后
print('完成')

##segmented_img = kmeans.cluster_centers_[kmeans.labels_].reshape(image.shape)#图像分割#图像中心点#标签?#图像中心点的一个标签#reshape还原成一个三维的,
print('完成')

segmented_imgs = []#列表
n_colors = (10,8,6,4,2)#几种不同的像素点
for n_cluster in n_colors: #从5color循环,遍历k值,很慢执行5次
    kmeans = KMeans(n_clusters = n_cluster,random_state=42).fit(X)#借鉴上面kmeans算法#fit使用X作为训练数据拟合模型
    segmented_img = kmeans.cluster_centers_[kmeans.labels_]#上面,这一步先把结果拿到手
    segmented_imgs.append(segmented_img.reshape(image.shape))#上面,reshape操作,恢复三维图像,#.append操作将,后面的数据添加到列表中
    print('完成')
    
plt.figure(figsize=(12,8))#tang10,5#moon12,8#?子图,尺寸变小?宽高
plt.subplot(231)#原始图像
##plt.imshow(image)#报错,得加.astype(np.uint8)
plt.imshow(image.astype('uint8'))#为什么有的图片反而不用uint8
plt.title('Original image')#标题

for idx,n_clusters in enumerate(n_colors):#枚举enumerate,能得到索引,?的个数,#for循环,每一次迭代的结果
    plt.subplot(232+idx)#idx从0开始?
    plt.imshow(segmented_imgs[idx])#显示#索引
    plt.imshow(segmented_imgs[idx].astype('uint8'))
    ##plt.title('{}colors'.format(n_clusters))#标题
    print('完成')
# plt.savefig('result.png')#保存图片
plt.show()
print('总完成')

原始图像

 10颜色聚类

图片中各类颜色的占比情况

 

 8颜色聚类

 

6颜色聚类 

 

4颜色聚类 

 

2颜色聚类 

 

饼状图显示颜色占比情况

#分类颜色程序,需要手动输入K值
import numpy as np
import cv2 as cv

img_rgb = cv.imread(r"C:\Users\wsl\Desktop\k-means\kmeans-py\strawberry.jpg")
img_bgr = cv.cvtColor(img_rgb, cv.COLOR_RGB2BGR)
Z = img_bgr.reshape((-1,3))

# convert to np.float32
Z = np.float32(Z)

# define criteria, number of clusters(K) and apply kmeans()
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 2##############################################################################################################
############################################################代表k不同时,需要更换的参数
ret,label,center=cv.kmeans(Z,K,None,criteria,10,cv.KMEANS_RANDOM_CENTERS)

# Now convert back into uint8, and make original image
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((img_bgr.shape))
print("完成")

#显示源头分类完的3通道颜色数据组,进行频率统计
img2= res2
a = img2.reshape((-1,3))
a = np.array(a)

uniques, counts = np.unique(a, return_counts=True, axis=0)

print([(unique, count) for unique, count in zip(uniques, counts)])
print(counts)#只打印出现的频率
print(uniques)
#绘制颜色出现频率的饼状图

# 绘制育龄妇女的受教育程度分布饼图
import matplotlib.pyplot as plt
 
# ********** Begin *********#
#总数据
#Num = 1501817+4506185
Num = Sum
#单个数据
#data = [1501817,4506185]
data = counts
#数据标签
#labels = ['(101,145,213)', '(253,253,254)']
#labels = [uniques[0], uniques[1],uniques[2],uniques[3],uniques[4], uniques[5],uniques[6], uniques[7],uniques[8], uniques[9]]
labels = [uniques[0], uniques[1]]
#####################################################################################################################################3
#各区域颜色
#colors = [(213/255, 145/255, 101/255),(254/255, 253/255, 253/255)]
#数组同除
Uniques = np.array(uniques)/255#归一,255变为1

#列表变元组
a0=tuple(Uniques[0])
a1=tuple(Uniques[1])
#a2=tuple(Uniques[2])
#a3=tuple(Uniques[3])
#a4=tuple(Uniques[4])
#a5=tuple(Uniques[5])
#a6=tuple(Uniques[6])
#a7=tuple(Uniques[7])
#a8=tuple(Uniques[8])
#a9=tuple(Uniques[9])
########################################################################################################################################
#colors = [Uniques[0],Uniques[1],Uniques[2],Uniques[3],Uniques[4],Uniques[5],Uniques[6],Uniques[7],Uniques[8],Uniques[9]]
#colors = [a0,a1,a2,a3,a4,a5,a6,a7,a8,a9]
colors = [a0,a1]
#########################################################################################################################################
#背景色,防止白色看不见
fig = plt.figure(1, facecolor='#EAEAEF', figsize=(10, 8))

#数据计算处理
#sizes = [data[0]/Num*100,data[1]/Num*100,data[2]/Num*100,data[3]/Num*100,data[4]/Num*100,data[5]/Num*100,data[6]/Num*100,data[7]/Num*100,data[8]/Num*100,data[9]/Num*100]
sizes = [data[0]/Num*100,data[1]/Num*100]
#############################################################################################################################################
#设置突出模块偏移值
#expodes = (0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.1)##################################################################################
expodes = (0.01,0.1)
#设置绘图属性并绘图
patches,p_text = plt.pie(sizes,explode=expodes,labels=labels,shadow=True,colors=colors)
## 用于显示为一个长宽相等的饼图

#改变字体大小
for t in p_text:
    t.set_size(10)
    
plt.axis('equal')
#保存并显示
#plt.savefig('fig10.png')##################################################################################################################
plt.savefig('fig2.png')
plt.show()
# ********** End **********#

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以回答你的问题。首先,K-means聚类算法是一种非监督学习算法,它在图像处理、数据挖掘等领域具有广泛的应用。该算法的思想是通过将数据点分成K个簇,使得同一个簇内的数据点的相似度较高,而不同簇之间的数据点的相似度较低。在图像分割中,可以将像素点视为数据点,利用K-means算法将图像划分成K个区域,从而实现图像分割的目的。 以下是采用K-means算法实现图像分割的代码,供你参考: ```python import numpy as np import cv2 def kmeans_color_quantization(image, clusters=8, rounds=1): h, w = image.shape[:2] samples = np.zeros([h*w, 3], dtype=np.float32) count = 0 for x in range(h): for y in range(w): samples[count] = image[x][y] count += 1 compactness, labels, centers = cv2.kmeans(samples, clusters, None, (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10000, 0.0001), rounds, cv2.KMEANS_RANDOM_CENTERS) centers = np.uint8(centers) res = centers[labels.flatten()] return res.reshape((image.shape)) # 读取图片 img = cv2.imread('test.jpg') # 图像压缩 img = kmeans_color_quantization(img,clusters=8) # 显示结果 cv2.imshow('image',img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这里使用了OpenCV中的cv2.kmeans函数实现K-means聚类算法。具体实现步骤是:首先将图像像素点作为数据点,利用K-means算法将图像分成多个簇;然后根据每个簇的质心值,将图像中的每个像素点重新赋值,达到压缩图像的效果。最后,使用cv2.imshow函数显示处理后的图像。 希望以上回答能够帮到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值