k均值聚类 图像分割实战 python

算法源于西瓜书309页介绍的约束种子k均值算法

k均值聚类 图像分割实战 python_第1张图片

 1.事先标注好一部分数据:

k均值聚类 图像分割实战 python_第2张图片k均值聚类 图像分割实战 python_第3张图片

绿色部分是前景 对应的rgb是[0,255,0] 

蓝色部分是背景 rgb[0,0,255]

2.

根据标注好的数据,遍历原始图片中的每一个像素点

计算该像素点与前景、背景的距离

与前景距离小就并入前景,否则并入背景

循环往复,直至前景,背景不再变化

代码:

import matplotlib.image as mpimg
import numpy as np
from PIL import Image

im = mpimg.imread('D:\\pythonProject\\data\\selectedimages\\monkey.bmp')
im2 = mpimg.imread('D:\\pythonProject\\data\\selectedimages\\monkey_marker.bmp')
im = np.array(im)
im2 = np.array(im2)
dst = np.zeros((im2.shape[0], im2.shape[1], 3))
S_f = []
S_b = []


def init_S():
    for i in range(im2.shape[0]):
        for j in range(im2.shape[1]):
            if (im2[i][j] == [0, 255, 0]).all():
                S_f.append([i, j])
            if (im2[i][j] == [0, 0, 255]).all():
                S_b.append([i, j])


def count_ave_color_f():
    R_a = 0
    G_a = 0
    B_a = 0
    for k in S_f:
        R_a += im[k[0]][k[1]][0]
        G_a += im[k[0]][k[1]][1]
        B_a += im[k[0]][k[1]][2]
    ave_color_f = np.array([int(R_a / len(S_f)), int(G_a / len(S_f)), int(B_a / len(S_f))])
    return ave_color_f


def count_ave_color_b():
    R_b = 0
    G_b = 0
    B_b = 0
    for k in S_b:
        R_b += im[k[0]][k[1]][0]
        G_b += im[k[0]][k[1]][1]
        B_b += im[k[0]][k[1]][2]
    ave_color_b = np.array([int(R_b / len(S_b)), int(G_b / len(S_b)), int(B_b / len(S_b))])
    return ave_color_b


T = 0
init_S()
count = []
num = 0
while T < 10:
    T += 1
    a_c_f = count_ave_color_f()
    a_c_b = count_ave_color_b()
    count.append([a_c_f, a_c_b])
    if T >= 2:
        x = count.pop(0)
        if (x[0] == a_c_f).any() and (x[1] == a_c_b).any():
            print('均值向量不再变化')
            break

    S_f = []
    S_b = []
    for i in range(im2.shape[0]):
        for j in range(im2.shape[1]):
            d_f = np.sqrt(sum(np.power((a_c_f - im[i][j]), 2)))
            d_b = np.sqrt(sum(np.power((a_c_b - im[i][j]), 2)))
            if d_f < d_b:
                S_f.append([i, j])
            else:
                S_b.append([i, j])

    print('前景像素:', len(S_f), '\t', '背景像素:', len(S_b))
    print('第%d轮迭代结束,' % T, '前景的均值为:', a_c_f, '背景的均值为:', a_c_b)

##画图
for i in S_f:
    dst[i[0], i[1]] = [255, 255, 255]  ###将前景转为白色
for j in S_b:
    dst[j[0], j[1]] = [0, 0, 0]  ###将背景转为黑色

img2 = Image.fromarray(np.uint8(dst))
img2.show(img2)
img2.save("output.png", "png")

运行结果:k均值聚类 图像分割实战 python_第4张图片

 

这个聚类方法只能处理特定的图像,也就是前景背景均值向量差距较大的图片,实际运用效果不怎么样,但是练练手还可以。

你可能感兴趣的:(python,均值算法,聚类)