Python|用Python生成NFT超像素风格头像( 二 )


因此 , 每个像素 , 以及聚类中心点 , 都将被表示成一个5维向量 ,CIELAB色彩空间的l、a、b , 以及当前像素或聚类中心在图片的x和y空间位置 。
直接按照欧氏距离计算 , 色彩偏差 , 与空间位置偏差 , 即

但 , 这样的计算方式 , 在图片过大、超像素宽度过小时 , 带来计算上偏向于色差或距离的问题 。 所以进一步需要做归一化 。

其中Ns=S , 即超像素平均宽度 , Nc表示图片中最大色差 (通常设定一个经验值即可 , 如论文默认用 10 , 为了做出比较有风格化的图片 , 色差超参Nc=m可以调大 , 越大像素的融合效应越强)
进一步精简得到

SLIC实现预处理图片的读取 , 以及将 RGB 色彩空间转换到 LBA , skimage.color 提供了转换函数 rgb2lab , 转换原理见https://blog.csdn.net/bby1987/article/details/109522126 。


\"\"\"
Return: 3D array color space [LAB

处理了带四通道的情况
\"\"\"
def read_image_in_lab_space(path):    
   img = Image.open(path)
   #部分图片有4通道 , 带透明度等情况 ,需要转成 RGB
   img = img.convert('RGB')
   rgb = np.asarray(img)
   lab = color.rgb2lab(rgb)
   height = lab.shape[0

   width = lab.shape[1

   return lab height width

初始化K表示超级像素在当前图的个数 , N为当前图形的像素个数即 ’图片长 x 图片高‘ , M表示色度强弱表示对于图片聚类中心选择的权重 , 越大则影响越小 。 从风格化的角度看 , K越大 , 超级像素越多 , 则对应的结果越精细 , M越小则对应的图片越精细 , 反之亦然 。 超像素区块宽度S~sqrt(N/K) , 可以通过像素点个数和K计算得到 。
初始化 , 按照S步长宽度得到 S x S 大小的区块 , 并且指定区块中心的像素为中心点 。 并且将每个像素关联到的聚类标签初始化为l(xy) = -1到聚类中心的距离记为d(xy) = ∞ 。

'''
@K how many clusters/superpixels in image.
@M max color distance in image [1-40

return K clusters (5-dim vectors)
'''
def intialize(lab K M height width):
   S = int(math.sqrt(height * width / K))
   h = S / 2
   w = S / 2
   clusters = [

 
   #根据s步长 , 设定初始化的中心点
   for x in range(int(S/2) height S):
       for y in range(int(S/2) width S):
           pixel_xy = Pixel(lab[x
[y
[0
lab[x
[y
[1
lab[x
[y
[2
x y)
           cluster = Cluster(pixel_xy)
           clusters.append(cluster)
   
    # 3x3 抗分配边缘线
   for cluster in clusters:
       cluster.move3x3(lab height width)
       
   return clusters

距离函数为了便于理解和实现 , 我们定义了 Pixel 类 , 是一个结构体 , 包含了一个像素 lba 色彩信息以及像素点 x、y 位置 。 Cluster 类实现了 , 聚类中心的更新 , 以及初始化位置优化调整 move3x3 ,move3x3 是为了防止当前选择的聚类中心落在了色差较大的轮廓边缘上 。

class Pixel(object):
   def __init__(self l a b x y):
       self.l self.a self.b self.x self.y = l a b x y
   
   def tonparray(self):
       return np.array([self.l self.a self.b self.x self.y
)

   def update(self arr):
       self.l self.a self.b self.x self.y = arr[0