概述
颜色量化
减少原图像中所用颜色,让新图像尽可能地从视觉上和原图像相似。
搭建一个模型,可以学习一张图像中的颜色,然后用学到的知识来重构原图像。
系统环境
macOS 10.14
实验
环境搭建
安装Numpy
python -m pip install numpy scipy matplotlib
下载后可能需要退出命令行重新进入
下载 MiniSom
python
pip install minisom
安装PIL
sudo pip install Pillow
导入
导入 MiniSom 类,以及 Numpy 和 matplotlib
from minisom import MiniSom
import numpy as np
import matplotlib.pyplot as plt
注意MiniSom大小写
加载图像
使用 matplotlib 的 imread 实用程序, 将图像加载为一个数组。
右键->拷贝图像可复制路径,注意图片格式
img = plt.imread(‘/Users/yangxiaoyan/Desktop/pig.jpg’)
使用 matplotlib 中的 imshow 函数来查看加载后的图像。
plt.imshow(img)
检查一下加载后的图像形状。
Img.shape
可以看到它是一个 3D 矩阵。将1080乘以1440 ,把数组转换为一个 2D 数组。再用 Numpy 的 shape 属性来检查它的形状。
pixels = np.reshape(img, (img.shape[0]*img.shape[1], 3))
Pixels.shape
SOM 初始化和训练
初始化 MiniSom 对象并将其分配给变量 som
som = MiniSom(x= 3, y = 3, input_len = 3, sigma=0.1, learning_rate=0.2)
som参数:
- 维度 - 构建一个 3*3 的 SOM,即得到的最终颜色将是 3 * 3,即 9。SOM 越大,训练所需的时间就越长。
- input_len - 数据集中的特征数量。使用 3,对应像素数组的形状。如果使用其它数字,会得到一个值错误异常,指示 MiniSom 无法将形状(3)中的输入数组发送到你选择的数字中。
- sigma - SOM 中不同相邻节点的半径,默认值为 1.0。
- learning_rate - 每次迭代期间权重的调整幅度。
将SOM的权重初始化为小的标准化随机值
使用random_weights_init函数并传入数据(像素)
som.random_weights_init(pixels)
保存起始权重,它们代表图像的初始颜色。稍后会将它们可视化。
使用 get_weights 函数和 Python 的副本来确保在权重更新之前得到它们。
starting_weights = som.get_weights().copy()
通过运行 train_random 函数来训练像素。它需要两个参数,第一个参数是需要训练的数据集,第二个参数是迭代次数。
som.train_random(pixels, 50)
向量量化
量化图像的每个像素,减少图像中的颜色数量。
使用 MiniSom 中的 quantization 实用程序。
qnt = som.quantization(pixels)
创建新图像
过程的开始将图像转换成 2D 数组。但现在将图像构建为 3D 图像。
用在开头加载的图像维度创建一个只有零的矩阵来完成这项工作。
借助 Numpy 的 zero 实用程序
clustered = np.zeros(img.shape)
将量化后的值放入新图像中。
使用 Numpy 的 unravel_index 功能。这个函数有三个参数:
-
indices - array_like
一个整数数组,其元素是维度变成数组的平铺版本的索引。 -
dims
整数元组整数元组 -
Order:{‘C’,‘F’},可选
确定是否应将索引视为以行主(C样式)或列主(Fortran样式)顺序编制索引。for i, q in enumerate(qnt): clustered [np.unravel_index(i, dims=(img.shape[0], img.shape[1]))] = q
注意缩进
显示结果
Matplotlib 可用 imshow 在轴上绘制图像。
使用一个 Matplotlib 图和 4 个子图来完成绘图。第一个和第二个子图将显示原始图像和新图像。第三和第四个子图将显示初始图像颜色和 SOM 学习的颜色。
创建一个 12*6 的图像。然后创建子图,它有 3 个参数:行数,列数和图索引。当这些数字小于 10 时,可以作为三位数传递,如下所示。然后使用 Matplotlib 的 imshow 来绘制图像。
plt.figure(figsize=(12, 6))
plt.subplot(221)
plt.title('Original')
plt.imshow(img)
plt.subplot(222)
plt.title('Result')
plt.imshow(clustered)
以类似的方式创建第三和第四个子图。
plt.subplot(223)
plt.title('Initial Colors')
plt.imshow(starting_weights)
plt.subplot(224)
plt.title('Learnt Colors')
plt.imshow(som.get_weights())
使用 tight_layout 功能来确保绘图不会挤在一起。最后,使用 plt.show()绘制它们。
plt.tight_layout()
plt.show()
如果出现图像不显示问题
import pylon
put.imshow(img)
pylon.show()
成功搭建了一个 SOM 网络,能够完成颜色量化任务,重构原图像。
运行结果
第一次:图像选择失败,原有颜色过少
第二次
参考文章
SOM是怎样一种模型(对于初学者如何操作,算法等)? - 景略集智的回答 - 知乎
https://www.zhihu.com/question/28046923/answer/499882606