如何解决因显示错误而关闭?
| 我正在绘制一个PGM图像: 这是我正在使用的数据。 问题是所显示的某些像素错误。例如: 图像顶部附近的三个灰色框的值为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()
编辑
我现在看到这里发生了什么。基本上,ѭ1似乎正在这样做:
确定动态范围(如[ min(image),max(image) ]
使用颜色表中指定的颜色数量(13种颜色)来表示
我想要它做的是:
使用我在创建颜色图时指定的动态范围(13)
使用颜色图中的13种颜色表示
我可以通过将图像的动态范围设置为13来验证这一点(请参阅标有“ѭ3”的行)。有一个更好的方法吗?
这是更新的图像:
解决方法
解决的办法是设置
im.set_clim(vmin,vmax)
。基本上,图像中的值被转换为覆盖整个颜色范围。例如,如果3
是数据中的最大值,则将为其分配最大的颜色值。
相反,您需要告诉它max_nodes
是最大值(在您的情况下为13),即使它没有出现在数据中,例如im.set_clim(0,13)
。
我对代码进行了少许更改,以便与其他具有values8ѭ值的数据文件一起使用:
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\')
一些更简单的测试数据来说明。请注意,“ 8”值是10,但是没有数据点达到该级别。这显示了值如何以1:1索引到颜色表中:
P2
5 3
10
0 1 0 2 0
3 0 2 0 1
0 1 0 2 0
输出:
,没有差异,您只是手动设置刻度线,使其标记的值与实际值不符。
请注意,您的LABELS
只是range(13)
,而您的实际勾号位置(ticks
)的范围从0到12。
因此,您正在手动将位置为10.6的顶部刻度线标记为12!
尝试取出cb.ax.set_yticklabels(map(str,LABELS))
行,您会明白我的意思(此外,matplotlib会自动将它们转换为字符串。没有理由调用map(str,LABELS)
)。
也许应该将实际的刻度位置转换为标签,而不是使用一组静态数字作为标签?像[round(tick) for tick in ticks]
?
编辑:对不起,这听起来比我原先想的要怪。。。我不是那个意思! :)
编辑2:
对于更新的问题,是的,imshow
根据输入的最小值和最大值自动确定范围。 (我很困惑……还能做什么?)
如果要使用没有插值的直接颜色映射,请使用一种离散的颜色图,而不是LinearSegmentedColormap
。但是,最简单的方法是手动设置matplotlib的ѭ19的限制(也就是ѭ21)。
如果要手动设置使用的颜色映射的范围,只需在imshow
返回的色轴对象上调用set_clim([0,12])
。
例如。
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
with open(\'temp.pgm\') as infile:
header,nrows,ncols = [infile.readline().strip() for _ in range(3)]
data = np.loadtxt(infile).astype(np.uint8)
cmap = mpl.cm.get_cmap(\'spectral\',13)
cax = plt.imshow(data,cmap,interpolation=\'nearest\')
cax.set_clim([0,13])
cbar = plt.colorbar(cax,ticks=np.arange(0.5,13,1.0))
cbar.ax.set_yticklabels(range(13))
plt.show()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。