【Python・OpenCV】画像の正規化の効果と使い方(cv2.normalize)

※当サイトではアフィリエイト広告を利用しています

Python プログラミング 画像処理

【Python・OpenCV】画像の正規化の効果と使い方(cv2.normalize)

2023-08-22

はじめに

この記事では、OpenCVのcv2.normalize関数による画像の正規化と、応用例について解説します。

(広告)OpenCV関連書籍をAmazonで探す

画像の正規化

画像データの正規化により、以下のような効果が期待できます。

  1. コントラストの改善:
    画像のコントラストを向上させることで、画像の明るさや色の違いがより顕著になります。これにより、画像の細部や特徴がより鮮明に見えるようになります。
  2. 特徴抽出の改善:
    画像を正規化することで、特徴抽出や画像認識のアルゴリズムがより効果的に機能する可能性が高まります。特に、機械学習アルゴリズムに入力データを供給する際に、値の範囲を一定の範囲に収めることは重要になります。
  3. 画像の前処理:
    画像を正規化することで、不要なノイズの影響を軽減し、画像処理の精度を向上させることができます。これは、画像を解析したり、画像処理アルゴリズムを適用する前に行われる一般的な前処理の手法です。
  4. データの比較:
    異なる画像を比較する場合、正規化された値を使用することで、値のスケールの違いによる影響を排除し、より公平な比較を行うことができます。

正規化の方法や適切な範囲は、具体的な問題とデータによって異なる場合がありますので、適切なパラメータの選択が重要となります。

cv2.normalize関数

cv2.normalize関数の使い方は下の通りです。

cv2.normalize(入力画像, 出力画像[, alpha[, beta[, norm_type[, dtype[, mask]]]]])

引数

名称説明
入力画像(必須)読み込む画像のファイル名
出力画像(必須)出力画像
alpha(オプション)正規化範囲の下限(float)(デフォルト:0)
beta(オプション正規化範囲の上限(float)(デフォルト:1)
norm_type(オプション正規化のタイプ。NormTypesを参照(デフォルト:cv2.NORM_L2
dtype(オプション出力される画像データのデータ型
mask(オプション画像の特定の領域を指定するマスク

戻り値

演算後の画像が戻り値となります。

ポイント

出力画像は戻り値で取得することができますが、引数で出力先を指定することもできます。戻り値で出力画像を取得する際は下に示すサンプルコードのように、引数の出力画像にNoneを指定します。

引数のnorm_typeで指定できるものは、NormTypesに列挙されていますが、cv2.normalize関数では全てが使用できるわけでは無いようです。使用可能なものを下に抜粋しました。下に無いものを指定するとエラーになります。

NormTypes

norm_type 説明
cv2.NORM_INF
  • 要素の絶対値の最大値を返します。すなわち、L∞ノルム(無限大ノルム)とも呼ばれます。
  • ノイズに対して敏感でなく、外れ値の影響を受けにくい特性を持ちます。
cv2.NORM_L1
  • 要素の絶対値の合計を返します。マンハッタン距離とも呼ばれます。
  • 一般的にはL1ノルムは外れ値に対してロバストで、多くの値がゼロに近い場合に有効です。
cv2.NORM_L2
  • 要素の平方根の合計を返します。ユークリッド距離とも呼ばれます。
  • L2ノルムは外れ値に対して敏感で、通常はノイズの少ないデータに適しています。
cv2.NORM_MINMAX
  • 値を指定された範囲(デフォルトでは最小:0、最大:1])に正規化します。
  • 主に画像のコントラスト調整や特徴抽出の前処理に使用されます。

ノルムとは

ノルム(Norm)は、ベクトルや行列の大きさや長さを表す数学的な概念です。画像処理や機械学習の分野でしばしば使用される概念です。ベクトルや行列のノルムを計算することによって、それらの大きさや距離を評価することができます。

画像処理では、ノルムは特徴ベクトルの正規化や類似性の評価などに使用されることがあります。例えば、画像間の距離を評価するために、それぞれの画像を特徴ベクトルとして表現し、特徴ベクトル間のノルムを計算して類似性を判断することがあります。

指定した範囲にスケーリングする例

cv2.normalize関数において、よく利用されるnorm_typeがcv2.NORM_MINMAXの場合のサンプルコードを下に示します。

入力画像として、この画像を使用しました。

入力画像をグレースケールに変換した後、正規化を行なっています。
輝度値が100〜200の範囲に収まるように正規化した結果が下記となります。

左上が入力画像、右上がそのヒストグラム、左下が正規化後の画像、右下がそのヒストグラムとなります。
引数は、alpha=100, beta=200, norm_type=cv2.NORM_MINMAX です。

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

# 画像の読み込み
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# 入力画像のヒストグラムの作成(引数の'image'を[ ]で囲うことを忘れないで下さい)
histogram1 = cv2.calcHist([image], [0], None, [256], [0, 256])


# 正規化
lower = 100                                                       # 正規化の下限値
upper = 200                                                       # 正規化の上限値
result = cv2.normalize(image, None, alpha=lower, beta=upper, norm_type=cv2.NORM_MINMAX)

# 正規化後の画像のヒストグラムの作成
histogram2 = cv2.calcHist([result], [0], None, [256], [0, 256])


# ヒストグラムの可視化
plt.rcParams["figure.figsize"] = [12,7.5]                         # 表示領域のアスペクト比を設定
title = "cv2.normalize (alpha=" + str(lower) + ", beta=" + str(upper) + ", norm_type=cv2.NORM_MINMAX" + "): codevace.com"
plt.figure(title)                                                 # ウィンドウタイトルを設定
plt.subplots_adjust(left=0.05, right=0.95, bottom=0.10, top=0.95) # 余白を設定
plt.subplot(221)                                                  # 1行2列の1番目の領域にプロットを設定
plt.imshow(image, vmin=0, vmax=255, cmap='gray')                  # 画像をグレースケールで表示、最大値・最小値を指定
plt.axis("off")                                                   # 軸目盛、軸ラベルを消す
plt.subplot(222)                                                  # 1行2列の2番目の領域にプロットを設定
plt.plot(histogram1)                                              # ヒストグラムのグラフを表示
plt.xlabel('Brightness')                                          # x軸ラベル(明度)
plt.ylabel('Count')                                               # y軸ラベル(画素の数)

# ヒストグラムの可視化
plt.subplot(223)                                                  # 1行2列の3番目の領域にプロットを設定
plt.imshow(result, vmin=0, vmax=255, cmap='gray')                 # 画像をグレースケールで表示、最大値・最小値を指定
plt.axis("off")                                                   # 軸目盛、軸ラベルを消す
plt.subplot(224)                                                  # 1行2列の4番目の領域にプロットを設定
plt.plot(histogram2)                                              # ヒストグラムのグラフを表示
plt.xlabel('Brightness')                                          # x軸ラベル(明度)
plt.ylabel('Count')                                               # y軸ラベル(画素の数)
plt.show()

ポイント

36行目のplt.imshow関数の引数に vmin=0, vmax=255 を指定しています。通常のグレースケール画像では必要がない場合がほとんどですが、正規化後の画像では輝度の範囲が100〜200であるため、plt.imshow関数のスケーリング機能で0〜255の階調で表示されないことがあり、明示的に指定しています。

おわりに

cv2.normalize関数の解説をしました。cv2.NORM_MINMAX以外のノルムの指定に関しては、筆者自身の理解不足で、記事内での解説が出来ませんでした。どなたか教えて頂けると嬉しいです。

最後までご覧いただきありがとうございました。

■(広告)OpenCVの参考書としてどうぞ!■

参考リンク

-Python, プログラミング, 画像処理
-