【Python・OpenCV】画像のコントラストと明るさを変更するには

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

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

【Python・OpenCV】画像のコントラストと明るさを変更するには

2023-07-01

はじめに

前回の投稿で、cv2.addWeighted関数の応用として画像のコントラストと明るさを変更する方法を紹介しました。

参考記事


cv2.addWeighted関数を使用する方法は応用的な手法のため、使われる機会は少ないと思います。
本投稿では、よく使われる画像のコントラストと明るさの変更を行う3種類の実装について考えてみます。

コントラストと明るさの変更

コントラストと明るさの変更は、画素値に対して以下に示す乗算と加算による計算式(1)を適用することで求めることが出来ます。
$$変更後 画素値 = [入力画素値] \times \alpha + \beta \tag{1}\\
\alpha : コントラスト(\alpha > 0)\\
\beta : 明るさ$$

以降では計算式(1)の演算を行う3つの方法について紹介します。

画像のコントラストと明るさの変更方法
  • cv2.convertScaleAbs関数
  • cv2.multiply関数
  • 画素値毎に直接計算

cv2.convertScaleAbs関数

cv2.convertScaleAbs関数を使用して、画像のコントラストと明るさを変更します。この関数は、入力画像をスケーリングし、絶対値を取った後の出力画像を生成します。

cv2.convertScaleAbs関数の構文

cv2.convertScaleAbs(入力画像[, alpha[, beta]])

引数

名称説明
入力画像(必須)入力画像データ
alpha(オプション)スケールファクター(コントラスト)、1.0で変化なし。
beta(オプション)スケーリングされた値に加算される値(明るさ)、0.0で変化なし。

戻り値

コントラストと明るさを変更後の画像データ(ndarray)

コントラストと明るさの変更の演算は以下の式で計算されます。

$$変更後 画素値 = [入力画素値] \times alpha + beta$$
以下のコードでは、alphaパラメータを使用してコントラストを調整し、betaパラメータを使用して明るさを調整しています。

import cv2

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

# コントラストと明るさの変更
alpha = 1.5  # コントラストの倍率(1より大きい値でコントラストが上がる)
beta = 10  # 明るさの調整値(正の値で明るくなる)

adjusted_image = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)

# 変更後の画像の表示
cv2.imshow("Original Image", image)
cv2.imshow('convertScaleAbs', adjusted_image)

cv2.waitKey(0)
cv2.destroyAllWindows()

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

引用元
駅近くの茶色の木製ベンチ

変更の結果は下の様になります。

cv2.multiply関数, cv2.add関数

cv2.multiply関数とcv2.add関数を使用することでも、画像のコントラストと明るさを変更することができます。cv2.multiply関数は各画素値に対して乗算を行い、cv2.add関数は各画素値に対して加算を行います。
つまり、これらの関数を用いて計算式(1)の演算を行います。

cv2.multiply関数

OpenCVのcv2.multiply関数は、2つの配列(画像)の要素ごとの乗算を行うための関数です。
具体的には、2つの入力行列(同じサイズである必要があります)の対応する要素同士を掛け算し、結果の行列を生成します。

cv2.multiply(入力データ1, 入力データ2, [, scale[, dtype]])

引数

名称説明
入力データ1(必須)1つ目の入力データ
入力データ2(必須)2つ目の入力データ。入力データ1とサイズ、データ型が同じである必要があります。
scale(オプション)スケールファクター、scale値を各要素(画素値)に乗算します。(デフォルト値:1)
dtype(オプション)出力データのデータ型

戻り値

演算後のデータ(ndarray)

cv2.add関数

cv2.add() 関数は、OpenCVライブラリで提供されている画像の加算を行うための関数です。
この関数は、2つの入力画像を要素ごとに加算します。
つまり、出力画像の各ピクセルの値は、対応する位置の2つの入力画像のピクセル値の合計となります。

cv2.add(入力データ1, 入力データ2, [, mask[, dtype]])

引数

名称説明
入力データ1(必須)1つ目の入力データ
入力データ2(必須)2つ目の入力データ。入力データ1とサイズ、データ型が同じである必要があります。
mask(オプション)8ビット,シングルチャンネルのマスクデータ。指定された場合、マスク画像の非ゼロピクセルに対応する位置でのみ加算が行われます。
dtype(オプション)出力画像のデータ型。指定されない場合は、入力画像のデータ型と同じになります。

戻り値

演算後のデータ(ndarray)

使い方

サンプルコードを示します。

import cv2
import numpy as np

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

# コントラストと明るさの変更
alpha = 1.0  # コントラストの倍率(1より大きい値でコントラストが上がる)
beta = 50.0  # 明るさの調整値(正の値で明るくなる)

# 画像のサイズを取得(height:高さ, width:幅, channel:チャンネル数)
height, width, channel = image.shape[:3]
# コントラストと明るさの変更
adjusted_image = cv2.multiply(image, np.array([alpha]))
adjusted_image = cv2.add(adjusted_image, np.full((height, width, 3), beta, np.uint8))

# 変更後の画像の表示
cv2.imshow("Original Image", image)
cv2.imshow('multiply', adjusted_image)

cv2.waitKey(0)
cv2.destroyAllWindows()

演算の結果は下の様になります。
cv2.convertScaleAbs関数と同様の結果が得られました。

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

画素値毎に直接計算する

3つ目の方法は画素値にアクセスし、計算式(1)を計算します。
OpenCVの関数は使用せず、for文によるループ処理を行います。
このため、Pythonでは処理が遅くなりますが、どのような処理を行なっているか分かり易いというメリットがあります。

下のサンプルコードでは18行目で計算式(1)の演算を行なっています。
np.clip関数はNumpyの関数で、第一引数の値を第二引数〜第三引数の範囲に収めます。
サンプルコードの例では計算式(1)の演算の結果が0未満の場合は0に置き換え、255より大きくなった場合は255に置き換えます。

import cv2
import numpy as np

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

# コントラストと明るさの変更
alpha = 1.0  # コントラストの倍率(1より大きい値でコントラストが上がる)
beta = 50.0  # 明るさの調整値(正の値で明るくなる)

# 出力先を準備
adjusted_image = np.zeros(image.shape, image.dtype)


for i in range(image.shape[0]):
    for j in range(image.shape[1]):
        for k in range(image.shape[2]):
            adjusted_image[i, j, k] = np.clip(image[i, j, k] * alpha + beta, 0, 255)

# 変更後の画像の表示
cv2.imshow("Original Image", image)
cv2.imshow('Pixel Access', adjusted_image)

cv2.waitKey(0)
cv2.destroyAllWindows()

演算の結果は下の様になります。
先に紹介した2つの方法と同等の結果になっていることがわかります。

おわりに

コントラストと明るさを変更する3つの方法について紹介しました。
最も簡単な方法はcv2.convertScaleAbs関数です。他の方法は計算式(1)の計算を行う実装方法を紹介し、cv2.convertScaleAbs関数の結果と同等であることを確認しました。
3つ目の画素値にアクセスして計算する方法は、処理速度の面でおすすめしませんが、どの様な計算をしているかを理解するために紹介させて頂きました。

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

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

参考リンク

(広告)おすすめ転職エージェント

転職はあなたの可能性を広げる鍵です。その鍵を手に入れるため、おすすめ転職エージェントを紹介します。

新しいキャリアの扉を開くために、転職エージェント活用して、妥協のない転職活動を行ってください。

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