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

概要

float 型の配列を OpenCV で扱える画像の形式に変換する方法について紹介します。

範囲のスケーリング

範囲が [aold,bold][a_{old}, b_{old}] である値 xoldx_{old} を範囲 [anew,bnew][a_{new}, b_{new}] の値 xnewx_{new} に変換する式は以下のようになります。

xnew=(xaold)bnewanewboldaold+anew 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()}]")
Python
[1, 7] -> [1.0, 2.0]

[0, 1] にスケーリングする

[anew,bnew]=[0,1][a_{new}, b_{new}] = [0, 1] を代入すると、先程の式は以下のように簡略化できます。

xnew=xaoldboldaold 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()}]")
Python
[1, 7] -> [0.0, 1.0]

[0, 255] にスケーリングする

[anew,bnew]=[0,255][a_{new}, b_{new}] = [0, 255] を代入すると、先程の式は以下のように簡略化できます。

xnew=255xaoldboldaold 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()}]")
Python
[1, 7] -> [0.0, 255.0]

[-1, 1] にスケーリングする

[anew,bnew]=[1,1][a_{new}, b_{new}] = [-1, 1] を代入すると、先程の式は以下のように簡略化できます。

xnew=2xaoldboldaold1 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()}]")
Python
[1, 7] -> [-1.0, 1.0]

float 型の配列を画像化する

float 型の配列を画像にする場合、まず画素値を [0,255][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)
Python
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)
Python

コメント

コメントする