opencv 画

# CIELUV色相環をPythonで描画する
>

- toc: true
- badges: true
- comments: true
- author: 山拓
- categories:

2020-01-13-cieluv.ipynb_

文件

修改

视图

插入

代码执行程序

工具

帮助

分享

登录

代码文本复制到云端硬盘连接修改


CIELUV色相環をPythonで描画する

 
  • toc: true
  • badges: true
  • comments: true
  • author: 山拓
  • categories: [python]

CIE Luv色空間 (CIE 1976 Luv color space)の色相環(hue wheel)をOpenCVとMatplotlibで描画する。

ぶっちゃけると色覚に関する研究もしていて、JNNS2019でポスター発表はしたが頓挫したりあっちこっちに行ったりしている。今回はその付随したメモである。色空間について、自分は今までHSV色空間を使うなどかなり適当だったが、先行研究がほとんどCIELUV色空間を使っていたので調べることとした。単なるHSVでは色の数値的差が知覚的差と一致しないが、CIELuvでは両者ができるだけ近くなるようにしている。

描画にはcolourまたはOpenCVを使う。Pythonのpackageであるcolourはpipで入る:pip install colour-science

なお、変換をscratchでする場合にはhttp://www.easyrgb.com/en/math.phpが参考になる。

OpenCVを使う場合

CIE Luv色空間において値域はL [0, 100], u[-100, 100], v[-100, 100]である。Hue angle の配列を作り、cos, sinに入れて100をかけ、それぞれをu, vとする。そしてLを適当に定めることでLuvの配列ができる。

後の面倒な変換はcv2.cvtColor(hogehoge, cv2.COLOR_Luv2RGB)に任せる(cf. 変換できる色空間の一覧)。単なる変換ではRGBのどれかの値が負の値を取るが、それを0にclippingしている。逆にcvtColorを使うと正規化されずにclippingされるので、L=100のときはほぼ白色となる。

変換式は下記参照(Miscellaneous Image Transformations — OpenCV 2.4.13.7 documentationより引用)。


image


色相バー


[ ]

#hide_input

import warnings

warnings.filterwarnings('ignore')

 

 

 


[ ]

import matplotlib.pyplot as plt

import numpy as np

import cv2

 

N_theta = 1000

luv = np.zeros((1, N_theta, 3)).astype(np.float32)

theta = np.linspace(0, 2*np.pi, N_theta)

luv[:, :, 0] = 80 # L

luv[:, :, 1] = np.cos(theta)*100 # u

luv[:, :, 2] = np.sin(theta)*100 # v

 

rgb = cv2.cvtColor(luv, cv2.COLOR_Luv2RGB)

plt.imshow(rgb, vmin=0, vmax=1, aspect=100)

plt.show()

 

 

 

 


色相環


[ ]

N_theta = 1000

luv = np.zeros((1, N_theta, 3)).astype(np.float32)

theta = np.linspace(0, 2*np.pi, N_theta)

luv[:, :, 0] = 80 # L

luv[:, :, 1] = np.cos(theta)*100 # u

luv[:, :, 2] = np.sin(theta)*100 # v

 

rgb = cv2.cvtColor(luv, cv2.COLOR_Luv2RGB)

# hue wheel plot

ax = plt.subplot(111, polar=True)

#get coordinates:

theta = np.linspace(0, 2*np.pi, rgb.shape[1]+1)

r = np.linspace(0.5, 1, rgb.shape[0]+1)

Theta,R = np.meshgrid(theta, r)

 

# get color

color = rgb.reshape((rgb.shape[0]*rgb.shape[1], rgb.shape[2]))

m = plt.pcolormesh(theta,R, rgb[:,:,0], color=color, linewidth=0)

# This is necessary to let the `color` argument determine the color

m.set_array(None)

plt.show()

 

 

 

 


uv平面

uv平面をplotすると次のようになる。


[ ]

W = 1000

H = 1000

luv = np.zeros((W, H, 3)).astype(np.float32)

u = np.linspace(-100, 100, W) # u

v = np.linspace(-100, 100, H) # v

U, V = np.meshgrid(u, v)

luv[:, :, 0] = 80

luv[:, :, 1] = U

luv[:, :, 2] = V

 

RGB = cv2.cvtColor(luv, cv2.COLOR_Luv2RGB)

plt.figure(figsize=(5,5))

plt.imshow(RGB, vmin=0, vmax=1)

plt.show()

 

 

 

 


Colourを使う場合

colourは色の変換関数が充実している。そこでu', v'平面上の円周上の色を、xyに変換、さらにXYZに変換し(このときY=1とする)、最後にRGBに変換したものをplotする。

色相バー

HSVと比べると青がかなり短いことが分かる。


[ ]

import colour

 

N_theta = 500

theta = np.linspace(0, 2*np.pi, N_theta)

r = 0.2

u = np.cos(theta)*r + 0.2009

v = np.sin(theta)*r + 0.4610

uv = np.dstack((u, v))

 

# map -> xy -> XYZ -> sRGB

xy = colour.Luv_uv_to_xy(uv)

xyz = colour.xy_to_XYZ(xy)

rgb = colour.XYZ_to_sRGB(xyz)

rgb = colour.utilities.normalise_maximum(rgb, axis=-1)

 

plt.figure(figsize=(5,3))

plt.imshow(np.reshape(rgb, (1, N_theta, 3)), aspect=100)

plt.show()

 

 

 

 


[ ]

N_theta = 500

theta = np.linspace(0, 2*np.pi, N_theta)

r = 0.2

u = np.cos(theta)*r + 0.2009

v = np.sin(theta)*r + 0.4610

uv = np.dstack((u, v))

 

# map -> xy -> XYZ -> sRGB

xy = colour.Luv_uv_to_xy(uv)

xyz = colour.xy_to_XYZ(xy)

rgb = colour.XYZ_to_sRGB(xyz)

rgb = colour.utilities.normalise_maximum(rgb, axis=-1)

 

# hue wheel plot

ax = plt.subplot(111, polar=True)

#get coordinates:

theta = np.linspace(0, 2*np.pi, rgb.shape[1]+1)

r = np.linspace(0.5, 1, rgb.shape[0]+1)

Theta,R = np.meshgrid(theta, r)

 

# get color

color = rgb.reshape((rgb.shape[0]*rgb.shape[1], rgb.shape[2]))

m = plt.pcolormesh(theta,R, rgb[:,:,0], color=color, linewidth=0)

# This is necessary to let the `color` argument determine the color

m.set_array(None)

plt.show()

 

 

 

 


CIE 1976 UCS (uniform chromaticity scale) diagram

描画方法を2つ示す。

Method 1

黒線は光のスペクトルに対応する点を意味する。


[ ]

import matplotlib.pyplot as plt

import numpy as np

import colour

 

samples = 258

xlim = (0, 1)

ylim = (0, 1)

 

wvl = np.arange(420, 700, 5)

wvl_XYZ = colour.wavelength_to_XYZ(wvl)

wvl_uv = colour.Luv_to_uv(colour.XYZ_to_Luv(wvl_XYZ))

wvl_pts = wvl_uv * samples

 

u = np.linspace(xlim[0], xlim[1], samples)

v = np.linspace(ylim[0], ylim[1], samples)

uu, vv = np.meshgrid(u, v)

 

# stack u and v for vectorized computations

uuvv = np.stack((vv,uu), axis=2)

 

# map -> xy -> XYZ -> sRGB

xy = colour.Luv_uv_to_xy(uuvv)

xyz = colour.xy_to_XYZ(xy)

dat = colour.XYZ_to_sRGB(xyz)

dat = colour.normalise_maximum(dat, axis=-1)

 

# now make an alpha/transparency mask to hide the background

# and flip u,v axes because of column-major symantics

alpha = np.ones((samples, samples)) # * wvl_mask

dat = np.swapaxes(np.dstack((dat, alpha)), 0, 1)

 

# lastly, duplicate the lowest wavelength so that the boundary line is closed

wvl_uv = np.vstack((wvl_uv, wvl_uv[0,:]))

 

fig, ax = plt.subplots(figsize=(5,5))

ax.imshow(dat,

         extent=[xlim[0], xlim[1], ylim[0], ylim[1]],

         interpolation='None',

         origin='lower')

 

ax.set(xlim=(0, 0.7), xlabel='CIE u\'',

       ylim=(0, 0.7), ylabel='CIE v\'')

ax.plot(wvl_uv[:,0], wvl_uv[:,1], c='0', lw=3)

plt.show()

 

 

 

 


Method 2

colour.plottingを用いる方法。


[ ]

import colour.plotting as cpl

 

cpl.plot_chromaticity_diagram_CIE1976UCS(standalone=False)

cpl.render(

        standalone=True,

        bounding_box=(-0.1, 0.7, -0.05, 0.7),

        x_tighten=True,

        y_tighten=True,

        filename="CIE1976UCS_diagram.png")

plt.show()

 

 

 

 


已复制 1 个单元格。现在,您可以将它们粘贴到当前笔记本或其他笔记本中。


[python]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值