如何使用imshow使用Matplotlib绘制具有非线性y轴的图像?

2024-05-09 22:02:43 发布

您现在位置:Python中文网/ 问答频道 /正文

如何将二维数组绘制为图像,Matplotlib的y刻度与y值的二次方成正比?

例如,我的数组的第一行在图像中的高度为1,第二行的高度为4,等等(单位无关) 用文字来解释并不简单,所以请看这张图片(这是我想要的结果):

alt text http://support.sas.com/rnd/app/da/new/802ce/iml/chap1/images/wavex1k.gif

如您所见,第一行比上一行小2倍,以此类推。

对于那些对我为什么要这么做感兴趣的人:

我有一个相当大的浮点数组(1070000),表示声音文件的离散小波变换系数。我试着用这些系数来绘制比例图。 我可以复制数组x次,直到得到所需的图像行大小,但内存无法保存这么多信息。。。


Tags: text图像httpsupport高度matplotlib绘制图片
3条回答

我发现使用matplotlib制作scalegram的最佳方法是使用imshow,类似于specgram的实现。使用矩形很慢,因为必须为每个值创建单独的标志符号。类似地,你不想把东西烘焙成一个统一的NumPy数组,因为你可能会很快耗尽内存,因为你的最高级别大约是你信号的一半。

下面是使用SciPy和PyWavelets的示例:

from pylab import *
import pywt
import scipy.io.wavfile as wavfile

# Find the highest power of two less than or equal to the input.
def lepow2(x):
    return 2 ** floor(log2(x))

# Make a scalogram given an MRA tree.
def scalogram(data):
    bottom = 0

    vmin = min(map(lambda x: min(abs(x)), data))
    vmax = max(map(lambda x: max(abs(x)), data))

    gca().set_autoscale_on(False)

    for row in range(0, len(data)):
        scale = 2.0 ** (row - len(data))

        imshow(
            array([abs(data[row])]),
            interpolation = 'nearest',
            vmin = vmin,
            vmax = vmax,
            extent = [0, 1, bottom, bottom + scale])

        bottom += scale

# Load the signal, take the first channel, limit length to a power of 2 for simplicity.
rate, signal = wavfile.read('kitten.wav')
signal = signal[0:lepow2(len(signal)),0]
tree = pywt.wavedec(signal, 'db5')

# Plotting.
gray()
scalogram(tree)
show()

您可能还希望根据级别自适应地缩放值。

这对我很有效。我唯一的问题是matplotlib在层之间创建了一个细细的空间。我还在想办法解决这个问题。

p.S.-尽管这个问题现在已经很老了,但我想我会在这里回答,因为这个页面是在谷歌上出现的,当时我正在寻找一种使用MPL创建scalegrams的方法。

你试过变换轴吗?例如:

ax = subplot(111)
ax.yaxis.set_ticks([0, 2, 4, 8])
imshow(data)

这意味着对于不存在的坐标,数据中必须存在间隙,除非有一种方法可以提供转换函数,而不仅仅是列表(从未尝试过)。

编辑

我承认这只是一个线索,不是一个完整的解决方案。这是我想说的更多细节。

假设您的数据在数组中,a。可以使用这样的变换:

class arr(object):
    @staticmethod
    def mylog2(x):
        lx = 0
        while x > 1:
            x >>= 1
            lx += 1
        return lx
    def __init__(self, array):
        self.array = array
    def __getitem__(self, index):
        return self.array[arr.mylog2(index+1)]
    def __len__(self):
        return 1 << len(self.array)

基本上,它将使用mylog2函数转换数组或列表的第一个坐标(您可以随心所欲地转换它-它是作为log2的简化而自制的)。优点是,如果需要,可以将其重新用于另一个转换,而且还可以轻松地控制它。

然后将数组映射到此数组,此数组不会生成副本,而是在实例中生成本地引用:

b = arr(a)

现在可以显示它,例如:

ax = subplot(111)
ax.yaxis.set_ticks([16, 8, 4, 2, 1, 0])
axis([-0.5, 4.5, 31.5, 0.5])
imshow(b, interpolation="nearest")

下面是一个示例(包含随机值的数组):

alt text http://img691.imageshack.us/img691/8883/clipboard01f.png

你可以看看matplotlib.image.NonUniformImage。但这只会有助于轴的非均匀性-我不认为你能像你想的那样自适应地绘制(我认为图像中的每个点总是有相同的区域-所以你必须多次有更宽的行)。有什么理由需要绘制完整的数组吗?很明显,所有的细节都不会出现在任何一个图中,所以我建议你对原始矩阵进行大幅度的降采样,这样你就可以根据需要复制行以获得图像,而不会耗尽内存。

相关问题 更多 >