Как представить информацию о плотности на трехмерной диаграмме рассеяния matplotlib

Я пытаюсь построить каналы r, g, b на изображении в виде трехмерного графика рассеяния.

Это хорошо работает, когда у меня есть черно-белое изображение, поскольку я получаю точечную диаграмму только с двумя отдельными кластерами на двух концах точечной диаграммы.

Однако для цветных изображений диаграмма рассеивания визуально не имеет особого смысла, поскольку существуют значения r, g, b, соответствующие многим точкам в цветовом пространстве изображения.

Итак, я получаю что-то вроде изображения, показанного ниже -

Трехмерный точечный график без информации о плотности

Чего я хотел бы добиться, так это каким-то образом представить информацию о плотности. Например, если количество точек, соответствующих (255 255 255), равно 1000, а количество точек, соответствующих (0,0,0), составляет всего 500, тогда я хочу, чтобы (255 255 255) было темно-красным, а (0,0,0) — темно-красным. быть желтым/оранжевым

Как мне добиться этого в matplotlib? Я также согласен с некоторым эффектом пузыря, где (255,255,255) представлен как больший пузырь по сравнению с (0,0,0), хотя я чувствую, что информация о плотности, закодированная как информация о цвете, была бы более визуально привлекательной.


person Thalish Sajeed    schedule 18.12.2018    source источник


Ответы (1)


Вот попытка использования Gaussian KDE. Он еще далек от совершенства и результат во многом зависит от параметров оценки (bw_method). Возможно, есть более простой способ, например, использование np.unique для получения частоты каждого уникального цвета.

Идея состоит в том, чтобы оценить распределение плотности цвета как многомерную гауссову смесь и использовать ее в качестве карты цветов для диаграммы рассеяния.

Это немного медленно для чего-то серьезного, но я думаю, что это дает хорошие результаты с достаточно маленькими изображениями. Возможно, какой-то метод оценки на основе БПФ + свертка может быть быстрее.

Давайте посмотрим код. Ничего особенного: он сглаживает и изменяет форму данных изображения так, как это нравится gaussian_kde, и возвращает компоненты RGB и плотности. Вы можете поэкспериментировать с bw_method и посмотреть, как изменятся результаты: чем больше плотность, тем более гладкую плотность вы получите.

from scipy.stats import gaussian_kde

def img_to_rgbk(img, bw=0.1):
    rgb = img.reshape(-1, 3).T
    k = gaussian_kde(rgb, bw_method=bw)(rgb)
    r, g, b = rgb

    return r, g, b, k

Вот результаты с игрушечным изображением

img = chelsea()[100:200, 100:200]

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

r, g, b, k = img_to_rgbk(img, bw=0.5)
ax.scatter(r, g, b, c=k, alpha=0.2)

Обратите внимание, что c=k используется для установки цвета маркера карты в соответствии с информацией о плотности, alpha необходимо, чтобы немного видеть сквозь облако.

Челси

Плотность цвета кошки Челси

Случайные цвета

случайная равномерная плотность цвета

Градиент

Обратите внимание, здесь вы можете увидеть, как неправильный выбор полосы пропускания может ввести в заблуждение. Достаточно маленький bw_method должен отображать по существу один цвет в столбце, повторяющийся по строкам. Таким образом, каждая точка должна иметь один и тот же цвет (и это будет при правильной пропускной способности). спектральная плотность цветовой карты

Градиент + шум

Здесь с лучшей пропускной способностью и некоторым шумом для распространения цветов. Обратите внимание на большую плотность вокруг беловатой области, где разрыв на графике без шума становится максимумом плотности. спектральный + шум = веселье

person filippo    schedule 18.12.2018