python - 因 imshow 中的一个错误而关闭?

标签 python matplotlib

我正在绘制 PGM 图像: enter image description here 这是 data我正在使用。

问题是一些显示的像素是错误的。例如:

  • 图像顶部附近的三个灰色框的值为 11(因此它们应该是红色,而不是红色)
  • 顶行的两个黄色像素 -- 它们的值为 8,所以它们应该是黄绿色,而不是黄色

谁能解释这些差异以及如何解决这些差异?

这是我的来源:

from pylab import *
import numpy    
LABELS = range(13)
NUM_MODES = len(LABELS)
def read_ascii_pgm(fname):
    """
    Very fragile PGM reader.  It's OK since this is only for reading files
    output by my own app.
    """
    lines = open(fname).read().strip().split('\n')
    assert lines[0] == 'P2'
    width, height = map(int, lines[1].split(' '))
    assert lines[2] == '13'
    pgm = numpy.zeros((height, width), dtype=numpy.uint8)
    for i in range(height):
        cols = lines[3+i].split(' ')
        for j in range(width):
            pgm[i,j] = int(cols[j])
    return pgm
def main():
    import sys
    assert len(sys.argv) > 1
    fname = sys.argv[1]
    pgm = read_ascii_pgm(fname)
    # EDIT: HACK!
    pgm[0,0] = 12
    cmap = cm.get_cmap('spectral', NUM_MODES)
    imshow(pgm, cmap=cmap, interpolation='nearest')
    edit = True
    if edit:
        cb = colorbar()
    else:
        ticks = [ (i*11./NUM_MODES + 6./NUM_MODES) for i in range(NUM_MODES) ]
        cb = colorbar(ticks=ticks)
        cb.ax.set_yticklabels(map(str, LABELS))
    savefig('imshow.png')
if __name__ == '__main__':
    main()

编辑

我现在明白这里发生了什么。基本上,imshow 似乎是这样做的:

  • 确定动态范围(如 [ min(image), max(image) ]
  • 使用颜色图中指定的颜色数(13 种颜色)来表示

我想要它做的是:

  • 使用我在创建颜色图 (13) 时指定的动态范围
  • 用色图中的 13 种颜色表示

我可以通过将图像的动态范围强制设置为 13 来验证这一点(请参阅标记为 HACK 的行)。有更好的方法吗?

这是一张更新后的图片: enter image description here

最佳答案

解决方法是设置im.set_clim(vmin, vmax)。基本上图像中的值被转换以覆盖整个颜色范围。例如,如果 3 是数据中的最大值,它将被分配最大颜色值。

相反,您需要告诉它 max_nodes 是最高值(在您的情况下为 13),即使它没有出现在数据中,例如im.set_clim(0, 13)

我稍微更改了您的代码以使用具有不同 num_modes 值的其他数据文件:

import numpy
from pylab import *

def read_ascii_pgm(fname):
    lines = open(fname).read().strip().split('\n')
    assert lines[0] == 'P2'
    width, height = map(int, lines[1].split(' '))
    num_modes = int(lines[2])
    pgm = numpy.zeros((height, width), dtype=numpy.uint8)
    for i in range(height):
        cols = lines[3+i].split(' ')
        for j in range(width):
            pgm[i,j] = int(cols[j])
    return pgm, num_modes + 1

if __name__ == '__main__':
    import sys
    assert len(sys.argv) > 1
    fname = sys.argv[1]
    pgm, num_modes = read_ascii_pgm(fname)
    labels = range(num_modes)
    cmap = cm.get_cmap('spectral', num_modes)
    im = imshow(pgm, cmap=cmap, interpolation='nearest')
    im.set_clim(0, num_modes)
    ticks = [(i + 0.5) for i in range(num_modes)]
    cb = colorbar(ticks=ticks)
    cb.ax.set_yticklabels(map(str, labels))
    savefig('imshow_new.png')

一些更简单的测试数据来说明。请注意,num_modes 值为 10,但没有数据点达到该级别。这显示了值如何以 1:1 的比例索引到颜色图中:

P2
5 3
10
0 1 0 2 0
3 0 2 0 1
0 1 0 2 0

输出:

enter image description here

关于python - 因 imshow 中的一个错误而关闭?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6127282/

相关文章:

python - 用numpy数组中的最近邻居填充nan

java - 等效于 Java 中的 Python 的 lambda 函数?

python - 将径向数据转换为笛卡尔网格以绘制曲面图

python - 使用 matplotlib 绘制分段函数会导致 ValueError : The truth value of an array with more than one element is ambiguous

python - 解压对自己的文件不起作用

python - 使用 python 检测新的或修改的文件

python - for 循环如何在元组中工作

python - 在同一个图表上绘制不同比例的多条线

python - matplotlib/Pandas 中的水平箱线图

python - 更改使用 seaborn.factorplot 创建的条形图中条形的宽度