大家好,欢迎来到IT知识分享网。
1. VQ(即Vector Quantization,矢量量化),其作用:将一个向量空间中的点,用其中一个有限子集中的点,进行编码;应用场景也很广泛,如图像压缩,声音压缩,CV领域特征降维等。
2. 数学含义:将矢量空间中的 k 维矢量映射到矢量的有限集合
- 即向量空间 R k R^k Rk中的所有x,都可以使用有限集合Y中的值表示:
Y = { y i : i = 1 , 2 , 3 , . . . , N } Y=\{y_i:i=1, 2,3,…,N\} Y={
yi:i=1,2,3,…,N}
- 且每个 x 都有相应邻域中的 y i y_i yi与之对应
3. 考虑一个图像编码的例子,有一个简单的图像使用VQ编码,例如:
其中:左边是原图,中间是codebook,右边是vq编码后的图像
其中:红色点就是对上述原图使用k-means聚类后得到的centroids
4. 对图像进行vq编码就是:将原图像中每个像素点当作一个数据,使用 K-means聚类得到 k 个centroids(即codebook中的值) ,然后用这些 centroids 的像素值来代替对应原图像中所有点的像素值,代码如下:
import numpy as np from scipy.cluster.vq import vq, kmeans import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D def plot_scatter(data, codebook): fig = plt.figure() ax = fig.add_subplot(111, projection='3d') colors = np.random.rand(data.shape[0]) # 散点颜色 sizes = np.random.randint(low=50, high=150, size=data.shape[0]) # 散点大小 ax.set_xlabel('R-X', c='r') ax.set_ylabel('G-Y', c='g') ax.set_zlabel('B-Z', c='b') ax.scatter(data[:, 0], data[:, 1], data[:, 2], c=colors, s=sizes, alpha=1) ax.scatter(codebook[:, 0], codebook[:, 1], codebook[:, 2], c='r', s=150) plt.show() return def test_vq(): # # data features = np.array([[121.6, 147.2, 108.8], [96.9, 160.6, 140.8], [51.2, 38.4, 108.8], [204.9, 179.2, 172.8], [40.5, 56.3, 98.6], [168.2, 182.1, 192.3]]) # # discrete data # features = np.array([[0., 0., 0.], # [12., 12., 12.], # [0., 0., 0.], # [12., 12., 12.], # [12., 12., 12.], # [0., 0., 0.]]) # # random data. # np.random.seed(seed=4321) # features = np.random.uniform(0., 1.0, size=(10, 3)) * 255 # codebook. code_book, dist = kmeans(features, 3, seed=4321) code_book = np.around(code_book, 1) # vq code_index, distor = vq(features,code_book) vq_data_from_codebook = code_book[code_index,:] print(f'code book: \n', code_book) print('-' * 128) print(f'code index from codebook: {
code_index}') print('-' * 128) print('vq data from codebook: \n{}'.format(vq_data_from_codebook)) print('-' * 128) print('vq distance: \n', distor) print('-' * 128) print('validation distance: \n', np.linalg.norm(features - vq_data_from_codebook, axis=1)) print('-' * 128) print('first row distance: \n', np.sqrt(np.sum(np.square(features[0] - vq_data_from_codebook[0])))) # plot plot_scatter(data=features, codebook=code_book) if __name__ == "__main__": test_vq()
注:代码对离散图像数据也是适合的
对于彩色图片来说,也可以用同样的方法来做,例如 RGB 彩色图像,每一个像素被当作是一个 3 维向量空间中的点, 使用scipy库中的k-means和vq,将centroids的个数分别为: 2,10,100,200;代码如下:
import os from scipy.cluster.vq import kmeans, vq import numpy as np from PIL import Image ''' blog: https://www.cnblogs.com/Higgerw/p/15238513.html ''' def k_vq(data, k, iter=20): print('Generating vq-%d...' % k) (centroids, distor) = kmeans(data, k, iter=iter) # get discrete codebook. (code_index, distor) = vq(data, centroids) # get discrete index from centroids. print('distor: %.6f' % distor.sum()) return centroids, code_index def main(): # get image. # path = 'lenna.jpg' path = 'xiaojiejie.jpg' pic = Image.open(path) data = np.array(pic) height, width, channel = data.shape data = np.float32(np.reshape(data, (height*width, channel))) # save path os.makedirs('output', exist_ok=True) vqclst = [2, 10, 100, 200] for k in vqclst: codebook, code_index = k_vq(data, k) im_vq = codebook[code_index, :] new_data = np.uint8(np.reshape(im_vq, (height, width, channel))) # h x w x c new_pic = Image.fromarray(new_data) new_pic.save('output/result-%d.jpg' % k) if __name__ == "__main__": # main()
运行代码的结果:
5. 那么重点来了,这里求解codebook是通过使用k-means聚类,k-means算法聚类一般通过欧氏距离求解属于同一簇的centroid的,而VQ-GAN中是先随机初始化一个N维的Embedding(也即是N维的codebook),然后计算Embedding与图像的featuremap的距离,通过卷积神经网络的反向传播算法更新Embedding中的值的到最后的codebook的,所以二者的原理是相似的。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/147608.html