OpenCV – float 型の配列を画像化する方法

目次

概要

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)

コメント

コメントする

目次