Pynote

Python、機械学習、画像処理について

OpenCV - 階調変換を画像に適用する方法について

概要

OpenCV で階調変換を画像に適用する方法について紹介する。

階調変換

画素値の入力を x \in [0, 255] としたとき、f(x) = y \in [0, 255] という関数を用意して、画像の画素値を変換することを階調変換という。

例えば、ネガポジ反転の階調変換関数は f(x) = 255 - y を表される。

import cv2
import matplotlib.pyplot as plt
import numpy as np


def plot_tone_transform(x, y):
    fig, ax = plt.subplots(figsize=(5, 5))
    ax.plot(x, y)
    ax.set_xlabel("Input")
    ax.set_ylabel("Output")
    ax.set_xticks([0, 255])
    ax.set_yticks([0, 255])
    ax.set_xlim(0, 255)
    ax.set_ylim(0, 255)

    plt.show()


# ネガポジ反転
x = np.arange(256)
y = 255 - x

plot_tone_transform(x, y)

この関数を使って変換するには、https://docs.opencv.org/master/d2/de8/group__core__array.html#gab55b8d062b7f5587720ede032d34156f:cv2.LUT を利用する。

dst = cv.LUT(src, lut[, dst])
  • 引数
    • src: 入力画像
    • lut: look up table の略。[0, 255] の値の変換後の値を (256,) の1次元配列で表す。例えば、lut[10] は入力10の変換後の値を表す。
  • 返り値
    • dst: 出力画像
# 画像を読み込む。
img = cv2.imread("sample.jpg", cv2.IMREAD_GRAYSCALE)

# 変換する。
dst = cv2.LUT(img, y)

# 結果を保存する。
cv2.imwrite("result.png", dst)

2値化 (binarization)

# 画像を読み込む。
img = cv2.imread("sample.jpg", cv2.IMREAD_GRAYSCALE)

# 2値化
x = np.arange(256)
y = np.where(x <= 128, 0, 255)

# 変換する。
dst = cv2.LUT(img, y)

# 入力と出力の関係をグラフにする。
plot_tone_transform(x, y)

# 結果を保存する。
cv2.imwrite("result.png", dst)


ポスタリゼーション (postarization)

# 画像を読み込む。
img = cv2.imread("sample.jpg")

# ポスタリゼーション
x = np.arange(256)

n = 4  # 画素値を何段階で表現するか
bins = np.linspace(0, 255, n + 1)
y = np.array([bins[i - 1] for i in np.digitize(x, bins)]).astype(int)

# 変換する。
dst = cv2.LUT(img, y)

# 入力と出力の関係をグラフにする。
plot_tone_transform(x, y)

# 結果を保存する。
cv2.imwrite("result.png", dst)


ソラリゼーション (solarization)

# 画像を読み込む。
img = cv2.imread("sample.jpg")

# ソラリゼーション
x = np.arange(256)
y = (np.sin(x * 2 * np.pi / 255) + 1) * 255 / 2

# 変換する。
dst = cv2.LUT(img, y)

# 入力と出力の関係をグラフにする。
plot_tone_transform(x, y)

# 結果を保存する。
cv2.imwrite("result.png", dst)