HOWTO · Python

Python で OpenCV モジュールを使用して画像を反転する

Python で OpenCV モジュールを使用して画像を反転する方法を学ぶ

このページの内容

Pythonで画像を反転するには、OpenCVが返す配列に cv2.bitwise_not() を適用します。符号なし8ビットの画像チャンネルでは、各値 v は 255 - v になります。以下ではチャンネルの扱いを説明し、画素データを使った計算例を示したうえで、カラー画像やグレースケール画像の処理と結果の保存方法を紹介します。

前提条件と画像の読み込み

スクリプトを実行する環境にPythonとOpenCVをインストールします。パッケージ名は opencv-python ですが、Pythonコードでは cv2 としてインポートします。まだインストールされていない場合は、pip install opencv-python を実行してください。NumPyを使う方法もありますが、標準的なOpenCVのPythonパッケージには依存関係としてNumPyが含まれています。

input_path に読み取り可能な画像ファイルのパスを設定します。OpenCVは既定でカラー画像をBGRのチャンネル順で読み込みます。image = cv2.imread(input_path) で画像を読み込みます。ファイルが存在しない、または読み取れない場合、imread は None を返すため、処理を始める前に image is not None を確認してください。以下の例では、一般的な画像ファイルで使われる8ビットのチャンネル値を扱います。

画像反転の仕組み

反転では、各チャンネルの値をその補数に変換します。0から255までの符号なし8ビット値では、黒は白に、白は黒になり、たとえば40は215になります。この処理は各チャンネルに個別に適用されるため、カラー画素の青、緑、赤の値はそれぞれ反転します。OpenCVが既定で返すカラー配列はRGBではなくBGRです。反転してもチャンネル順は保たれるため、色の並び替えは起こりません。

OpenCVで画像を反転する

OpenCVの cv2.bitwise_not() は、配列の各要素にビット単位のNOTを適用します。符号なし8ビットの画像データでは、各値を255から引いた場合と同じ結果になります。次の小さな標準ライブラリの例では、画像ファイルや画像処理パッケージを使わずに、画素値の計算を確認できます。まず値の変化を理解するために使い、OpenCVの画像配列を処理するときは、読み込みに成功したことを確認してから cv2.bitwise_not(image) を呼び出してください。

次の例を実行します。

このセクションのコードと表示されるラベルや出力は英語のままです。

pixel = [10, 40, 200]
inverted_pixel = [255 - value for value in pixel]
print("original:", pixel)
print("inverted:", inverted_pixel)
original: [10, 40, 200]
inverted: [245, 215, 55]

画像ファイルを処理するには、input_path に入力画像のパスを、output_path に保存先を設定してから、次の例を実行します。先にOpenCVをインストールしてください。以下のパスは置き換えが必要な例示用の値です。プログラムは画像の読み込みや書き込みに失敗した場合にその旨を表示し、読み込めなかった画像の処理は行いません。

try:
    import cv2
except ImportError:
    print("Install opencv-python to run this example.")
else:
    input_path = "input.png"
    output_path = "inverted.png"
    image = cv2.imread(input_path)

    if image is None:
        print(f"Could not read {input_path}")
    else:
        inverted = cv2.bitwise_not(image)
        written = cv2.imwrite(output_path, inverted)
        if not written:
            print(f"Could not write {output_path}")

        show_preview = False
        if show_preview:
            cv2.imshow("Original", image)
            cv2.imshow("Inverted", inverted)
            cv2.waitKey(0)
            cv2.destroyAllWindows()

読み込んだカラー配列は image に、反転した結果は inverted に格納されます。OpenCVは既定でカラー画像のチャンネルをBGR順で返します。この処理はチャンネルの順序を変えず、それぞれの値を反転します。上の画素計算例では、同じ符号なし8ビット値の変化を確認できます。

グレースケール画像を反転する

グレースケール画像では、各画素は3つのカラー値ではなく、1つの輝度値を持ちます。cv2.IMREAD_GRAYSCALE を指定して直接読み込み、gray_image is not None を確認してから、同じビット演算を適用してください。結果は1チャンネルの2次元配列のままで、cv2.imwrite() で保存できます。

このセクションのコードと表示されるラベルや出力は英語のままです。

try:
    import cv2
except ImportError:
    print("Install opencv-python to run this example.")
else:
    input_path = "input.png"
    gray_output_path = "inverted-gray.png"
    gray_image = cv2.imread(input_path, cv2.IMREAD_GRAYSCALE)

    if gray_image is None:
        print(f"Could not read {input_path} as grayscale")
    else:
        inverted_gray = cv2.bitwise_not(gray_image)
        written = cv2.imwrite(gray_output_path, inverted_gray)
        if not written:
            print(f"Could not write {gray_output_path}")

NumPyで画像を反転する

画像データがすでにNumPy配列にある場合は、代替方法としてNumPyの numpy.invert を使えます。この関数は各要素にビット単位のNOTを適用し、符号なし8ビット値ではOpenCVと同じチャンネルの補数を返します。この例では8ビットカラー画像を読み込んで反転し、保存結果を確認します。ここでの 255 - v という説明は符号なし8ビットデータに限られます。符号付き整数や、より広い整数型の配列に一般化しないでください。その場合もNumPyはビット単位の補数を計算します。

このセクションのコードと表示されるラベルや出力は英語のままです。

try:
    import cv2
    import numpy as np
except ImportError:
    print("Install opencv-python and numpy to run this example.")
else:
    input_path = "input.png"
    numpy_output_path = "inverted-numpy.png"
    image = cv2.imread(input_path)

    if image is None:
        print(f"Could not read {input_path}")
    else:
        inverted_numpy = np.invert(image)
        written = cv2.imwrite(numpy_output_path, inverted_numpy)
        if not written:
            print(f"Could not write {numpy_output_path}")

一般的な8ビット画像ファイルでは、cv2.bitwise_not(image) と numpy.invert(image) はチャンネルごとに同じ結果を返します。ワークフローのほかの部分でもOpenCVを使っているならOpenCVの処理を、配列操作としてNumPyの関数が必要ならNumPyの処理を選ぶとよいでしょう。

反転した画像を保存して表示する

反転した画像に対応する配列を書き込みます。カラー画像なら cv2.imwrite(output_path, inverted)、グレースケール画像なら cv2.imwrite(gray_output_path, inverted_gray) を使います。戻り値の真偽値を確認してください。False は、保存先のパスが利用できない、形式がサポートされていないなどの理由でOpenCVが書き込みに失敗したことを示します。各例では written でこの戻り値を確認し、書き込みに失敗した場合にその旨を表示します。

OpenCVの例には、任意で使えるプレビュー処理があります。両方のウィンドウを開くには、該当箇所で show_preview を True に設定してください。GUIでの表示にはグラフィカル環境が必要なため、ヘッドレス環境では利用できないことがあります。cv2.imwrite() による保存にはウィンドウを開く必要はありません。OpenCVとNumPyを使う画像ファイルの例は、それぞれのパッケージがインストールされ、input.png を読み取れる環境を想定しています。この記事で提供された実行証拠が対象としているのは、上の小さな画素計算例のみです。