2017-01-11 2 views
1

У меня есть двумерная треугольная сетка с n вершинами, которая хранится в переменной tri (объект matplotlib.tri.Triangulation); Я могу построить сетку с функцией trcolcolor matplotlib достаточно легко, и все работает нормально. Тем не менее, у меня также есть (r, g, b) тройки для каждой вершины (vcolors), и эти значения не падают вдоль одного измерения, поэтому их нельзя легко преобразовать в карту цветов (например, представьте, если вы наложили треугольная сетка на большой фотографии парка, а затем назначила каждой вершине цвет пикселя под ним).tripcolor с использованием значений RGB для каждой вершины

Я думал, что я мог бы сделать что-то вроде этого:

matplotlib.pyplot.tripcolor(tri, vcolors) 

ValueError: Collections can only map rank 1 arrays

Есть ли удобный способ преобразовать vcolors -like (п х 3) матрицу в то полезное по tripcolor? Есть ли альтернатива tripcolor, которая принимает цвета вершин?

Одна вещь, которую я пытался это сделать мой собственный Colormap:

z = numpy.asarray(range(len(vcolors)), dtype=np.float)/(len(vcolors) - 1) 
cmap = matplotlib.colors.Colormap(vcolors, N=len(vcolors)) 
matplotlib.pyplot.tripcolor(tri, z, cmap=cmap) 
matplotlib.pyplot.show() 

Это, однако, не сделал ничего --- не цифра не появляется и не возникает никаких ошибок; функция возвращает дескриптор фигуры, но ничего не получается (я использую ноутбук IPython). Обратите внимание: если я вызываю следующее, график выглядит просто отлично:

tripcolor(tri, np.zeros(len(vcolors))) 
matplotlib.pyplot.show() 

Я использую Python 2.7.

+0

Я удалил мой ответ, как это явно не помогло. Чтобы предотвратить дальнейшие путаницы: если вы хотите замаскировать гуро, упомяните об этом в вопросе. Поскольку tripcolor не позволяет затушевывать Gouraud в сочетании с аргументом 'facecolors', у вас нет решения вашего вопроса, кроме использования цветовой карты. Если количество разных цветов ограничено, возможным решением может быть создание пользовательской цветовой палитры, например. если вы имеете только 255 различных значений цвета, вы можете создать colormap из этих 255 значений. – ImportanceOfBeingErnest

+0

Gouraud shading - это плюс, но я не требую этого. С затенением или без gouraud ваше утверждение, что аргумент 'facecolors' может решить эту проблему, кажется ложным: для него по-прежнему требуется 1-й z-вектор, который интерпретируется в соответствии с цветовой схемой. Это не помогает мне перейти от тройки RGB за вершину к чему-то полезному. В моем вопросе предлагается альтернатива 'tripcolor', которая может обрабатывать этот случай, поэтому я не согласен с тем, что решение невозможно. Он также явно указывает, что пользовательское решение colormap терпит неудачу, поэтому, если у вас есть обходной путь, я бы хотел его услышать (количество цветов - 'len (vcolors)'). – user16054

ответ

1

После укоренения вокруг в matplotlib «tripcolor и Colormap кода s, я придумал следующее решение, которое, кажется, работает только до тех пор, как один использует„Гуро“затенения (в противном случае, он делает очень плохую работу выводящих цвет лица, см. ниже).

Хитрость заключается в том, чтобы создать цветовую палитру, что, когда данное n равномерно разнесенного числа между 0 и 1 (включительно) воспроизводит исходный массив цветов:

def colors_to_cmap(colors): 
    ''' 
    colors_to_cmap(nx3_or_nx4_rgba_array) yields a matplotlib colormap object that, when 
    that will reproduce the colors in the given array when passed a list of n evenly 
    spaced numbers between 0 and 1 (inclusive), where n is the length of the argument. 

    Example: 
     cmap = colors_to_cmap(colors) 
     zs = np.asarray(range(len(colors)), dtype=np.float)/(len(colors)-1) 
     # cmap(zs) should reproduce colors; cmap[zs[i]] == colors[i] 
    ''' 
    colors = np.asarray(colors) 
    if colors.shape[1] == 3: 
     colors = np.hstack((colors, np.ones((len(colors),1)))) 
    steps = (0.5 + np.asarray(range(len(colors)-1), dtype=np.float))/(len(colors) - 1) 
    return matplotlib.colors.LinearSegmentedColormap(
     'auto_cmap', 
     {clrname: ([(0, col[0], col[0])] + 
        [(step, c0, c1) for (step,c0,c1) in zip(steps, col[:-1], col[1:])] + 
        [(1, col[-1], col[-1])]) 
     for (clridx,clrname) in enumerate(['red', 'green', 'blue', 'alpha']) 
     for col in [colors[:,clridx]]}, 
     N=len(colors)) 

Опять же, обратите внимание, что 'gouraud' затенения для этого требуется работать. Чтобы продемонстрировать, почему это не удается, следующие коды кода показывают мой конкретный пример использования. (Я рисую часть сплющенного листа коры с частично прозрачным наложением данных). В этом коде есть 40 886 вершин (в the_map.coordinates) и 81126 треугольников (в the_map.indexed_faces); массив colors имеет форму (40886, 3).

Следующий код прекрасно с «Гуро» затенение работы:

tri = matplotlib.tri.Triangulation(the_map.coordinates[0], 
            the_map.coordinates[1], 
            triangles=the_map.indexed_faces.T) 
cmap = rgbs_to_cmap(colors) 
zs = np.asarray(range(the_map.vertex_count), dtype=np.float)/(the_map.vertex_count - 1) 
plt.figure(figsize=(16,16)) 
plt.tripcolor(tri, zs, cmap=cmap, shading='gouraud') 

Plot using Gouraud shading

Но без «Гуро» затенение, гране- цвета возможно быть назначены в соответствии со средним их вершин (не проверить это), что явно неправильно:

plt.figure(figsize=(16,16)) 
plt.tripcolor(tri, zs, cmap=cmap) 

enter image description here

0

гораздо более простой способ создания карты цветов это через from_list:

z = numpy.arange(n) 
cmap = matplotlib.colors.LinearSegmentedColormap.from_list(
    'mymap', rgb, N=len(rgb) 
    ) 
Смежные вопросы