защо моята цветна лента има линии в нея?

Редактиране: Тъй като това изглежда е популярна публикация, ето решението, което изглежда работи добре за мен. Благодаря @gazzar и @mfra.

cbar.solids.set_rasterized(True)
cbar.solids.set_edgecolor("face")

Някой знае ли защо в цветната ми лента има нещо, което изглежда като линии? Или по-скоро защо преходът на цветовете не е плавен? Използвам базова карта, очевидно, но това не би трябвало да има значение, тъй като всичко е извикване на matplotlib под капака AFAICT. Създавам картата, правейки нещо подобно

grays = plt.cm.get_cmap("Grays")
sc = mymap.scatter(xpoints, ypoints, s=sizes, c=color_values, cmap=grays, alpha=.75,
                   marker="o", zorder=10, vmin=0, vmax=1)
cbar = mymap.colorbar(sc, drawedges=True, location="bottom")

Пробвах без и без алфа и резултатът беше същият. Може би защото моят масив color_values ​​не е достатъчно фин? Мога ли да задам основните стойности, които са картографирани някъде в цветната лента? Не виждам как и не виждам този проблем другаде. Т.е. мога да копирам примера на matplotlib show_colorbars без този проблем.

Пример за лоша цветна лента


person jseabold    schedule 21.02.2013    source източник
comment
Опитвали ли сте да запазите фигурата в различни формати? Ако да, винаги ли получавате тези проблеми?   -  person Francesco Montesano    schedule 21.02.2013
comment
Виждал съм това само като резултат от алфата, наистина ли сте сигурни, че е същото с алфа=1.0?   -  person Rutger Kassies    schedule 21.02.2013
comment
Да, случва се с png, но не съм отстранил това. Да, видях го за алфа = 1.0 със SVG.   -  person jseabold    schedule 22.02.2013
comment
Хм... никоя от изброените по-долу опции изглежда не решава проблема за мен. Моята цветна лента все още има бели линии, когато запазя fig като PDF.   -  person nukeguy    schedule 19.08.2015
comment
Двата реда, дадени като решение в последната редакция, не трябва да се използват заедно. Едното или другото е достатъчно.   -  person divenex    schedule 05.10.2015
comment
Ето предложено решение с изчислени имитирани алфа стойности: stackoverflow.com/a/64201085/2084944   -  person Tik0    schedule 05.10.2020


Отговори (7)


В случай, че създавате векторни графики, опитвали ли сте това (взето от http://matplotlib.org/api/pyplot_api.html?highlight=colorbar#matplotlib.pyplot.colorbar):

„Известно е, че някои програми за преглед на векторни графики (svg и pdf) изобразяват бели празнини между сегментите на цветната лента. Това се дължи на грешки в програмите за преглед, а не на matplotlib. Като заобиколно решение цветната лента може да бъде изобразена с припокриващи се сегменти:

cbar = colorbar()
cbar.solids.set_edgecolor("face")
draw()

Това обаче има отрицателни последици при други обстоятелства. Особено с полупрозрачни изображения (алфа ‹ 1) и разширения на цветни ленти и не е активирано по подразбиране, вижте (проблем #1188)."

person mfra    schedule 22.02.2013
comment
Благодаря. Това наистина изглежда е проблемът, четейки #1188 и прикачения (върнат) PR. Интересното е също, че SVG се изобразяват по различен начин във Firefox и Chrome, за което не се бях сещал. - person jseabold; 22.02.2013
comment
Изглежда, че най-добрите резултати за алфа ‹ 1 идват от използването на drawedges=False и set_edgecolor(face). Сега имам черни линии, но са по-слабо изразени и само в по-тъмните цветове. - person jseabold; 22.02.2013
comment
Това наистина е грешка във визуализатора(ите), но също така е вярно, че се използва неоптимален начин за изобразяване на цветната лента. Цялата фигура трябва да бъде начертана като едно цяло, като се използва гладко засенчване, а не 256 малки правоъгълника. Както PDF, така и SVG форматите поддържат линейно гладко засенчване с произволен брой цветове. - person Mojca; 05.03.2014

Изглежда, че вашият график използва някои прозрачни (алфа) стойности. Имах същия проблем (полупрозрачна графика, но исках цветната лента да е плътна) и това въпрос и отговор го поправиха за мен! За справка:

cbar.set_alpha(1)
cbar.draw_all()
person Wesley Baugh    schedule 26.03.2013
comment
Това промени цветната ми карта в цветната лента! Защо?? Какво по дяволите :D - person Rylan Schaeffer; 23.05.2020

Пробвах и двете настройки дадени в другите коментари, а именно

cbar.solids.set_rasterized(True)
cbar.solids.set_edgecolor("face")

и за съжаление нито един от тях не ми подейства.

Така че опитах напълно различен подход, който е огромен хак, но поне свършва работата. Когато подадете alpha към imshow, това задава алфа стойност, която ще се използва за смесване с други изображения. Поради причини за по-висока мощност (както @mfra спомена) това създава белите линии, които толкова презираме. Очевидно ключът тогава е да не се предава алфа стойност на imshow. Въпреки това все още трябва по някакъв начин да създадем цветната лента.

По този начин като заобиколно решение можем сами да направим алфа смесването, преди да дадем цветни карти на imshow. Като пример, нека използваме цветовата карта winter:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

xx, yy = np.meshgrid(np.linspace(-1, 1, 100), np.linspace(-1, 1, 100))
zz = xx**2 + yy**2

my_cmap_rgb = plt.get_cmap('winter')(np.arange(256))
alpha = 0.5

for i in range(3): # Do not include the last column!
    my_cmap_rgb[:,i] = (1 - alpha) + alpha*my_cmap_rgb[:,i]
my_cmap = mpl.colors.ListedColormap(my_cmap_rgb, name='my_cmap')

Тук създавам нова цветова карта, my_cmap_rgb, базирана на winter и след това редактирам не-алфа каналите (0, 1 и 2), за да направя алфа смесването сам. След това мога просто да използвам тази нова цветова карта, за да начертая фигурата си.

f, ax = plt.subplots()
cim = ax.imshow(zz, cmap=my_cmap)
cbar = plt.colorbar(cim)
ax.set_title("No lines and no transparency")

Без редове и  без прозрачност Сега го сравнете с изображението, което бихте получили без този трик:

f, ax = plt.subplots()
cim = ax.imshow(zz, cmap='winter', alpha=0.5)
cbar = plt.colorbar(cim)
ax.set_title("Lines and transparency")

„Линии

Очевидно проблемът е решен, ако не се нуждаете от прозрачност. От друга страна, ако се нуждаете от прозрачност, има още едно решение. Първо трябва да начертаете изображение без прозрачност, за да получите цветната лента, и след това да начертаете изображение с прозрачност, но чиято цветна лента няма да бъде използвана.

f, ax = plt.subplots()
cim = ax.imshow(zz, cmap=my_cmap)
cbar = plt.colorbar(cim)
plt.cla()  # Clears axis
ax.plot(50,50, 'ko')
ax.imshow(zz, cmap='winter', alpha=0.5)
ax.set_title("No lines and transparency")

Това води до изображение, чиято цветна лента няма линии и въпреки това запазва прозрачността. Въпреки че остава огромен хак, поне вече не трябва да търпим тези редове!

„Без

person cako    schedule 27.02.2016
comment
Приложих последния трик (графика без алфа, графика с цветна лента, графика с алфа), тъй като трябваше да минавам изображения през imshow, като втората беше прозрачно насложена върху първата, а втората имаше цветната лента. По този начин се сблъсква с проблема с прозрачните ивици. - person ; 20.04.2016

Обикновено предпочитам да растеризирам съдържанието на цветната лента, за да избегна този проблем, използвайки съвета на Ерик Фиринг тук като добавите следния ред.

cbar.solids.set_rasterized(True) 

Това заобиколно решение се предполага, че е неуспешно за изображения с прозрачност, но в повечето нормални случаи дава желания резултат.

person gazzar    schedule 15.08.2014
comment
Връщам се към това две години по-късно. Това наистина помага доста. - person jseabold; 26.04.2015
comment
Отлично. Изглежда по-добре и също по-малък svg изход! - person Bram; 24.12.2015

Опитвам:

cbar = mymap.colorbar(sc, drawedges=False, location="bottom")

Вече е добре документиран в мрежата (което успях да намеря), но

*drawedges*   [ False | True ] If true, draw lines at color
              boundaries.

(изтеглено от matplotlib/lib/matplotlib/colorbar.py) Мисля, че като зададете drawedges на True му казвате да начертае тези линии.

person tacaswell    schedule 21.02.2013
comment
drawedges наистина рисува ръбовете за мен, но ги рисува в черно! Не е особено полезно. Решението на mfra работи без чертежи за мен. (matplotlib v1.3.1) - person travc; 24.10.2014

Тъй като нито едно от другите предложения не работи за мен, в крайна сметка премахнах алфа канала от екземпляра на цветната лента:

from matplotlib.colors import to_rgb

lut = colorbar.solids.get_facecolor()
bg_color = to_rgb('white')
lut[:, :3] *= lut[:, 3:]
lut[:, :3] += (1 - lut[:, 3:]) * bg_color
lut[:, 3] = 1.
colorbar.solids.set_facecolor(lut)

Цветната лента трябваше да бъде начертана веднъж, преди да можете да получите достъп до цветовете на лицето.

person christianbrodbeck    schedule 29.01.2018

Следното може да бъде друго решение, дори и да не е елегантно.

In [1]: children = cbar.ax.get_children()
In [2]: children
Out[2]:
[<matplotlib.collections.QuadMesh at 0x21783c41b70>,
 <matplotlib.collections.LineCollection at 0x21783bfdc18>,
 <matplotlib.patches.Polygon at 0x21783ba0588>,
 <matplotlib.patches.Polygon at 0x21783beef98>,
 <matplotlib.spines.Spine at 0x21783b77c88>,
 <matplotlib.spines.Spine at 0x21783b77470>,
 <matplotlib.spines.Spine at 0x21783b70c88>,
 <matplotlib.spines.Spine at 0x21783b70860>,
 <matplotlib.axis.XAxis at 0x21783b6ac50>,
 <matplotlib.axis.YAxis at 0x21783ba60f0>,
 <matplotlib.text.Text at 0x21783bc2198>,
 <matplotlib.text.Text at 0x21783bc2320>,
 <matplotlib.text.Text at 0x21783bc22b0>,
 <matplotlib.patches.Rectangle at 0x21783bc2358>]
In [3]: obj = children[1]  # Get the LineCollection object
In [4]: obj.set_linewidth(0)
person Daewon Lee    schedule 11.11.2017