SNIC(Python实现)

# @Time : 2022/1/29
# @Author : hcl
import cv2
import numpy as np
import queue
import time
from matplotlib import pyplot as plt


def imgShow(window_title, image):
    cv2.imshow(window_title, image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


def distance(center, element):
    """
    计算element和聚类中心的距离
    :param center: 聚类中心
    :param element:
    :return:
    """
    distance_x = pow(center[0] - element[0], 2) + pow(center[1] - element[1], 2)
    distance_c = pow(img_lab[center[0]][center[1]] - img_lab[element[0]][element[1]], 2)
    distance_c = sum(distance_c)
    return pow(distance_x / height_s + distance_c / m, 0.5)


def updateCenter():
    """
    更新质心
    :return:
    """
    # points是所有以key为质心的点的列表
    old_center = R[old_index]
    sum_points[old_index][0] += key[0]
    sum_points[old_index][1] += key[1]
    sum_points[old_index][2] += 1
    points = result[old_center]
    value = sum_points[old_index]
    new_center = value[0] // value[2], value[1] // value[2]
    R[old_index] = new_center
    result.pop(old_center)
    points.append(key)
    result[new_center] = points


def findNeighbor(point):
    neighbors = [(point[0] - 1, point[1] - 1), (point[0] - 1, point[1]), (point[0] - 1, point[1] + 1),
                 (point[0], point[1] - 1), (point[0], point[1] + 1),
                 (point[0] + 1, point[1] - 1), (point[0] + 1, point[1]), (point[0] + 1, point[1] + 1)]
    new_neighbors = []
    for x, y in neighbors:
        if 0 <= x < height and 0 <= y < width:
            new_neighbors.append((x, y))
    return new_neighbors


start_time = time.time()
img = cv2.imread(r'161062.jpg')
# 如果图片过大可以先resize
# img = cv2.resize(img, (0, 0), fx=0.2, fy=0.2)
print(img.shape)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
img_lab = np.array(img_lab, dtype=int)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
height, width, _ = img_lab.shape
num_points = height * width
# height_s和width_s是初始化一个簇的大小,我在这里初始化的时候没有初始化簇心的数量,我初始化的是簇的大小
height_s = height // 10
width_s = width // (width // height_s)
print(width_s, height_s)
num_k = height // height_s * (width // width_s)
print(f'簇心个数:{num_k}')
m = 20
# 点 和 index的关系
L = {}
# index 和 点的关系
R = {}
# 点: [点的横坐标之和, 点的纵坐标之和, 点的数量]
sum_points = {}
elements = queue.PriorityQueue()
result = {}
for i in range(height):
    for j in range(width):
        L[(i, j)] = 0

index = 0
min_dist = {}
for i in range(height // height_s):
    for j in range(width // width_s):
        index += 1
        R[index] = (i * height_s + height_s // 2, j * width_s + width_s // 2)
        elements.put([0, R[index], index])
        min_dist[R[index]] = 0
        result[(i * height_s + height_s // 2, j * width_s + width_s // 2)] = []
        sum_points[index] = [0, 0, 0]

i = 1
rate = 0
while not elements.empty():
    e = elements.get()
    key = e[1]
    if L[key] == 0:
        if i / num_points * 100 > rate + 0.1:
            print('\r', end='')
            rate = i / num_points * 100
            print(f'进度:{rate}%', end='')
        i += 1
        L[key] = e[2]
        old_index = L[key]
        updateCenter()
        key_neighbors = findNeighbor(key)
        for key_neighbor in key_neighbors:
            if L[key_neighbor] == 0:
                dist = distance(R[old_index], key_neighbor)
                if key_neighbor not in min_dist:
                    min_dist[key_neighbor] = dist
                    elements.put([dist, key_neighbor, old_index])
                elif dist < min_dist[key_neighbor]:
                    min_dist[key_neighbor] = dist
                    elements.put([dist, key_neighbor, old_index])

j = 0
for k, v in result.items():
    for i in v:
        gray[i[0]][i[1]] = 31 * j
    j += 1

# 绘制边界
for i in range(1, height - 1):
    for j in range(1, width - 1):
        count = 0
        point_neighbor = [(i - 1, j - 1), (i - 1, j), (i - 1, j + 1),
                          (i, j - 1), (i, j + 1),
                          (i + 1, j - 1), (i + 1, j), (i + 1, j + 1)]
        for neighbor in point_neighbor:
            if gray[neighbor[0]][neighbor[1]] != gray[i][j]:
                count += 1
        if count > 2:
            img[i][j][0] = 255
            img[i][j][1] = 0
            img[i][j][2] = 0

print('\r', end='')
print('进度:100%')
print(f'总耗时:{time.time() - start_time}秒')
plt.imshow(img)
plt.show()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值