Python + OpenCV4プログラミングの学習(5)〜色の処理など〜
本記事はOpenCVによる色の処理などを行ったときの備忘録である。
事前準備
以下の記事で仮想環境opencvEnvを構築していることを前提とする。 kawakeee.hatenablog.com
また、任意の画像を用意しておく。今回はLenna.jpgを用意した。

グレイスケール
以下のコードを写経しgrayscale.pyのファイルを作成。
import cv2 try: # どのような画像であってもグレイスケールで読み込む img = cv2.imread('img/Lenna.jpg', cv2.IMREAD_GRAYSCALE) if img is None: print('ファイルを読み込めません') import sys sys.exit() cv2.imwrite('img/grayscale.jpg', img) cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows() except: import sys print("Error:", sys.exc_info()[0]) print(sys.exc_info()[1]) import traceback print(traceback.format_tb(sys.exc_info()[2]))
対象画像が白黒画像で生成される。cv2.IMREAD_GRAYSCALE
を用いない方法もあるので以下に添付する。
# 対象画像をグレイスケールに変換 (対象画像, 白黒2値)
dst = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
- cv2.IMREAD_GRAYSCALE:cv2.imreadの引数に指定して画像をグレイスケールで読み込む。
- cv2.cvtColor:対象画像を引数で指定した色調に変更する。
使用例:cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
引数は、順に(対象画像, 色調設定)を表す。上記では対象画像がグレイスケールに変換される。
実行結果
(opencvEnv)$ python grayscale.py
指定フォルダ配下にグレイスケールされた画像が生成されていることを確認。
輝度平滑化
以下のコードを写経しequalize.pyのファイルを作成。
import cv2 try: # OpenCVの輝度平滑化関数はグレイスケール画像が対象のため、グレイスケール化 img = cv2.imread('img/Lenna.jpg', cv2.IMREAD_GRAYSCALE) if img is None: print('ファイルを読み込めません') import sys sys.exit() # 対象画像を輝度平滑化する。(輝度の統一) dst = cv2.equalizeHist(img) cv2.imwrite('img/equalizeHist.jpg', dst) cv2.imshow('img', dst) cv2.waitKey(0) cv2.destroyAllWindows() except: import sys print("Error:", sys.exc_info()[0]) print(sys.exc_info()[1]) import traceback print(traceback.format_tb(sys.exc_info()[2]))
OpenCVの輝度平滑化の関数はグレイスケール画像であることを前提にしているため、画像読み込み時にcv2.IMREAD_GRAYSCALE
を指定する。
- cv2.equalizeHist(...):対象画像を輝度平滑化する
使用例:cv2.equalizeHist(img) 引数は、順に(対象画像)を表す。
実行結果
(opencvEnv)$ python threshold.py
指定フォルダ配下に輝度平滑化された画像が生成されていることを確認。
グレイスケールで生成した画像と比べ輝度が統一されたように感じる。
スレッショルド処理
以下のコードを写経しthreshold.pyのファイルを作成。
import cv2 try: # 輝度に対してスレッショルド処理を行うため、グレイスケール化 img = cv2.imread('img/Lenna.jpg', cv2.IMREAD_GRAYSCALE) if img is None: print('ファイルを読み込めません') import sys sys.exit() # スレッショルド変換 (対象画像, 閾値, 最大値, スレッショルド変換設定) # THRESH_BINARY の場合 # 輝度が閾値より大きい箇所は 最大値(200)に変換 # 輝度が閾値以下の箇所は 0に変換 ret, dst = cv2.threshold(img, 100, 200, cv2.THRESH_BINARY) cv2.imwrite('img/threshold_THRESH_BINARY.jpg', dst) cv2.imshow('dst1', dst) # THRESH_BINARY_INV の場合 # 輝度が閾値より大きい箇所は 0に変換 # 輝度が閾値以下の箇所は 最大値(200)に変換 ret, dst = cv2.threshold(img, 100, 200, cv2.THRESH_BINARY_INV) cv2.imwrite('img/threshold_THRESH_BINARY_INV.jpg', dst) cv2.imshow('dst2', dst) # THRESH_TRUNC の場合 # 輝度が閾値より大きい箇所は 閾値に変換 # 輝度が閾値以下の箇所は 0に変換 ret, dst = cv2.threshold(img, 100, 200, cv2.THRESH_TRUNC) cv2.imwrite('img/threshold_THRESH_TRUNC.jpg', dst) cv2.imshow('dst3', dst) # THRESH_TOZERO の場合 # 輝度が閾値より大きい箇所は 変換しない # 輝度が閾値以下の箇所は 0に変換 ret, dst = cv2.threshold(img, 100, 200, cv2.THRESH_TOZERO) cv2.imwrite('img/threshold_THRESH_TRUNC.jpg', dst) cv2.imshow('dst4', dst) # THRESH_TOZERO_INV の場合 # 輝度が閾値より大きい箇所は 0に変換 # 輝度が閾値以下の箇所は 変換しない ret, dst = cv2.threshold(img, 100, 200, cv2.THRESH_TOZERO_INV) cv2.imwrite('img/threshold_THRESH_TRUNC.jpg', dst) cv2.imshow('dst5', dst) cv2.waitKey(0) cv2.destroyAllWindows() except: import sys print("Error:", sys.exc_info()[0]) print(sys.exc_info()[1]) import traceback print(traceback.format_tb(sys.exc_info()[2]))
- cv2.threshold(...):スレッショルド処理した画像を生成
使用例:cv2.threshold(img, 100, 200, cv2.THRESH_BINARY)
引数は、順に(対象画像,閾値,最大値,スレッショルド処理の種類)を表す。
ここでは以下の5パターンのスレッショルド処理を実行。
スレッショルド処理 | 処理内容 |
---|---|
THRESH_BINARY | 輝度が閾値より大きい箇所は 最大値に変換 輝度が閾値以下の箇所は 0に変換 |
THRESH_BINARY_INV | 輝度が閾値より大きい箇所は 0に変換 輝度が閾値以下の箇所は 最大値に変換 |
THRESH_TRUNC | 輝度が閾値より大きい箇所は 閾値に変換 輝度が閾値以下の箇所は 0に変換 |
THRESH_TOZERO | 輝度が閾値より大きい箇所は 変換しない 輝度が閾値以下の箇所は 0に変換 |
THRESH_TOZERO_INV | 輝度が閾値より大きい箇所は 0に変換 輝度が閾値以下の箇所は 変換しない |
実行結果
(opencvEnv)$ python threshold.py
指定フォルダ配下にスレッショルド処理された画像を確認。
アダプティブスレッショルド処理
以下のコードを写経しadaptive_threshold.pyのファイルを作成。
import cv2 try: img = cv2.imread('img/Lenna.jpg', cv2.IMREAD_GRAYSCALE) if img is None: print('ファイルを読み込めません') import sys sys.exit() print(img) # アダプティブスレッショルド変換 # 周りのピクセルと比べ輝度が大きい箇所は 最大値(200)に変換 # 周りのピクセルと比べ輝度が小さい箇所は 0に変換 dst = cv2.adaptiveThreshold(img, 200, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 7, 8) cv2.imwrite('img/adaptiveThreshold.jpg', dst) cv2.imshow('dst', dst) print(dst[:3]) cv2.waitKey(0) cv2.destroyAllWindows() except: import sys print("Error:", sys.exc_info()[0]) print(sys.exc_info()[1]) import traceback print(traceback.format_tb(sys.exc_info()[2]))
(調査中)ググってみたが概要しかつかめていない...
adaptiveThresholdの処理内容について詳しい方いたらご教授お願いします。
ざっくりだが、周辺のピクセルに比べ輝度が大きい箇所は最大値(この場合200)に変換され、小さい箇所は0に変換されているよう。
実行結果
(opencvEnv)$ python adaptive_threshold.py
指定フォルダ配下にアダプティブスレッショルドされた画像が生成されていることを確認。
カラー画像の各成分を分離
以下のコードを写経しsplit.pyのファイルを作成。
import cv2 try: img = cv2.imread('img/Lenna.jpg') if img is None: print('ファイルを読み込めません') import sys sys.exit() # 対象画像のカラー画像を分離 rgb = cv2.split(img) blue = rgb[0] green = rgb[1] red = rgb[2] cv2.imwrite('img/b.jpg', blue) cv2.imwrite('img/g.jpg', green) cv2.imwrite('img/r.jpg', red) cv2.imshow('blue', blue) cv2.imshow('green', green) cv2.imshow('red', red) cv2.waitKey(0) cv2.destroyAllWindows() except: import sys print("Error:", sys.exc_info()[0]) print(sys.exc_info()[1]) import traceback print(traceback.format_tb(sys.exc_info()[2]))
- cv2.split(...):カラー画像の色成分を分離
使用例:cv2.split(img)
引数の(対象カラー画像)を色成分に分離した結果を返す。
今回、生成されたb.jpg、g.jpg、r.jpgは各色成分の強さを表している。画像が白に近いほど、当該成分の色が強い。逆に、画像が黒に近いほど、当該成分の色が弱い。
実行結果
(opencvEnv)$ python split.py
色成分が分離された画像が生成されていることを確認。
他と比べr.jpgが白っぽい画像であることから、元の画像は全体的に赤成分が強い画像であるとわかる。

まとめ
- cv2.IMREAD_GRAYSCALE:cv2.imreadの引数に指定して画像をグレイスケールで読み込む。
- cv2.cvtColor:対象画像を引数で指定した色調に変更する。
- cv2.equalizeHist(...):対象画像を輝度平滑化する
- cv2.threshold(...):スレッショルド処理した画像を生成
- cv2.split(...):カラー画像の色成分を分離