为了账号安全,请及时绑定邮箱和手机立即绑定

Python SVD 修复重建图像的特征值数量?

Python SVD 修复重建图像的特征值数量?

慕仙森 2023-03-01 16:10:58
我正在尝试重建我之前使用 SVD 分解的图像。图片是这样的:我用这段代码成功分解了图像:from PIL import Imageimport numpy as npimport matplotlib.pyplot as pltimg = Image.open('steve.jpg')img = np.mean(img, 2)U,s,V = np.linalg.svd(img)s图像奇异值的数组。我取的奇异值越多,重建图像与原始图像就越相似。例如,如果我取 20 个奇异值:n = 20S = np.zeros(np.shape(img))for i in range(0, n):    S[i, i] = s[i]recon_img = U@S@Vplt.imshow(recon_img)plt.axis('off')plt.show()我想固定奇异值的最小数量以获得良好的pretty结果:与原始图像相似的图像。此外,我想看看当我采用更多的奇异值时结果会发生多少变化。我尝试了一个动画但没有成功:from PIL import Imageimport numpy as npimport matplotlib.pyplot as pltfrom matplotlib.animation import FuncAnimationimg = Image.open('steve.jpg')img = np.mean(img, 2)U,s,V = np.linalg.svd(img)fig = plt.figure()def update(i):    S = np.zeros(np.shape(img))    n = 20    for i in range(0, n):        S[i, i] = s[i]    recon_img = U@S@V    plt.imshow(recon_img)    plt.axis('off')ani = FuncAnimation(fig = fig, func = update, frames = 20, interval = 10)plt.show()
查看完整描述

1 回答

?
慕码人2483693

TA贡献1860条经验 获得超9个赞

如果您绘制s奇异值,您可以看到一条非常陡峭的下降曲线,如果您对 y 轴使用对数刻度则更好:

plt.semilogy(s, 'k-')

//img1.sycdn.imooc.com//63ff08d10001ce5405790440.jpg

如您所见,前 50 个奇异值是最重要的:几乎每个奇异值都超过 1000。从 ~50 到 ~250 的值低一个数量级,并且它们的值缓慢下降:包含曲线的斜率(记住对数 y 标度)。那个蜜蜂说我会用前 50 个元素来重塑你的形象。


关于动画:当动画逐帧更新时,计数器i增加 1。在您的代码中,您错误地使用了i切片s和定义S;你应该重命名柜台。
此外,随着动画的进行,您需要采用越来越多的奇异值,这是n逐帧保持不变的设置。您需要n在每个循环中更新,因此您可以将其用作计数器。
此外,您需要擦除之前绘制的图像,因此您需要plt.gca().cla()在函数的开头添加一个update
检查下面的代码以供参考:

from PIL import Image

import numpy as np

import matplotlib.pyplot as plt

from matplotlib.animation import FuncAnimation


img = Image.open('steve.jpg')

img = np.mean(img, 2)


U,s,V = np.linalg.svd(img)


fig, ax = plt.subplots(1, 2, figsize = (4, 4))


ax[0].imshow(img)

ax[0].axis('off')

ax[0].set_title('Original')


def init():

    ax[1].cla()

    ax[1].imshow(np.zeros(np.shape(img)))

    ax[1].axis('off')

    ax[1].set_title('Reconstructed\nn = 00')



def update(n):

    ax[1].cla()

    S = np.zeros(np.shape(img))

    for i in range(0, n):

        S[i, i] = s[i]


    recon_img = U@S@V


    ax[1].imshow(recon_img)

    ax[1].axis('off')

    ax[1].set_title(f'Reconstructed\nn = {n:02}')


ani = FuncAnimation(fig = fig, func = update, frames = 50, init_func = init, interval = 10)

ani.save('ani.gif', writer = 'imagemagick')


plt.show()

这给了这个动画:

https://i.stack.imgur.com/6loY5.gif

如您所见,前 50 个元素足以很好地重建图像。其余元素增加了一些噪音并稍微改变了背景。



查看完整回答
反对 回复 2023-03-01
  • 1 回答
  • 0 关注
  • 74 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信