1. OpenCVの基本#
OpenCVはコンピュータ・ビジョンのための様々な機能が用意されたC++のライブラリで、Pythonからも利用することができる。PipやAnacondaを用いる場合、以下のコマンドでインストールできる。
# Pipを用いる場合
pip install opencv-python
# Anacondaを用いる場合
conda install opencv
PythonからOpenCVを使うには、 cv2 モジュールをインポートすれば良い。
import cv2
また、インストールされているOpenCVのバージョンは次のようにして確認できる。
print(cv2.__version__)
2026年現在のOpenCVの最新バージョンは4.12.0なので、正しくインストールされていれば、これに近い値が表示されるはずである。
1.1. 画像の読み書き#
OpenCVで画像を読み込むには cv2.imread を用いる。カラー画像として読み込みたい場合には第二引数に cv2.IMREAD_COLOR を指定する。すると、画像の情報がNumPyの配列として返ってくる。
import cv2
img = cv2.imread("sample.jpg", cv2.IMREAD_COLOR)
cv2.imread は画像の読み込みが成功したときにはNumPyの配列を返すが、失敗したときには None を返す (この際、例外などは発生しない)。従って、画像の読み込みの成否をプログラムで明示的に行う必要がある。
if img is None:
raise IOError("Failed to load image")
読み込まれた画像の大きさは「高さ × 幅」という順序でデータが格納されており、通常、各画素値は np.uint8 型、すなわち8ビット符号なし整数で表されている。なお、OpenCVを用いて読み込んだ画像はチャンネルがBGRの順に並んでいるため、必要に応じてチャンネルの順序を入れ替える必要がある。
print(img.shape) # (height, width, channels)
print(img.dtype) # uint8
# チャンネル順序の入れ替え (OpenCVを使う場合)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# チャンネル順序の入れ替え (NumPyを使う場合)
img_rgb = np.flip(img, axis=2)
画像を保存するには、データを np.uint8 型に変換したうえで cv2.imwrite を用いる。
cv2.imwrite("sample_out.jpg", img)
OpenCVは様々な形式の画像の読み書きの対応しており、代表的なJPEG, PNG等の画像フォーマットであれば読み書きがサポートされている。
画像を保存するときの注意
画像を保存する際、画像を表すNumPy配列のデータ型が np.uint8 以外の場合には、単純に配列上の値が整数化されるため、予期しない画像が保存されることがあるので注意が必要である。
1.2. 画像の表示#
OpenCV等で読み込んだ画像を表示する場合にはMatplotlibの imshow を使うのが一般的である。
import matplotlib.pyplot as plt
plt.imshow(img_rgb)
plt.show()
ただし、Matplotlibは画像の輝度の最大値と最小値を見て、画像の画素値を自動的に正規化するので、0-255の階調で画像を表示したい場合には、 vmin と vmax を指定する必要がある。
plt.imshow(img_rgb, vmin=0, vmax=255)
plt.show()
また、グレースケールの画像を表示する場合、Matplotlibはデフォルトではカラーマップを自動的に適用してしまうので、 cmap="gray" を指定する必要がある。
plt.imshow(img_gray, cmap="gray", vmin=0, vmax=255)
plt.show()
より詳しいMatplotlibの使い方については各自インターネットや書籍等で調べること。
1.3. 画像の圧縮#
画像を圧縮して保存するには、 cv2.imwrite の第3引数に圧縮率を表すパラメータを設定すれば良い。ただし、指定すべき圧縮パラメータは画像の形式によって異なるので注意が必要である。
例えば、JPEG形式の画像の圧縮率を変化させるには、 [cv2.IMWRITE_JPEG_QUALITY, 95] のようにオプションをパラメータを設定すれば良い。この際、画像品質として指定できるパラメータは0-100の整数で、値が大きいほど高品質な画像が得られる。
cv2.imwrite("jpeg_quality_95.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 95])
PNG形式の画像の圧縮率を変化させるには、 [cv2.IMWRITE_PNG_COMPRESSION, 3] のようにオプションをパラメータを設定すれば良い。この際、PNGの圧縮率として指定できるパラメータは0-9の整数で、値が大きいほど高圧縮な画像が得られる。
cv2.imwrite("png_compression_3.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 3])
PNG形式は可逆圧縮のデータ形式であったので、圧縮率を変化させたとしても画像の品質が変化することはない。その代わりに圧縮率を上げると、画像の読み書きにかかる時間が増加する。
1.4. 色空間の変更#
OpenCVは様々な色空間への変換をサポートしており、cv2.cvtColor を用いて色変換を行うことができる。
例えば、RGB形式からグレースケール形式への色変換は以下のようにして行うことができる。OpenCVのグレースケール化は、NTSC規格に従って、RGBのチャンネルに (0.299, 0.587, 0.114) の重みをかけて加算する。
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2GRAY)
同様に、RGB形式からHSV形式への色変換は以下のようにして行うことができる。
img_hsv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV)
この際、注意すべき点は cv2.cvtColor による色変換では、画像のビット深度が変化しない、という点である。従って、上記のプログラムで得られる img_hsv の各チャンネルは8ビット符号なし整数で表されている。
しかし、HSVの各チャンネルのうち、Hは色相を表すため0-255の範囲で量子化すると計算上都合が悪い。そのため、変換後のHチャンネルは0-179の範囲で量子化されている。
このように、変換前の画像のビット深度によって変換後の画像の表現方法が変わることがあるので注意が必要である。
1.5. データ型の変更#
OpenCVに用意された多くの関数は画像が np.uint8 型 (0-255の範囲の整数) あるいは np.float32 型 (0.0-1.0の範囲の小数) で表されていることを暗に仮定している。
そのため、32bit符号付き整数 (np.int32) や 64bit浮動小数 (np.float64) などのデータ型で画像を操作すると、関数によっては予期しない挙動が生じることがある。
通常、 cv2.imread で読み込んだ画像は np.uint8 型で表されており、各色のチャネルは 0-255の範囲の整数である。他方、画像を32bit浮動小数で表す場合には、各色の範囲は0.0-1.0の範囲に正規化されることが多い。
そのため、 np.uint8 型の画像を np.float32 型に変換するには、NumPyを用いて以下の操作を行えば良い。
img_float = (img / 255.0).astype(np.float32)
逆に、 np.flaat32 型の画像を np.uint8 型に変換する際は、少しだけ注意が必要で、予め np.float32 型の画像の画素値が0.0-1.0の範囲に収まっていることを保証する必要がある。
典型的には以下のような操作を行えば良いだろう。
img_uint8 = (np.clip(img_float, 0.0, 1.0) * 255.0).astype(np.uint8)
以上のように、画像のデータ型を変換する際には、データ型に応じて、輝度の範囲が変化することに留意してほしい。
1.6. 特定の成分の取り出し#
画像を操作していると、画像の赤、緑、青などの色成分に対して個別の処理を行いたい場合がある。OpenCVで画像を読み込むと、画像のチャンネルはBGRの順に並んでいるので、赤、緑、青の成分を取り出すには、以下のようにすれば良い。
r_channel = img[:, :, 2]
g_channel = img[:, :, 1]
b_channel = img[:, :, 0]
これと同様の操作はNumPyの np.split や OpenCVの cv2.split でも行うことができる。
# NumPyを用いる場合
b_channel, g_channel, r_channel = np.split(img, 3, axis=2)
# OpenCVを用いる場合
b_channel, g_channel, r_channel = cv2.split(img)
反対に、赤、緑、青の成分を結合してカラー画像 (以下の例ではRGBの順) を作成するには、以下のようにすれば良い。
# NumPyを用いる場合
img_rgb = np.stack((r_channel, g_channel, b_channel), axis=2)
# OpenCVを用いる場合
img_rgb = cv2.merge((r_channel, g_channel, b_channel))
画像のチャネルの取り出しは頻出する操作なので、覚えておくと役に立つだろう。