Выкл одной ошибкой в ​​imshow? - PullRequest
5 голосов
/ 25 мая 2011

Я строю изображение PGM: enter image description here Вот данные , которые я использую.

Проблема в том, что некоторые из показанных пикселей неверны.Например:

  • три серых поля в верхней части изображения имеют значение 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

Ответы [ 2 ]

5 голосов
/ 25 мая 2011

Решение - установить 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

3 голосов
/ 25 мая 2011

Нет никаких расхождений, вы просто устанавливаете галочки вручную для значений, которые не являются тем, чем они являются на самом деле.

Обратите внимание, что ваш 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]?

Редактировать: Извините, это звучало странно, чем я хотел ... Я не хотел, чтобы это звучало так!:)

Edit2 : в ответ на обновленный вопрос, да, imshow определяет диапазон автоматически из минимального и максимального значений ввода.(Я в замешательстве ... Что еще это могло бы сделать?)

Если вы хотите прямое сопоставление цветов без интерполяции, тогда используйте одну из дискретных цветовых карт, а не LinearSegmentedColormap.Однако проще всего вручную установить пределы для одного из LinearSegmentedColormap с matplotlib (что и есть matplotlib.cm.spectral).

Если вы хотите вручную установить диапазон используемого цветового отображения, просто вызовите set_clim([0,12]) для объекта coloraxis, который возвращает imshow.

Например

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()

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...