当前位置: 首页 > news >正文

图片的谱表征

用谱方法来表征图像 Spectral Representations of Natural Images

  • 1.导入库
  • 2.定义相关子函数
  • 3.主函数
    • 3.1 读入lenna图片、resize以及保存
    • 3.2 计算该图像的拉普拉斯矩阵及谱特征
    • 3.3 图像重建及保存
  • 参考文献

本文是对Understanding Convolutions on Graphs以及对应的google colab:SpectralRepresentations.ipynb的学习总结。

通过学习此文,也可以深入理解下图神经网络中谱空间模型。

注意:该colab存在一两处bug,可参考本文fix过的代码。完整代码见https://download.csdn.net/download/WANGWUSHAN/86781716。

1.导入库

import functools
import itertools
import os
import matplotlib.pyplot as plt
import numpy as np
import scipy.sparse
import scipy.sparse.linalg

2.定义相关子函数

主要包括了计算图的拉普拉斯矩阵 L = D − A L=D-A L=DA以及图的重建子函数。

def get_index(x, y, img_width, img_height):
    return y * img_width + x


def get_neighbours(x, y, img_width, img_height):
    neighbours_x_pos = [max(0, x - 1), x, min(x + 1, img_width - 1)]
    neighbours_y_pos = [max(0, y - 1), y, min(y + 1, img_height - 1)]
    neighbours = itertools.product(neighbours_x_pos, neighbours_y_pos)
    neighbours = set(neighbours)
    neighbours.discard((x, y))
    return neighbours


def compute_sparse_laplacian(img_width, img_height):
#计算图的拉普拉斯矩阵
    neighbours_fn = functools.partial(
        get_neighbours, img_width=img_width, img_height=img_height)
    index_fn = functools.partial(
        get_index, img_width=img_width, img_height=img_height)

    senders = []
    recievers = []
    values = []
    for x in range(img_width):
        for y in range(img_height):
            pos = (x, y)
            pos_index = index_fn(*pos)

            degree = 0.
            for neighbour in neighbours_fn(*pos):
                neigh_index = index_fn(*neighbour)
                senders.append(pos_index)
                recievers.append(neigh_index)
                values.append(-1.)
                degree += 1.

            senders.append(pos_index)
            recievers.append(pos_index)
            values.append(degree)
    return scipy.sparse.coo_matrix((values, (senders, recievers)))


def keep_first_components(img_data, num_components):
#图的重建子函数
    orig_shape = img_data.shape
    img_reshaped = np.reshape(img_data, (-1, 3))
    chosen_eigenvecs = eigenvecs[:, :num_components]
    spectral_coeffs = chosen_eigenvecs.T @ img_reshaped
    upd_img_data_reshaped = chosen_eigenvecs @ spectral_coeffs
    return np.reshape(upd_img_data_reshaped, orig_shape).astype(int)

3.主函数

3.1 读入lenna图片、resize以及保存

from PIL import Image
img_name = 'E:/lenna.png'
img_width = 32
img_height = 32
img_data = np.asarray(Image.open(img_name).resize((img_width, img_height)))
save_dir = 'E:/spectral_representation'
if not os.path.exists(save_dir):
    os.makedirs(save_dir)

plt.axis('off')
_ = plt.imshow(img_data)
plt.show()
Image.fromarray(img_data).save(os.path.join(save_dir, '1ena.png'))

原图resize之后,显示如下:
在这里插入图片描述

3.2 计算该图像的拉普拉斯矩阵及谱特征

计算拉普拉斯矩阵,以及该矩阵的特征值、特征向量。

num_eigenvecs = 800
assert num_eigenvecs < img_width*img_height
v0 = np.ones(img_width * img_height)
laplacian = compute_sparse_laplacian(img_width, img_height)
eigenvals, eigenvecs = scipy.sparse.linalg.eigsh(
    laplacian, k=num_eigenvecs,  which='SM', v0=v0)
assert np.all(eigenvals >= 0)

plt.hist(eigenvals, bins=100)
plt.title('Histogram of Laplacian Eigenvalues')
plt.show()

在这里插入图片描述

3.3 图像重建及保存

base_name = os.path.basename(img_name).split('.')[0]

for num_components in [1, 10, 100, 200, 500, num_eigenvecs]:
    upd_img_data = keep_first_components(
        img_data, num_components).astype(np.uint8)
    upd_img_name = f'{base_name}-{num_components}.png'

    # plt.axis('off')
    # plt.imshow(upd_img_data)

    Image.fromarray(upd_img_data).save(
        os.path.join(save_dir, upd_img_name))
base_name = os.path.basename(img_name).split('.')[0]

for num_components in [1, 10, 100, 200, 500, img_width*img_height]:
    upd_img_data = keep_first_components(
        img_data, num_components).astype(np.uint8)
    upd_img_name = f'{base_name}-{num_components}.png'

    plt.axis('off')
    plt.imshow(upd_img_data)

    Image.fromarray(upd_img_data).save(
        os.path.join(save_dir, upd_img_name))

下图从左到右使用的特征向量个数分别为1, 10, 100, 200, 500, 800。可以看出随着特征向量增多,重建效果越来越好。
在这里插入图片描述

参考文献

[1] Understanding Convolutions on Graphs
[2] google colab:SpectralRepresentations.ipynb

相关文章:

  • 基于Vue+node的图书馆座位预约选座管理系统
  • 用DIV+CSS技术设计的凤阳旅游网站(web前端网页制作课作业)HTML+CSS+JavaScript
  • 【redis】从高并发场景下超卖问题到redis分布式锁
  • vscode安装及c++配置
  • 【Java Web项目】基于WebSocket的Web聊天室
  • Ansible自动化运维
  • 多线程【锁策略与CAS的ABA问题】
  • 清华系激光雷达公司,成了量产元年最大的黑马
  • 基于springboot的球员转会管理系统的设计与实现-计算机毕业设计源码+LW文档
  • 【Arduino与MFRC522握手】
  • 生成式对抗网络(GAN)【第六章】
  • 了解 Flutter 开发者们的 IDE 使用情况
  • linux下的权限
  • AI 杀疯了,NovelAI开源教程
  • 【深度学习】卷积神经网络之图像分类|CNN、AlexNet、VGG、GoogLeNet、ResNet
  • Asm.js的简单介绍
  • cookie和session
  • express + mock 让前后台并行开发
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • Laravel 实践之路: 数据库迁移与数据填充
  • mongo索引构建
  • MQ框架的比较
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • PAT A1050
  • 半理解系列--Promise的进化史
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 规范化安全开发 KOA 手脚架
  • 无服务器化是企业 IT 架构的未来吗?
  • 《码出高效》学习笔记与书中错误记录
  • hi-nginx-1.3.4编译安装
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • ​你们这样子,耽误我的工作进度怎么办?
  • ‌‌雅诗兰黛、‌‌兰蔻等美妆大品牌的营销策略是什么?
  • ‌JavaScript 数据类型转换
  • #define与typedef区别
  • #mysql 8.0 踩坑日记
  • #QT(串口助手-界面)
  • (11)iptables-仅开放指定ip访问指定端口
  • (3)选择元素——(17)练习(Exercises)
  • (9)STL算法之逆转旋转
  • (二刷)代码随想录第16天|104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (十)Flink Table API 和 SQL 基本概念
  • (五)关系数据库标准语言SQL
  • (一)SvelteKit教程:hello world
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转)setTimeout 和 setInterval 的区别
  • (转)视频码率,帧率和分辨率的联系与区别
  • .DFS.
  • .Net - 类的介绍
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .net打印*三角形
  • .NET连接MongoDB数据库实例教程
  • /etc/apt/sources.list 和 /etc/apt/sources.list.d