【Python・OpenCV】ネガポジ反転、白黒反転を行うには

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

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

【Python・OpenCV】ネガポジ反転、白黒反転を行うには

2023-09-12

はじめに

ネガポジ変換は、画像のネガティブとポジティブを切り替える方法です。ネガティブ画像は明るい部分が暗く、暗い部分が明るいもので、ポジティブ画像は通常の色調を持つ画像です。
一般的な画像処理アプリケーションにおいて、ネガポジ変換が必要となる場面は多くないかもしれません。ビデオエフェクトなど芸術的な効果を得る場合やクリエイティブな場面で面白い効果を生み出す際などに限定されてしまうかもしれませんが、画素値の反転方法を知っておくことが役に立つ場面があると思いますので、紹介します。

ネガポジ反転とは

ネガポジ変換は、画像のネガティブとポジティブを切り替える方法です。ネガティブ画像は明るい部分が暗く、暗い部分が明るいもので、ポジティブ画像は通常の色調を持つ画像です。

ネガポジ反転、白黒反転の方法

OpenCVを使用して、ネガティブ画像をポジティブ画像に変換、白黒反転する方法を、ここでは2つ紹介します。

減算による方法

多くの場合、OpenCVで扱う画像のデータ型は256階調の表現が可能なuint8であるため、各ピクセルの色情報を255から減算することで、ネガポジ反転することができます。

サンプルコードを章の最後に示します。

ネガポジ変換の演算はサンプルコードの11行目、下の記述になります。

# ネガポジ変換を行う
negative_image = 255 - rgb_image

ポイント

Pythonでは1画素ずつ計算するのではなく、このように記述することで効率的に処理することができます。for文などで1画素ずつ計算を行うと処理時間が長くなってしまいます。

注意

減算による方法では、画像データのデータ型はuint8に限定されます。他のデータ型のデータでは正しく変換されません。

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

左上に入力画像、右上に入力画像のヒストグラム、左下にネガポジ変換画像、右下にネガポジ変換画像のヒストグラムを表示していま

数式の通り、RGB各チャンネルの輝度値が反転されていることがわかります。

import cv2
import matplotlib.pyplot as plt

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

# BGRのチャンネル並びをRGBの並びに変更(matplotlibで表示するため)
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 

# ネガポジ変換を行う
negative_image = 255 - rgb_image

# ヒストグラムの作成(引数の'image'を[ ]で囲うことを忘れないで下さい)
r_image_hist = cv2.calcHist([rgb_image], [0], None, [256], [0, 256])
b_image_hist = cv2.calcHist([rgb_image], [1], None, [256], [0, 256])
g_image_hist = cv2.calcHist([rgb_image], [2], None, [256], [0, 256])
r_negative_hist = cv2.calcHist([negative_image], [0], None, [256], [0, 256])
b_negative_hist = cv2.calcHist([negative_image], [1], None, [256], [0, 256])
g_negative_hist = cv2.calcHist([negative_image], [2], None, [256], [0, 256])

# 変換結果を表示
plt.rcParams["figure.figsize"] = [12,7.5]                           # ウィンドウサイズを設定
title = "Negative Positive Conversion: codevace.com"
plt.figure(title)                                                   # ウィンドウタイトルを設定
plt.subplots_adjust(left=0.05, right=0.95, bottom=0.03, top=0.95)   # 余白を設定
plt.subplot(221)                                                    # 2行2列の1番目の領域にプロットを設定
plt.imshow(rgb_image)                                               # 入力画像を表示
plt.title('Original Image')                                         # 画像タイトル設定
plt.axis("off")                                                     # 軸目盛、軸ラベルを消す
plt.subplot(222)                                                    # 2行2列の2番目の領域にプロットを設定
plt.plot(b_image_hist, color='blue', label='blue')                  # 青チャンネルのヒストグラムのグラフを表示
plt.plot(g_image_hist, color='green', label='green')                # 緑チャンネルのヒストグラムのグラフを表示
plt.plot(r_image_hist, color='red', label='red')                    # 赤チャンネルのヒストグラムのグラフを表示
plt.title('Original Histogram')                                     # ヒストグラムのグラフのタイトル設定
plt.subplot(223)                                                    # 2行2列の3番目の領域にプロットを設定
plt.imshow(negative_image)                                          # 反転画像を表示
plt.title('Converted Image(255 - [input image])')                   # 画像タイトル設定
plt.axis("off")                                                     # 軸目盛、軸ラベルを消す
plt.subplot(224)                                                    # 2行2列の4番目の領域にプロットを設定
plt.plot(b_negative_hist, color='blue', label='blue')               # 青チャンネルのヒストグラムのグラフを表示
plt.plot(g_negative_hist, color='green', label='green')             # 緑チャンネルのヒストグラムのグラフを表示
plt.plot(r_negative_hist, color='red', label='red')                 # 赤チャンネルのヒストグラムのグラフを表示
plt.title('Converted Histogram')                                    # ヒストグラムのグラフのタイトル設定
plt.show()

cv2.bitwise_not関数を使う方法

OpenCVのcv2.bitwise_not関数を使うことで、ネガポジ反転、白黒反転を行うことができます。

cv2.bitwise_not(入力画像[, mask])

引数

名称説明
入力画像(必須)入力画像
mask(オプション)画像の特定の領域を指定するマスク。

戻り値

戻り値は反転後の画像データです。

使い方

cv2.bitwise_not関数を使用したサンプルコードです。
減算による方法のサンプルコードとほとんど同じですが、11行目の減算をcv2.bitwise_not関数に変更しています。

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

減算による方法と同じ結果が得られていることがわかります。

import cv2
import matplotlib.pyplot as plt

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

# BGRのチャンネル並びをRGBの並びに変更(matplotlibで表示するため)
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 

# ネガポジ変換を行う
negative_image = cv2.bitwise_not(rgb_image)

# ヒストグラムの作成(引数の'image'を[ ]で囲うことを忘れないで下さい)
r_image_hist = cv2.calcHist([rgb_image], [0], None, [256], [0, 256])
b_image_hist = cv2.calcHist([rgb_image], [1], None, [256], [0, 256])
g_image_hist = cv2.calcHist([rgb_image], [2], None, [256], [0, 256])
r_negative_hist = cv2.calcHist([negative_image], [0], None, [256], [0, 256])
b_negative_hist = cv2.calcHist([negative_image], [1], None, [256], [0, 256])
g_negative_hist = cv2.calcHist([negative_image], [2], None, [256], [0, 256])

# 変換結果を表示
plt.rcParams["figure.figsize"] = [12,7.5]                           # ウィンドウサイズを設定
title = "Negative Positive Conversion: codevace.com"
plt.figure(title)                                                   # ウィンドウタイトルを設定
plt.subplots_adjust(left=0.05, right=0.95, bottom=0.03, top=0.95)   # 余白を設定
plt.subplot(221)                                                    # 2行2列の1番目の領域にプロットを設定
plt.imshow(rgb_image)                                               # 入力画像を表示
plt.title('Original Image')                                         # 画像タイトル設定
plt.axis("off")                                                     # 軸目盛、軸ラベルを消す
plt.subplot(222)                                                    # 2行2列の2番目の領域にプロットを設定
plt.plot(b_image_hist, color='blue', label='blue')                  # 青チャンネルのヒストグラムのグラフを表示
plt.plot(g_image_hist, color='green', label='green')                # 緑チャンネルのヒストグラムのグラフを表示
plt.plot(r_image_hist, color='red', label='red')                    # 赤チャンネルのヒストグラムのグラフを表示
plt.title('Original Histogram')                                     # ヒストグラムのグラフのタイトル設定
plt.subplot(223)                                                    # 2行2列の3番目の領域にプロットを設定
plt.imshow(negative_image)                                          # 反転画像を表示
plt.title('Converted Image(cv2.bitwise_not)')                       # 画像タイトル設定
plt.axis("off")                                                     # 軸目盛、軸ラベルを消す
plt.subplot(224)                                                    # 2行2列の4番目の領域にプロットを設定
plt.plot(b_negative_hist, color='blue', label='blue')               # 青チャンネルのヒストグラムのグラフを表示
plt.plot(g_negative_hist, color='green', label='green')             # 緑チャンネルのヒストグラムのグラフを表示
plt.plot(r_negative_hist, color='red', label='red')                 # 赤チャンネルのヒストグラムのグラフを表示
plt.title('Converted Histogram')                                    # ヒストグラムのグラフのタイトル設定
plt.show()

グレースケール画像の白黒反転

グレースケール画像の場合のネガポジ反転は白黒反転になります。この場合も同じ様に減算による方法とcv2.bitwise_not関数を使う方法で処理することができます。

左がグレースケールの入力画像、中央が減算による方法の反転結果、右がcv2.bitwise_not関数を使う方法の反転結果です。期待どおりに輝度値が反転されていることがわかります。

import cv2
import matplotlib.pyplot as plt

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

# 白黒変換を行う
bin_image_inverted_1 = 255 - image
bin_image_inverted_2 = cv2.bitwise_not(image)

# 画像とエッジ画像を表示
plt.rcParams["figure.figsize"] = [12,3.5]                           # ウィンドウサイズを設定
title = "Grayscale Image Conversion: codevace.com"
plt.figure(title)                                                   # ウィンドウタイトルを設定
plt.subplots_adjust(left=0.05, right=0.95, bottom=0.03, top=0.95)   # 余白を設定
plt.subplot(131)                                                    # 2行2列の1番目の領域にプロットを設定
plt.imshow(image, cmap='gray')                                      # 入力画像を表示
plt.title('Original Image')                                         # 画像タイトル設定
plt.axis("off")                                                     # 軸目盛、軸ラベルを消す
plt.subplot(132)                                                    # 2行2列の3番目の領域にプロットを設定
plt.imshow(bin_image_inverted_1, cmap='gray')                       # 減算による反転画像を表示
plt.title('Converted Image(255 - [Original Image])')                # 画像タイトル設定
plt.axis("off")                                                     # 軸目盛、軸ラベルを消す
plt.subplot(133)                                                    # 2行2列の4番目の領域にプロットを設定
plt.imshow(bin_image_inverted_2, cmap='gray')                       # cv2.bitwise_notによる反転画像を表示
plt.title('Converted Image(cv2.bitwise_not)')                       # 画像タイトル設定
plt.axis("off")                                                     # 軸目盛、軸ラベルを消す
plt.show()

おわりに

ネガポジ反転、白黒反転の方法を2つ紹介しました。
処理自体は1行で完結するので、難しいことはないと思います。
お手持ちの画像を使用して試してみてください。
また、サンプルコードの大部分はmatplotlibを使って結果を表示する処理となります。画像もグラフも同じウィンドウに綺麗に表示できるのでとても便利です。

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

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

参考リンク

(広告)あなたに合ったプログラミング スクールが見つかるかも

プログラミングの学習が、新しい世界を開きます。副業からキャリアの転換まで、目標に向かって一歩を踏み出しましょう。

これらのプログラミング スクールは、あなたの目的に合わせて選択できるさまざまなプログラムを提供しています。どのスクールを選ぶにせよ、プログラミングは未来への扉を開き、新しい機会を切り開く手段として素晴らしい選択です。あなたの夢や目標を実現する第一歩を踏み出す準備はできていますか?

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