目次
概要
float 型の配列を OpenCV で扱える画像の形式に変換する方法について紹介します。
範囲のスケーリング
範囲が $[a_{old}, b_{old}]$ である値 $x_{old}$ を範囲 $[a_{new}, b_{new}]$ の値 $x_{new}$ に変換する式は以下のようになります。
$$ x_{new} = (x – a_{old})\frac{b_{new} – a_{new}}{b_{old} – a_{old}} + a_{new} $$
In [1]:
import numpy as np
def scale(x, a_old, b_old, a_new, b_new):
if a_old == b_old:
return x
new_x = (x - a_old) / (b_old - a_old) * (b_new - a_new) + a_new
return new_x
x = np.array([5, 6, 4, 5, 6, 4, 1, 5, 1, 7])
x2 = scale(x, x.min(), x.max(), 1, 2)
print(f"[{x.min()}, {x.max()}] -> [{x2.min()}, {x2.max()}]")
[1, 7] -> [1.0, 2.0]
[0, 1] にスケーリングする
$[a_{new}, b_{new}] = [0, 1]$ を代入すると、先程の式は以下のように簡略化できます。
$$ x_{new} = \frac{x – a_{old}}{b_{old} – a_{old}} $$
In [2]:
import numpy as np
def scale_to_0_1(x, a_old, b_old):
if a_old == b_old:
return x
new_x = (x - a_old) / (b_old - a_old)
return new_x
x = np.array([5, 6, 4, 5, 6, 4, 1, 5, 1, 7])
x2 = scale_to_0_1(x, x.min(), x.max())
print(f"[{x.min()}, {x.max()}] -> [{x2.min()}, {x2.max()}]")
[1, 7] -> [0.0, 1.0]
[0, 255] にスケーリングする
$[a_{new}, b_{new}] = [0, 255]$ を代入すると、先程の式は以下のように簡略化できます。
$$ x_{new} = 255 \frac{x – a_{old}}{b_{old} – a_{old}} $$
In [3]:
import numpy as np
def scale_to_0_255(x, a_old, b_old):
if a_old == b_old:
return x
new_x = 255 * (x - a_old) / (b_old - a_old)
return new_x
x = np.array([5, 6, 4, 5, 6, 4, 1, 5, 1, 7])
x2 = scale_to_0_255(x, x.min(), x.max())
print(f"[{x.min()}, {x.max()}] -> [{x2.min()}, {x2.max()}]")
[1, 7] -> [0.0, 255.0]
[-1, 1] にスケーリングする
$[a_{new}, b_{new}] = [-1, 1]$ を代入すると、先程の式は以下のように簡略化できます。
$$ x_{new} = 2\frac{x – a_{old}}{b_{old} – a_{old}} – 1 $$
In [4]:
import numpy as np
def scale_to_neg1_1(x, a_old, b_old):
if a_old == b_old:
return x
new_x = 2 * (x - a_old) / (b_old - a_old) - 1
return new_x
x = np.array([5, 6, 4, 5, 6, 4, 1, 5, 1, 7])
x2 = scale_to_neg1_1(x, x.min(), x.max())
print(f"[{x.min()}, {x.max()}] -> [{x2.min()}, {x2.max()}]")
[1, 7] -> [-1.0, 1.0]
float 型の配列を画像化する
float 型の配列を画像にする場合、まず画素値を $[0, 255]$ の範囲に変換し、その後 numpy.uint8
型にキャストします。
In [5]:
import cv2
from IPython import display
def imshow(img, format=".jpg", **kwargs):
"""ndarray 配列をインラインで Notebook 上に表示する。"""
img = cv2.imencode(format, img)[1]
img = display.Image(img, **kwargs)
display.display(img)
In [6]:
import numpy as np
def array_to_img(x):
if x.min() == x.max():
return np.zeros_like(x, dtype=np.uint8)
img = 255 * (x - x.min()) / (x.max() - x.min())
img = img.astype(np.uint8)
return img
# 適当な float 型の配列を作成する。
arr = np.tile(np.linspace(0, 1, 200).reshape(1, -1, 1), (200, 1, 3))
img = array_to_img(arr)
imshow(img)
コメント