Matplotlib による画像の透明度

Beginner

This tutorial is from open-source community. Access the source code

はじめに

この実験では、Matplotlib を使って 2 次元画像で透明度と色をブレンドする方法を紹介します。目的は、imshow を使ってデータの特定の部分を強調することです。

VM のヒント

VM の起動が完了したら、左上隅をクリックしてノートブックタブに切り替え、Jupyter Notebook を使って練習しましょう。

時々、Jupyter Notebook が読み込み終了するまで数秒待つ必要があります。Jupyter Notebook の制限により、操作の検証を自動化することはできません。

学習中に問題がある場合は、Labby にお問い合わせください。セッション後にフィードバックを提供してください。すぐに問題を解決いたします。

データの生成

まず、2 次元グリッド内に 2 つの 2 次元ブロブを生成します。一方のブロブは正の値、もう一方は負の値になります。

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import Normalize

def normal_pdf(x, mean, var):
    return np.exp(-(x - mean)**2 / (2*var))

## Generate the space in which the blobs will live
xmin, xmax, ymin, ymax = (0, 100, 0, 100)
n_bins = 100
xx = np.linspace(xmin, xmax, n_bins)
yy = np.linspace(ymin, ymax, n_bins)

## Generate the blobs. The range of the values is roughly -.0002 to.0002
means_high = [20, 50]
means_low = [50, 60]
var = [150, 200]

gauss_x_high = normal_pdf(xx, means_high[0], var[0])
gauss_y_high = normal_pdf(yy, means_high[1], var[0])

gauss_x_low = normal_pdf(xx, means_low[0], var[1])
gauss_y_low = normal_pdf(yy, means_low[1], var[1])

weights = (np.outer(gauss_y_high, gauss_x_high)
           - np.outer(gauss_y_low, gauss_x_low))

## We'll also create a grey background into which the pixels will fade
greys = np.full((*weights.shape, 3), 70, dtype=np.uint8)

データの生成

まず、2 次元グリッド内に 2 つの 2 次元ブロブを生成します。一方のブロブは正の値、もう一方は負の値になります。

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import Normalize

def normal_pdf(x, mean, var):
    return np.exp(-(x - mean)**2 / (2*var))

## ブロブが存在する空間を生成する
xmin, xmax, ymin, ymax = (0, 100, 0, 100)
n_bins = 100
xx = np.linspace(xmin, xmax, n_bins)
yy = np.linspace(ymin, ymax, n_bins)

## ブロブを生成する。値の範囲はおおよそ-.0002 から.0002 である
means_high = [20, 50]
means_low = [50, 60]
var = [150, 200]

gauss_x_high = normal_pdf(xx, means_high[0], var[0])
gauss_y_high = normal_pdf(yy, means_high[1], var[0])

gauss_x_low = normal_pdf(xx, means_low[0], var[1])
gauss_y_low = normal_pdf(yy, means_low[1], var[1])

weights = (np.outer(gauss_y_high, gauss_x_high)
           - np.outer(gauss_y_low, gauss_x_low))

## ピクセルが漸消するグレーの背景も作成する
greys = np.full((*weights.shape, 3), 70, dtype=np.uint8)

ブロブをプロットする

次に、透明度なしでimshowを使ってこれらのブロブをプロットします。

vmax = np.abs(weights).max()
imshow_kwargs = {
    'vmax': vmax,
    'vmin': -vmax,
    'cmap': 'RdYlBu',
    'extent': (xmin, xmax, ymin, ymax),
}

fig, ax = plt.subplots()
ax.imshow(greys)
ax.imshow(weights, **imshow_kwargs)
ax.set_axis_off()
plt.show()

ブロブをプロットする

次に、透明度なしでimshowを使ってこれらのブロブをプロットします。

vmax = np.abs(weights).最大値()
imshow_kwargs = {
    'vmax': vmax,
    'vmin': -vmax,
    'cmap': 'RdYlBu',
    'extent': (xmin, xmax, ymin, ymax),
}

fig, ax = plt.subplots()
ax.imshow(greys)
ax.imshow(weights, **imshow_kwargs)
ax.set_axis_off()
plt.show()

透明度をブレンドする

imshowを使ってデータをプロットする際に透明度を含める最も簡単な方法は、データの形状に合う配列をalpha引数に渡すことです。

## 右に向かって線形に増加する値のアルファチャンネルを作成する。
alphas = np.ones(weights.shape)
alphas[:, 30:] = np.linspace(1, 0, 70)

## 画像とグラフを作成する
fig, ax = plt.subplots()
ax.imshow(greys)
ax.imshow(weights, alpha=alphas, **imshow_kwargs)
ax.set_axis_off()
plt.show()

透明度をブレンドする

imshowを使ってデータをプロットする際に透明度を含める最も簡単な方法は、データの形状に合う配列をalpha引数に渡すことです。

## 右に向かって線形に増加する値のアルファチャンネルを作成する。
alphas = np.ones(weights.shape)
alphas[:, 30:] = np.linspace(1, 0, 70)

## 画像とグラフを作成する
fig, ax = plt.subplots()
ax.imshow(greys)
ax.imshow(weights, alpha=alphas, **imshow_kwargs)
ax.set_axis_off()
plt.show()

透明度を使って値を強調する

最後に、同じプロットを再作成しますが、今回は透明度を使ってデータの極端な値を強調します。これは、小さな p 値を持つデータポイントを強調するためによく使われます。また、画像の値を強調するために等高線も追加します。

## 重み値に基づいてアルファチャンネルを作成する
alphas = Normalize(0,.3, clip=True)(np.abs(weights))
alphas = np.clip(alphas,.4, 1)  ## アルファ値は下側で.4 でクリップされる

## 画像とグラフを作成する
fig, ax = plt.subplots()
ax.imshow(greys)
ax.imshow(weights, alpha=alphas, **imshow_kwargs)

## さまざまなレベルをさらに強調するために等高線を追加する
ax.contour(weights[::-1], levels=[-.1,.1], colors='k', linestyles='-')
ax.set_axis_off()
plt.show()

ax.contour(weights[::-1], levels=[-.0001,.0001], colors='k', linestyles='-')
ax.set_axis_off()
plt.show()

透明度を使って値を強調する

最後に、同じプロットを再作成しますが、今回は透明度を使ってデータの極端な値を強調します。これは、小さな p 値を持つデータポイントを強調するためによく使われます。また、画像の値を強調するために等高線も追加します。

## 重み値に基づいてアルファチャンネルを作成する
alphas = Normalize(0,.3, clip=True)(np.abs(weights))
alphas = np.clip(alphas,.4, 1)  ## アルファ値は下側で.4 でクリップされる

## 画像とグラフを作成する
fig, ax = plt.subplots()
ax.imshow(greys)
ax.imshow(weights, alpha=alphas, **imshow_kwargs)

## さまざまなレベルをさらに強調するために等高線を追加する
ax.contour(weights[::-1], levels=[-.1,.1], colors='k', linestyles='-')
ax.set_axis_off()
plt.show()

ax.contour(weights[::-1], levels=[-.0001,.0001], colors='k', linestyles='-')
ax.set_axis_off()
plt.show()

まとめ

この実験では、Matplotlib を使って 2 次元画像において透明度と色をブレンドする方法を学びました。また、imshowを使ってデータの特定の部分を強調する方法も学びました。