玩命加载中...
### 3. NMF压缩图像 非负矩阵分解(NMF)是一个常用的对矩阵进行填充、平滑的算法。一个著名的案例就是Netflix利用NMF来填充“用户-电影”矩阵。这里,我们将对三个颜色逐一进行矩阵分解。 $$d\_{\text{Red}}= P\_{\text{Red}} Q\_{\text{Red}}$$ 这里$d\_{\text{Red}}$是$600\times 800$的矩阵,$P\_{\text{Red}}$是$600\times K$的非负矩阵,$Q\_{\text{Red}}$是$K\times 800$的非负矩阵,其中$K$的矩阵分解中成分的个数。通常成分个数越多,拟合效果越好。 假如这个$600\times 800$的图像中每个像素点的颜色都不一样,那么我们需要 $$800\times 600 \times 3 = 1440000$$ 个数来表示这个图像。对于NMF压缩之后的图像,我们只需要 $$600 \times K \times 3 + K \times 800 \times 3$$ 个数来表示。在$K$较小时,比如100以内,NMF的压缩效率明显优于K Means。 下面,我们就来看看NMF压缩后的图像的视觉效果。 下面的函数`NMFImage(d, num_components)`就可以用来生成根据NMF压缩得到的图像。 ```python from sklearn.decomposition import NMF def NMFImage(d, num_components): w, h, c = d.shape new_img = d.copy() for i in range(c): nmf = NMF(n_components=num_components) P = nmf.fit_transform(d[:, :, i]) Q = nmf.components_ new_img[:, : ,i] = np.clip(P @ Q, 0, 1) return {'new_image': new_img} ``` 运行以上函数,我们可以看看在不同的成分个数取值之下,图像压缩的效果。 ```python plt.figure(figsize=(12, 9)) plt.imshow(d); plt.axis('off') plt.show() for i in [1, 2, 3]: print('Number of components:', i) out = NMFImage(d, i) new_image = out['new_image'] plt.figure(figsize=(12, 9)) plt.imshow(new_image); plt.axis('off') plt.show() ``` `Number of components: 1` <img src="nmf_1.jpg" style="max-width:95%;" /> `Number of components: 2` <img src="nmf_2.jpg" style="max-width:95%;" /> `Number of components: 3` <img src="nmf_3.jpg" style="max-width:95%;" /> `Number of components: 5` <img src="nmf_5.jpg" style="max-width:95%;" /> `Number of components: 10` <img src="nmf_10.jpg" style="max-width:95%;" /> `Number of components: 20` <img src="nmf_20.jpg" style="max-width:95%;" /> `Number of components: 80` <img src="nmf_80.jpg" style="max-width:95%;" /> `Number of components: 150` <img src="nmf_150.jpg" style="max-width:95%;" /> ### 4. 完整代码 **点击[这里](http://sofasofa.io/tutorials/image_compression/taibei101.jpg)下载实验图片**。 ```python import numpy as np import matplotlib.pyplot as plt from skimage import io from sklearn.cluster import KMeans from sklearn.decomposition import NMF # 利用K Means进行压缩 def KMeansImage(d, n_colors): w, h, c = d.shape dd = np.reshape(d, (w * h, c)) km = KMeans(n_clusters=n_colors) km.fit(dd) labels = km.predict(dd) centers = km.cluster_centers_ new_img = d.copy() for i in range(w): for j in range(h): ij = i * h + j new_img[i][j] = centers[labels[ij]] return {'new_image': new_img, 'center_colors': centers} # 利用NMF进行压缩 def NMFImage(d, n_components): w, h, c = d.shape new_img = d.copy() for i in range(c): nmf = NMF(n_components=n_components) P = nmf.fit_transform(d[:, :, i]) Q = nmf.components_ new_img[:, : ,i] = np.clip(P @ Q, 0, 1) return {'new_image': new_img} # 查看K Means在不同聚类个数下的视觉效果 plt.figure(figsize=(12, 9)) plt.imshow(d); plt.axis('off') plt.show() for i in [2, 3, 5, 10, 20, 30]: print('Number of clusters:', i) out = KMeansImage(d, i) centers, new_image = out['center_colors'], out['new_image'] plt.figure(figsize=(12, 1)) plt.imshow([centers]); plt.axis('off') plt.show() plt.figure(figsize=(12, 9)) plt.imshow(new_image); plt.axis('off') plt.show() # 查看NMF在不同成分个数下的视觉效果 plt.figure(figsize=(12, 9)) plt.imshow(d); plt.axis('off') plt.show() for i in [1, 2, 3, 5, 10, 20, 30, 50, 80, 150]: print('Number of components:', i) out = NMFImage(d, i) new_image = out['new_image'] plt.figure(figsize=(12, 9)) plt.imshow(new_image); plt.axis('off') plt.show() ``` <ul class="pagination"> <li><a href="index.php">第1页</a></li> <li class="active"><a href="#">第2页</a></li> </ul> <ul class="pager"> <li class="previous"><a href="index.php"><b>&larr; 返回前一页</b></a></li> <li class="next"><a href="../../tutorials.php"><b><i class="fa fa-graduation-cap" aria-hidden="true"></i>&nbsp; 学完咯!</b></a></li> </ul>