소개
Matplotlib 는 Python 에서 널리 사용되는 데이터 시각화 라이브러리입니다. 색각 이상 시뮬레이션 기능을 포함하여 다양한 내장 기능을 갖추고 있습니다. 이 랩에서는 Matplotlib 를 사용하여 색각 이상을 시뮬레이션하는 단계를 안내합니다.
VM 팁
VM 시작이 완료되면, 왼쪽 상단을 클릭하여 Notebook 탭으로 전환하여 실습을 위해 Jupyter Notebook에 접속하십시오.
때로는 Jupyter Notebook 이 로딩을 완료하는 데 몇 초 정도 기다려야 할 수 있습니다. Jupyter Notebook 의 제한으로 인해 작업의 유효성 검사는 자동화될 수 없습니다.
학습 중 문제가 발생하면 언제든지 Labby 에게 문의하십시오. 세션 후 피드백을 제공해주시면 문제를 신속하게 해결해 드리겠습니다.
필요한 라이브러리 및 모듈 가져오기
먼저 Matplotlib, NumPy, colorspacious 를 포함하여 필요한 라이브러리와 모듈을 가져와야 합니다. 또한 시뮬레이션하려는 색상 필터 옵션을 설정합니다.
import functools
from pathlib import Path
import colorspacious
import numpy as np
_BUTTON_NAME = "Filter"
_BUTTON_HELP = "Simulate color vision deficiencies"
_MENU_ENTRIES = {
"None": None,
"Greyscale": "greyscale",
"Deuteranopia": "deuteranomaly",
"Protanopia": "protanomaly",
"Tritanopia": "tritanomaly",
}
색상 필터 함수 정의
다음으로, 색상 필터 이름에 따라 색상 필터 함수를 생성하는 함수를 정의합니다. 이 함수는 colorspacious 모듈을 사용하여 입력 이미지를 색상 필터 이름에 따라 다른 색상 공간으로 변환합니다.
def _get_color_filter(name):
"""
Given a color filter name, create a color filter function.
Parameters
----------
name : str
The color filter name, one of the following:
- ``"none"``: ...
- ``"greyscale"``: Convert the input to luminosity.
- ``"deuteranopia"``: Simulate the most common form of red-green
colorblindness.
- ``"protanopia"``: Simulate a rarer form of red-green colorblindness.
- ``"tritanopia"``: Simulate the rare form of blue-yellow
colorblindness.
Color conversions use `colorspacious`_.
Returns
-------
callable
A color filter function that has the form:
def filter(input: np.ndarray[M, N, D])-> np.ndarray[M, N, D]
where (M, N) are the image dimensions, and D is the color depth (3 for
RGB, 4 for RGBA). Alpha is passed through unchanged and otherwise
ignored.
"""
if name not in _MENU_ENTRIES:
raise ValueError(f"Unsupported filter name: {name!r}")
name = _MENU_ENTRIES[name]
if name is None:
return None
elif name == "greyscale":
rgb_to_jch = colorspacious.cspace_converter("sRGB1", "JCh")
jch_to_rgb = colorspacious.cspace_converter("JCh", "sRGB1")
def convert(im):
greyscale_JCh = rgb_to_jch(im)
greyscale_JCh[..., 1] = 0
im = jch_to_rgb(greyscale_JCh)
return im
else:
cvd_space = {"name": "sRGB1+CVD", "cvd_type": name, "severity": 100}
convert = colorspacious.cspace_converter(cvd_space, "sRGB1")
def filter_func(im, dpi):
alpha = None
if im.shape[-1] == 4:
im, alpha = im[..., :3], im[..., 3]
im = convert(im)
if alpha is not None:
im = np.dstack((im, alpha))
return np.clip(im, 0, 1), 0, 0
return filter_func
메뉴 항목 설정
선택한 색상 필터 이름에 따라 메뉴 항목을 설정하는 함수를 정의합니다. 이 함수는 선택 사항에 따라 색상 필터 함수를 업데이트합니다.
def _set_menu_entry(tb, name):
tb.canvas.figure.set_agg_filter(_get_color_filter(name))
tb.canvas.draw_idle()
툴바 설정
다음으로, 사용된 백엔드 (backend) 유형에 따라 툴바를 설정하는 함수를 정의합니다. 이 함수는 사용자가 시뮬레이션할 색상 필터 유형을 선택할 수 있는 버튼을 생성합니다.
def setup(figure):
tb = figure.canvas.toolbar
if tb is None:
return
for cls in type(tb).__mro__:
pkg = cls.__module__.split(".")[0]
if pkg != "matplotlib":
break
if pkg == "gi":
_setup_gtk(tb)
elif pkg in ("PyQt5", "PySide2", "PyQt6", "PySide6"):
_setup_qt(tb)
elif pkg == "tkinter":
_setup_tk(tb)
elif pkg == "wx":
_setup_wx(tb)
else:
raise NotImplementedError("The current backend is not supported")
샘플 이미지 생성
색상 필터 함수를 시연하기 위해 샘플 이미지를 생성합니다. Grace Hopper 의 샘플 이미지를 가져와 Matplotlib 을 사용하여 플롯합니다. 또한 사인파의 플롯도 생성합니다.
if __name__ == '__main__':
import matplotlib.pyplot as plt
from matplotlib import cbook
plt.rcParams['figure.hooks'].append('mplcvd:setup')
fig, axd = plt.subplot_mosaic(
[
['viridis', 'turbo'],
['photo', 'lines']
]
)
delta = 0.025
x = y = np.arange(-3.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2
imv = axd['viridis'].imshow(
Z, interpolation='bilinear',
origin='lower', extent=[-3, 3, -3, 3],
vmax=abs(Z).max(), vmin=-abs(Z).max()
)
fig.colorbar(imv)
imt = axd['turbo'].imshow(
Z, interpolation='bilinear', cmap='turbo',
origin='lower', extent=[-3, 3, -3, 3],
vmax=abs(Z).max(), vmin=-abs(Z).max()
)
fig.colorbar(imt)
## A sample image
with cbook.get_sample_data('grace_hopper.jpg') as image_file:
photo = plt.imread(image_file)
axd['photo'].imshow(photo)
th = np.linspace(0, 2*np.pi, 1024)
for j in [1, 2, 4, 6]:
axd['lines'].plot(th, np.sin(th * j), label=f'$\\omega={j}$')
axd['lines'].legend(ncols=2, loc='upper right')
plt.show()
요약
이 Lab 에서는 Matplotlib 을 사용하여 색각 이상을 시뮬레이션하는 방법을 배웠습니다. colorspacious 모듈을 사용하여 선택한 색상 필터 이름에 따라 입력 이미지를 다른 색상 공간으로 변환했습니다. 또한 색상 필터 기능을 시연하기 위해 샘플 이미지를 생성했습니다.