Opencv和pycharm实现k-means对图像的分割处理

用Opencv和pycharm实现k-means对图像的分割处理

注:这个例子只适合学习用,图像处理用k-means就像2021年用大哥大
安装Opncv: https://blog.csdn.net/aspecialpig/article/details/105746760

k-means算法

1.确定聚K类,随机选择K个点为中心点(质心)
2.计算所有样本点各自到K个中心的距离(欧氏距离),根据远近聚类
3.聚类完成后,每个聚类求平均值更新中心,重复上一步迭代
4.直到满足收敛条件(一般是中心点不再改变或者改变很小)
关键:
1.K选择聚几次
2.初始点选择(当前簇中所有数据点的平均值)
3.迭代次数
优点:
1.简单易实现
2.聚类效果中上(靠K和中心点的选择)
3.空间复杂度N,时间复杂度NKI(N样本个数,K中心点个数,I迭代次数)
缺点:
1.对离群点,噪声点敏感(求平均值更新中心点)
2.难区别样本少而且紧密的点
3.大规模数据,收敛速度比较慢(所有数据的平均值)
4.结果不一定全局最优,只是局部最优(与K和初始点选取有关)

代码

import cv2
import numpy as np
import matplotlib.pyplot as plt

#读取原始图像
img = cv2.imread('girl.png')
print(img.shape)#高度,宽度,通道数量(可以看成属性),3表示RGB

#图像二维像素转换为一维,每一维上每个像素(样本)有三个属性
#遇到的RGB图像的值是处于0-255之间的,为了更好的处理图像,通常会将图像值转变到0-1之间
#这个处理的过程就是图像的float类型转变为uint8类型过程。
#float类型取值范围 :-1 到1 或者 0到1
#uint8类型取值范围:0到255
data = img.reshape((-1,3))#属性3个,其他变成一维
print(data.shape)
print(data.dtype)#查看数据类型 是uint8
data = np.float32(data)#将图像uint8转换为float,

#迭代停止模式选择(type, max_iter, epsilon)
#cv2.TERM_CRITERIA_EPS :精确度(误差)满足epsilon,则停止。
#cv2.TERM_CRITERIA_MAX_ITER:迭代次数超过max_iter,则停止。
#两者结合,满足任意一个结束。
criteria = (cv2.TERM_CRITERIA_EPS +
            cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
#初始点选取
#v2.KMEANS_PP_CENTERS:使用kmeans++算法的中心初始化算法,即初始中心的选择使眼色相差最大.
#cv2.KMEANS_RANDOM_CENTERS:每次随机选择初始中心(Select random initial centers in each attempt.)
flags = cv2.KMEANS_RANDOM_CENTERS
#compactness:紧密度,返回每个点到相应重心的距离的平方和
#labels:结果标记,每个成员被标记为分组的序号,如 0,1,2,3,4...等
#centers:由聚类的中心组成的数组
#K-Means聚类 聚集成2类
compactness2, labels2, centers2 = cv2.kmeans(data, 2, None, criteria, 10, flags)#None处表示分类标签,10表示重复试验10次返回最好一次结果
#K-Means聚类 聚集成4类
compactness3, labels3, centers3 = cv2.kmeans(data, 3, None, criteria, 10, flags)
#K-Means聚类 聚集成8类
compactness4, labels4, centers4 = cv2.kmeans(data, 4, None, criteria, 10, flags)
#K-Means聚类 聚集成16类
compactness5, labels5, centers5 = cv2.kmeans(data, 5, None, criteria, 10, flags)
#K-Means聚类 聚集成64类
compactness32, labels32, centers32 = cv2.kmeans(data, 32, None, criteria, 10, flags)

#图像转换回uint8二维类型,为BGR图像,不是原图
centers2 = np.uint8(centers2)
res = centers2[labels2]
dst2 = res.reshape((img.shape))

centers3 = np.uint8(centers3)
res = centers3[labels3]
dst3 = res.reshape((img.shape))

centers4 = np.uint8(centers4)
res = centers4[labels4]
dst4 = res.reshape((img.shape))

centers5 = np.uint8(centers5)
res = centers5[labels5]
dst5 = res.reshape((img.shape))

centers32 = np.uint8(centers32)
res = centers32[labels32]
dst32 = res.reshape((img.shape))

#BGR图像转换为RGB显示
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)#cv2.COLOR_BGR2RGB 将BGR格式转换成RGB格式
dst2 = cv2.cvtColor(dst2, cv2.COLOR_BGR2RGB)
dst3 = cv2.cvtColor(dst3, cv2.COLOR_BGR2RGB)
dst4 = cv2.cvtColor(dst4, cv2.COLOR_BGR2RGB)
dst5 = cv2.cvtColor(dst5, cv2.COLOR_BGR2RGB)
dst32 = cv2.cvtColor(dst32, cv2.COLOR_BGR2RGB)

#用来正常显示中文标签
plt.rcParams['font.sans-serif']=['SimHei']
#显示图像
titles = [u'原始图像', u'聚类图像 K=2', u'聚类图像 K=3',
          u'聚类图像 K=4', u'聚类图像 K=5',  u'聚类图像 K=32']
images = [img, dst2, dst3, dst4, dst5, dst32]
for i in range(6):
   plt.subplot(2,3,i+1)#2行3列
   plt.imshow(images[i])
   plt.title(titles[i])
   plt.xticks([]),plt.yticks([])#X,Y轴标空
plt.show()

图片

girl.png

运行结果

在这里插入图片描述

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
基于k-means图像分割是一种常见的图像处理方法,可以将一张图像分成多个区域,每个区域内的像素具有相似的颜色或亮度。在Python中,可以使用OpenCV和sklearn库来实现基于k-means图像分割。 以下是一个基于k-means图像分割的Python代码示例: ```python import cv2 import numpy as np from sklearn.cluster import KMeans # 读入图像 img = cv2.imread('image.jpg') # 将图像转换为一维数组 img_flat = img.reshape((-1,3)) # 进行k-means聚类 kmeans = KMeans(n_clusters=5, random_state=0).fit(img_flat) # 获取聚类中心 centers = np.uint8(kmeans.cluster_centers_) # 将每个像素点重新赋值为其所在聚类的中心值 new_img = centers[kmeans.labels_] # 将一维数组转换回图像形式 new_img = new_img.reshape(img.shape) # 显示原图和分割后的图像 cv2.imshow('image', img) cv2.imshow('segmented image', new_img) cv2.waitKey(0) ``` 在上面的代码中,首先读入图像并将其转换为一维数组。然后使用KMeans函数进行聚类,将像素点分成5个类别。接着获取聚类中心,并将每个像素点重新赋值为其所在聚类的中心值。最后将一维数组转换回图像形式,并显示原图和分割后的图像。 需要注意的是,这种基于k-means图像分割方法并不是完美的,可能会出现一些分割不清晰或者分割不准确的情况。如果需要更加精确的图像分割效果,可以考虑使用其他算法或者结合多种算法来进行处理

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值