Как представить информацию о плотности на трехмерном графике рассеяния Matplotlib - PullRequest
0 голосов
/ 18 декабря 2018

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

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

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

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

3-D scatter plot without density information

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

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

1 Ответ

0 голосов
/ 18 декабря 2018

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

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

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

Давайте посмотрим код.Ничего особенного: он сглаживает и изменяет данные изображения так, как это нравится 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 необходимо, чтобы видеть немного сквозь облако.

Челси

Chelsea the cat color density

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

random uniform color density

Градиент

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

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

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

...