利用K_means分割图像(opencv的安装,K_means代码)

利用K_means分割图像

step 1 准备工作

安装opencvopencv-python的版本应该要与python的版本一致才可以

首先需要查看自己的python版本号,
Alt

这里我的版本号就是3.11.1,然后根据版本号安装opencv-python,各版本Opencv的对应的各版本Python安装包:,这里只需要找到自己所需要的版本号即可,不用手动安装。下面有教程。

https://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv

在这里插入图片描述

像我的版本3.11.1就是cp311,对应opencv-python-4.5.5

然后看下面这个教程,跟着教程做

opencv 指定版本的安装_opencv_迷路爸爸180-DevPress官方社区 (csdn.net)

安装完成之后,就可以写代码了。

step 2 准备图片

Alt

我们目测一下图中有7中不同颜色的区域,故k=7。

代码如下:

import cv2
import numpy as np
# k-means 参数
k = 7
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)
flags = cv2.KMEANS_RANDOM_CENTERS
# 读取图像
img = cv2.imread('img_1.png')
#img.shape (1000,1000,3)

# 将图像转换为二维数组
Z = img.reshape((-1, 3))#(1000000,3)
#Z必须要把他转化为float32的形式。不转的话下面的cv2.kmeans会报错
Z=np.float32(Z)

# 进行k-means聚类
ret, label, center = cv2.kmeans(Z, k, None, criteria, 10, flags)
#label.shape(1000000,1) label 即把1000000个像素点分类,值为[0-6]
# center.shape(7,3) 即7个中心点,每一个中心点的维度为(1,3) ,三列分别代表RGB的值

# 将结果转换回图像形式
# center = np.uint8(center)
# res = center[label.flatten()]
# res2 = res.reshape((img.shape))

# 设置各类别对应的颜色
colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 0, 255), (0, 255, 255), (255, 255, 255)]

# 遍历每个像素点,根据类别给它着色
for i in range(k):
    Z[label.flatten() == i] = colors[i]
#Z.shape(1000000,3)

#把着色的像素点 Z.shape为(1000000,3),转化为原图片的维度 即(1000,1000,3).
result = Z.reshape((img.shape))

#展示图片
cv2.imshow('kmeans-image-demo',result)
cv2.waitKey(0)
cv2.destroyAllWindows()

最终的结果为

Alt

自己手写K_means

原始的图片

Alt

import numpy as np
import cv2

img = cv2.imread('img_5.jpg')
print(img.shape)  
img_new = img.reshape((-1, 3))
print(img_new.shape)

k = 5
init_center = np.array([[166,246,255], [22,97,55], [195,161,182], [50,54,36],[0,0,0]])
# init_center = np.array([[172,208,196], [16,93,51], [137,219,210], [65,67,46],[0,0,0]])

#找离自己最近的中心点
def findminest(img_new, init_center, k):
    m = img_new.shape[0]
    #记录自己所属的类
    label = np.zeros(m)
    for i in range(m):
        minnest = np.inf
        for j in range(k):
            dis = np.sum((img_new[i, :] - init_center[j, :]) ** 2)
            if dis < minnest:
                minnest = dis
                label[i] = j
    return label

#通过算平均值更新中心点
def update_center(img_new, k, label):
    new_center = np.zeros((k, 3))
    for i in range(k):
        new_center[i, :] = np.mean(img_new[i == label, :], axis=0)
    return new_center

#迭代更新
def run_K_means(img_new, init_center, k, iters):
    m = img_new.shape[0]
    label = np.zeros(m)
    for i in range(iters):
        label = findminest(img_new, init_center, k)
        init_center = update_center(img_new, k, label)
        print(label)
    return label

#迭代次数为10
iters = 10
label = run_K_means(img_new, init_center, k, iters)

#给每一个类着色
colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0),(255,0,255)]
for i in range(k):
    img_new[label.flatten() == i] = colors[i]

#展示图片
cv2.imshow('kmeans-image-demo',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

最终的结果:

Alt

自己手写fuzzy c-means

原始的图片

Alt

import numpy as np
import cv2

#读入图片
img=cv2.imread("img_5.jpg")

#将图像转换为二维数组
img_new=img.reshape((-1,3))

#FCM
#X代表数据,c代表聚类数目,m是加权指标,eps是差别,max_its是最大迭代次数
def FCM(X, c, m, eps, max_its):
    sample_num = X.shape[0]
    # U为隶属度矩阵
    u = np.random.random((sample_num, c))
    # U归一化
    u = u / np.sum(u, axis=1)[:, np.newaxis]
    it = 0
    
    #迭代
    while it < max_its:
        it += 1
        um = u ** m
        # 计算中心
        center = np.dot(um.T, X) / (np.sum(um.T, axis=1))[:, np.newaxis]

        # 计算各个样本点离各中心点的距离
        distance = np.zeros((sample_num, c))
        for i, x in enumerate(X):
            for j, v in enumerate(center):
                distance[i][j] = np.sum((x - v) ** 2)

        # 计算新的u
        new_u = np.zeros((sample_num, c))
        for i in range(sample_num):
            for j in range(c):
                new_u[i][j] = 1. / np.sum((distance[i][j] / distance[i]) ** (2 / (m - 1)))
        
        if np.sum(abs(new_u - u)) < eps:
            break
        u = new_u
        # 返回每一行隶属度最大的类
    return np.argmax(u, axis=1)

c = 5
m=2
max_its = 15
eps=1e-15
idx = FCM(img_new, c,m,eps ,max_its)
print(idx)

#给每一个聚类着色
colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0),(255,0,255)]
for i in range(c):
    img_new[idx.flatten() == i] = colors[i]

#展示着色之后的图片
cv2.imshow('kmeans-image-demo',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

聚类之后的图片

Alt

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值