惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
宝玉的分享
宝玉的分享
G
Google Developers Blog
T
Tailwind CSS Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
V2EX
V
Visual Studio Blog
博客园 - Franky
S
SegmentFault 最新的问题
Jina AI
Jina AI
爱范儿
爱范儿
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
D
DataBreaches.Net
C
Check Point Blog
月光博客
月光博客
P
Proofpoint News Feed
T
The Blog of Author Tim Ferriss
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MongoDB | Blog
MongoDB | Blog
The GitHub Blog
The GitHub Blog
Y
Y Combinator Blog
Martin Fowler
Martin Fowler

卡瓦邦噶!

服务器高性能网络调优 | 卡瓦邦噶! 为何写作 | 卡瓦邦噶! 读《金阁寺》 | 卡瓦邦噶! 雨季又来 | 卡瓦邦噶! MTU Probe 引起的初始延迟 | 卡瓦邦噶! 3.5 秒的固定延迟问题 | 卡瓦邦噶! 学习网络的一点经验 | 卡瓦邦噶! ARP 问题诊断 | 卡瓦邦噶! 网络断断续续…… | 卡瓦邦噶! Piccolo P2P 镜像分发 | 卡瓦邦噶! 一起看电影 | 卡瓦邦噶! 《征服C指针》 | 卡瓦邦噶! 我的姥姥 | 卡瓦邦噶! Python的哲学 Python 3.5的新特性 学校不教的计算机课 垃圾回收(GC)的三种基本方式 在编程中体验纯粹的快乐 从《美丽新世界》谈自由 在快钱实习 迷人的嗓音和迷人的故事——《Sleepyhead》 Python 的十个自然语言处理工具 记一个愚蠢的bug 一年炉石传说的游戏体验 《以撒的结合:重生》网页版图鉴 分清 C++的指针、引用和数组 笑话三则 自由比皇帝更伟大——《悲惨世界》笔记 Git 10 周年访谈:Linus 讲述背后故事 用 0x3f3f3f3f 设定最大int值的优点
SLIC算法分割超像素原理及Python实现
laixintao · 2017-03-13 · via 卡瓦邦噶!

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

import math

from skimage import io, color

import numpy as np

from tqdm import trange

class Cluster(object):

    cluster_index = 1

    def __init__(self, h, w, l=0, a=0, b=0):

        self.update(h, w, l, a, b)

        self.pixels = []

        self.no = self.cluster_index

        self.cluster_index += 1

    def update(self, h, w, l, a, b):

        self.h = h

        self.w = w

        self.l = l

        self.a = a

        self.b = b

    def __str__(self):

        return "{},{}:{} {} {} ".format(self.h, self.w, self.l, self.a, self.b)

    def __repr__(self):

        return self.__str__()

class SLICProcessor(object):

    @staticmethod

    def open_image(path):

        """

        Return:

            3D array, row col [LAB]

        """

        rgb = io.imread(path)

        lab_arr = color.rgb2lab(rgb)

        return lab_arr

    @staticmethod

    def save_lab_image(path, lab_arr):

        """

        Convert the array to RBG, then save the image

        """

        rgb_arr = color.lab2rgb(lab_arr)

        io.imsave(path, rgb_arr)

    def make_cluster(self, h, w):

        return Cluster(h, w,

                       self.data[h][w][0],

                       self.data[h][w][1],

                       self.data[h][w][2])

    def __init__(self, filename, K, M):

        self.K = K

        self.M = M

        self.data = self.open_image(filename)

        self.image_height = self.data.shape[0]

        self.image_width = self.data.shape[1]

        self.N = self.image_height * self.image_width

        self.S = int(math.sqrt(self.N / self.K))

        self.clusters = []

        self.label = {}

        self.dis = np.full((self.image_height, self.image_width), np.inf)

    def init_clusters(self):

        h = self.S / 2

        w = self.S / 2

        while h < self.image_height:

            while w < self.image_width:

                self.clusters.append(self.make_cluster(h, w))

                w += self.S

            w = self.S / 2

            h += self.S

    def get_gradient(self, h, w):

        if w + 1 >= self.image_width:

            w = self.image_width - 2

        if h + 1 >= self.image_height:

            h = self.image_height - 2

        gradient = self.data[w + 1][h + 1][0] - self.data[w][h][0] + \

                   self.data[w + 1][h + 1][1] - self.data[w][h][1] + \

                   self.data[w + 1][h + 1][2] - self.data[w][h][2]

        return gradient

    def move_clusters(self):

        for cluster in self.clusters:

            cluster_gradient = self.get_gradient(cluster.h, cluster.w)

            for dh in range(-1, 2):

                for dw in range(-1, 2):

                    _h = cluster.h + dh

                    _w = cluster.w + dw

                    new_gradient = self.get_gradient(_h, _w)

                    if new_gradient < cluster_gradient:

                        cluster.update(_h, _w, self.data[_h][_w][0], self.data[_h][_w][1], self.data[_h][_w][2])

                        cluster_gradient = new_gradient

    def assignment(self):

        for cluster in self.clusters:

            for h in range(cluster.h - 2 * self.S, cluster.h + 2 * self.S):

                if h < 0 or h >= self.image_height: continue

                for w in range(cluster.w - 2 * self.S, cluster.w + 2 * self.S):

                    if w < 0 or w >= self.image_width: continue

                    L, A, B = self.data[h][w]

                    Dc = math.sqrt(

                        math.pow(L - cluster.l, 2) +

                        math.pow(A - cluster.a, 2) +

                        math.pow(B - cluster.b, 2))

                    Ds = math.sqrt(

                        math.pow(h - cluster.h, 2) +

                        math.pow(w - cluster.w, 2))

                    D = math.sqrt(math.pow(Dc / self.M, 2) + math.pow(Ds / self.S, 2))

                    if D < self.dis[h][w]:

                        if (h, w) not in self.label:

                            self.label[(h, w)] = cluster

                            cluster.pixels.append((h, w))

                        else:

                            self.label[(h, w)].pixels.remove((h, w))

                            self.label[(h, w)] = cluster

                            cluster.pixels.append((h, w))

                        self.dis[h][w] = D

    def update_cluster(self):

        for cluster in self.clusters:

            sum_h = sum_w = number = 0

            for p in cluster.pixels:

                sum_h += p[0]

                sum_w += p[1]

                number += 1

                _h = sum_h / number

                _w = sum_w / number

                cluster.update(_h, _w, self.data[_h][_w][0], self.data[_h][_w][1], self.data[_h][_w][2])

    def save_current_image(self, name):

        image_arr = np.copy(self.data)

        for cluster in self.clusters:

            for p in cluster.pixels:

                image_arr[p[0]][p[1]][0] = cluster.l

                image_arr[p[0]][p[1]][1] = cluster.a

                image_arr[p[0]][p[1]][2] = cluster.b

            image_arr[cluster.h][cluster.w][0] = 0

            image_arr[cluster.h][cluster.w][1] = 0

            image_arr[cluster.h][cluster.w][2] = 0

        self.save_lab_image(name, image_arr)

    def iterate_10times(self):

        self.init_clusters()

        self.move_clusters()

        for i in trange(10):

            self.assignment()

            self.update_cluster()

            name = 'lenna_M{m}_K{k}_loop{loop}.png'.format(loop=i, m=self.M, k=self.K)

            self.save_current_image(name)

if __name__ == '__main__':

    p = SLICProcessor('Lenna.png', 500, 30)

    p.iterate_10times()