【python】画像処理opencvライブラリの使い方 入門編

本ページには PR が含まれます。

この記事ではopencvライブラリで画像処理の実装方法をわかりやすく解説します。

サンプルコードをコピペしながらサクサク処理を試せますので、 ぜひ活用してみてください。


目次

opencvライブラリでできること

opencvライブラリは画像や動画に対して数学的処理を加えることで様々な画像処理を可能にするオープンソースライブラリです。

opencvライブラリで実装可能な代表的な機能は以下の通りです。

opnecvライブラリの活用例
  • フィルタ処理
  • 行列演算処理
  • オブジェクト追跡処理
  • 領域分割処理
  • 特徴点抽出処理
  • 物体認識処理
  • 機械学習処理
  • パノラマ合成処理
  • コンピューテーショナルフォトグラフィ処理
  • GUI(ウィンドウ表示、トラックバーなど)
  • カメラキャプチャ、動画ファイル処理
  • カメラキャリブレーション処理

opencvライブラリはpythonで画像処理を行うのに欠かせないライブラリと言って良いでしょう。

本記事ではopencvライブラリの基礎に重点を置いて、具体的に紹介しますのでぜひ参考にしてみてください。

ライブラリのインストール

まずはじめにpythonの実行環境にopencvライブラリをインストールしましょう。

ターミナル(mac)もしくはコマンドプロンプト(Windows)で下記を実行します。

numpyライブラリは直接的には画像処理と関係ありませんが、演算処理に必要なのでインストールします。

pip install opencv-python
pip install numpy

最終行に「Successfully installed 〜〜〜」と表示されて入ればインストール成功です。


動作確認

続いて、pythonでopencvライブラリが動作するか簡単な方法で確認しましょう。

pythonファイルで下記を入力し、実行します。

import cv2
# opencvライブラリのバージョンを確認
print(cv2.__version__)
# 出力結果
4.5.5

上記のようにバージョン情報が出力されていれば、opencvライブラリは正常に動作しています。


画像の読み込み cv2.imread()

opencvライブラリで画像処理を行うため、初めにサンプル画像を用意してその画像をpythonで読み込みます。

私の場合はこちらの右下の画像を読み込みます。

読み込む画像ファイルはPython実行ファイルと同階層もしくはそれより階層に配置してください。

opencvライブラリでは絶対パスを指定しても、別の上位ディレクトリにアクセスできません。

なんかデスクに置いてあったマウントレーニア
(画像ファイル名 : mtrainier.jpg)

opencvライブラリで画像を読み込むにはcv2.imread()メソッドを使用します。

cv2.imread(画像ファイルパス, カラースケール引数)


カラースケール引数に指定できる値と意味は以下の通りです。

意味
1 (もしくはcv2.IMREAD_COLOR)カラースケールで読み込み。透明度は無視。(デフォルト)
0 (もしくはcv2.IMREAD_GRAYSCALE)グレースケールで読み込み。
-1 (もしくはcv2.IMREAD_UNCHANGED)透明度を反映し、カラースケールで読み込み。
# -*- coding: utf-8 -*-
import cv2

# 画像の読み込み
img = cv2.imread("mtrainier.jpg", 1)
print(type(img))
# 出力結果
<class 'numpy.ndarray'>

上記のように、読み込まれた画像はnumpy.ndarray型の配列に格納されます。


画像の表示 cv2.imshow()

読み込んだ画像ファイルを表示させるにはcv2.imshow()メソッドを使用します。

cv2.imshow(表示ウィンドウのタイトル, 画像オブジェクト)

# -*- coding: utf-8 -*-
import cv2

# 画像の読み込み
img = cv2.imread("mtrainier.jpg")
# 画像を表示
cv2.imshow("Mt.rainier", img)

# キーボードが押されるまで表示
cv2.waitKey(0)
# すべての画像表示ウィンドウを破棄
cv2.destroyAllWindows()

上記を実行すると、下図のように別ウィンドウで画像が表示されます。

ウィンドウがアクティブな状態で何らかのキーボードを押すと、ウィンドウが閉じます。

cv2.imread()メソッドにおいてカラースケール引数を0, -1と指定した場合の表示はそれぞれ下図の通りです。

cv2.imread("mtrainier.jpg", 0)で読み込み
cv2.imread("mtrainier.jpg", -1)で読み込み

グレースケール(カラースケール引数0)の表示は白黒となっているのでわかりやすいでしょう。

透明度を反映した読み込み(カラースケール引数-1)は今回の画像では差があまりわからないようです。


表示状態の保持 cv2.waitKey()

画像表示のプログラムと一緒に利用されるcv2.waitKey()メソッドの役割について解説しておきます。

pythonのプログラムにおいてcv2.imshow()メソッドは一時的に画像を表示する機能しか持ちません。

そのため、ウィンドウ表示状態を保持しなければウィンドウが一瞬で閉じてしまいます。

そこで、cv2.waitKey()メソッドが役立ちます。

cv2.waitKey(待機時間[ミリ秒])

# ウィンドウ表示後5000ミリ秒(=5秒)保持
cv2.waitKey(5000)

のようにして、画像がウィンドウに表示されてから何ミリ秒保持するよう指定することができます。

待機時間[ミリ秒]0以下の値を指定すれば、キーボードが押されるまで永続的に待機し続けさせられます。

また、cv2.waitKey()メソッドの戻り値は押されたキーのASCIIコード(10進数表記)となります。

キーボードのASCIIコード

# キーボードが押されるまでウィンドウ保持
key = cv2.waitKey(0)
### キーボードの「A」を押した場合
print(key)
# 出力結果
97

ウィンドウの破棄 cv2.destroyAllWindows()

ウィンドウの画面保持状態が終了した後、ウィンドウ画面は自然と閉じられますが、

ウィンドウは閉じていてもアクティブ状態が解除されない場合があるため、一元的に

cv2.destroyAllwindows()

ですべての画像表示ウィンドウを破棄するのが通例です。

基本的にcv2.waitKey()メソッドの直後に記載します。


画像に描画

続いて、読み込んだ画像に図形やテキストを描画する方法を解説していきます。

opencvライブラリには様々な描画メソッドが用意されています。

円を描画

画像に円を描画するには、cv2.circle()メソッドを使用します。

cv2.circle(img, center, radius, color, thickness, lineType)

のようにそれぞれ引数を指定して円を描画できます。

引数とその意味については下記の通りです。

引数名意味指定する値の例
img画像オブジェクトnumpy.ndarray型の画像
center円の中心座標(500, 200)などのタプル型
radius円の半径2, 13などのint型
color円の色(255, 100, 0)などのbgrカラータプル
※rgbではなくbgrの順であることに注意
thickness線の太さ100, 30, -1などのint型
(0未満の値を指定すると円を塗りつぶし)
lineType線の種類cv2.LINE_4, cv2.LINE_8(デフォルト),
cv2.LINE_AA(アンチエイリアス : 線を滑らかにする処理)
# -*- coding: utf-8 -*-
import cv2

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

# さまざまな円を描画
img = cv2.circle(img, center=(1500,1500), radius=1000, color=(255, 0, 132), thickness=50, lineType=cv2.LINE_AA)
img = cv2.circle(img, center=(2600,1800), radius=50, color=(0, 183, 255), thickness=10)
img = cv2.circle(img, center=(400,2700), radius=2000, color=(0, 106, 255), thickness=25)
img_circle = cv2.circle(img, center=(500,300), radius=300, color=(77, 255, 0), thickness=-1, lineType=cv2.LINE_4)

# 画像を表示
cv2.imshow("Mt.rainier", img_circle)
# キーボードが押されるまで表示
cv2.waitKey(0)
# キーボードが押されたらウィンドウを閉じる
cv2.destroyAllWindows()

このように読み込んだ画像に対してさまざまな円を描画することができます。

中心座標や半径は画像サイズによって適切な値に設定してください。


直線を描画

画像に直線を描画するには、cv2.line()メソッドを使用します。

cv2.line(img, pt1, pt2, color, thickness, lineType)

のようにそれぞれ引数を指定して直線を描画できます。


引数とその意味については下記の通りです。

引数名意味指定する値の例
img画像オブジェクトnumpy.ndarray型の画像
pt1線分の第1端点の座標(500, 200)などのタプル型
pt2線分の第2端点の座標(100, 750)などのタプル型
color線の色(255, 100, 0)などのbgrカラータプル
※rgbではなくbgrの順であることに注意
thickness線の太さ100, 30などのint型
lineType線の種類cv2.LINE_4, cv2.LINE_8(デフォルト),
cv2.LINE_AA(アンチエイリアス : 線を滑らかにする処理)
# -*- coding: utf-8 -*-
import cv2

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

# さまざまな線を描画
img = cv2.line(img, pt1=(1500,1500), pt2=(100,2800), color=(255, 0, 132), thickness=150, lineType=cv2.LINE_AA)
img = cv2.line(img, pt1=(2600,100), pt2=(3000,1000), color=(0, 183, 255), thickness=100)
img = cv2.line(img, pt1=(400,2700), pt2=(100,0), color=(0, 106, 255), thickness=125)
img_line = cv2.line(img, pt1=(500,300), pt2=(1500,300), color=(77, 255, 0), thickness=500, lineType=cv2.LINE_4)

# 画像を表示
cv2.imshow("Mt.rainier", img_line)
# キーボードが押されるまで表示
cv2.waitKey(0)
# キーボードが押されたらウィンドウを閉じる
cv2.destroyAllWindows()

このように読み込んだ画像にさまざまな線を描画することができます。


テキストを描画

画像にテキストを描画するには、cv2.putText()メソッドを使用します。

cv2.putText(img, text, org, fonFace, fontScale, color, thickness, lineType, bottomLeftOrigin)

のようにそれぞれ引数を指定してテキストを描画できます。


引数とその意味については下記の通りです。

引数名意味指定する値の例
img画像オブジェクトnumpy.ndarray型の画像
text描画する文字列"Hello World!!"などのstr型
org文字列の左下隅の座標(100, 750)などのタプル型
fontFace文字のフォントcv2.FONT_HERSHEY_SIMPLEX, cv2.FONT_HERSHEY_PLAIN,
cv2.FONT_HERSHEY_DUPLEX, cv2.FONT_HERSHEY_COMPLEX,
cv2.FONT_HERSHEY_TRIPLEX, cv2.FONT_HERSHEY_COMPLEX_SMALL,
cv2.FONT_SCRIPT_SIMPLEX, cv2.FONT_SCRIPT_COMPLEX,
cv2.FONT_ITALIC
color文字の色(255, 100, 0)などのbgrカラータプル
※rgbではなくbgrの順であることに注意
thickness文字の太さ10, 30などのint型
lineType線の種類cv2.LINE_4, cv2.LINE_8(デフォルト),
cv2.LINE_AA(アンチエイリアス : 線を滑らかにする処理)
bottomLeftOrigin画像データの原点位置True(画像データの左下原点)
False(画像データの左上原点、デフォルト)
# -*- coding: utf-8 -*-
import cv2

# 画像の読み込み
img = cv2.imread("mtrainier.jpg")
img = cv2.putText(img, text="Hello World!!", org=(600,2000), fontFace=cv2.FONT_HERSHEY_SIMPLEX, color=(255, 0, 132), fontScale=10, thickness=10, lineType=cv2.LINE_AA)
img = cv2.putText(img, text="あいうえお", org=(500,1500), fontFace=cv2.FONT_HERSHEY_PLAIN, fontScale=10, color=(0, 183, 255), thickness=10)
img = cv2.putText(img, text="ABCDE", org=(400,1000), fontFace=cv2.FONT_HERSHEY_DUPLEX, fontScale=25, color=(0, 106, 255), thickness=15)
img_text = cv2.putText(img, text="Let's start opencv!!", org=(300,500), fontFace=cv2.FONT_HERSHEY_TRIPLEX, fontScale=5, color=(77, 255, 0), thickness=10, lineType=cv2.LINE_4)
# 画像を表示
cv2.imshow("Mt.rainier", img_text)
# キーボードが押されるまで表示
cv2.waitKey(0)
# キーボードが押されたらウィンドウを閉じる
cv2.destroyAllWindows()

上図のように、読み込んだ画像上にテキストを挿入することができます。

しかしながら、日本語がすべて「???????」となってしまっていることがわかります。

opencvライブラリは日本語フォントに対応していません。

opencvで読み込んだ画像に日本語を挿入するにはひと工夫必要です。


日本語を描画する方法

opencvライブラリでは残念ながら日本語を表示させられません。

そこで、別の画像処理ライブラリを利用して力技で日本語を表示させます。

pillowライブラリという別の画像処理ライブラリを使用します。まず、pillowライブラリをインストールしましょう。

pip install pillow

日本語表示するために新たに関数を定義します。

import numpy as np
import cv2
import os
from PIL import Image, ImageDraw, ImageFont

def pillow_opencv(img_pillow):
    img_opencv_rgb = np.array(img_pillow, dtype=np.uint8)
    img_opencv_bgr = np.array(img_opencv_rgb)[:, :, ::-1]
    cv2.imwrite("draft.jpg", img_opencv_bgr)
    img = cv2.imread("draft.jpg")
    os.remove("draft.jpg")
    return img

def opencv_pillow(img_opencv):
    img_opencv_rgb = img_opencv[:, :, ::-1]
    img_pillow = Image.fromarray(img_opencv_rgb)
    return img_pillow

def cv2_putJapanese(img, text, org, fontFace, fontScale, color):
    x, y = org
    b, g, r = color
    colorRGB = (r, g, b)
    img_pillow = opencv_pillow(img)
    draw = ImageDraw.Draw(img_pillow)
    font_pillow = ImageFont.truetype(font=fontFace, size=fontScale)
    _, h = draw.textsize(text, font=font_pillow)
    draw.text(xy=(x,y-h), text=text, fill=colorRGB, font=font_pillow)
    img_opencv = pillow_opencv(img_pillow)
    return img_opencv

この関数をプログラム冒頭にコピペすれば、cv2_putJapanese()関数を呼び出して日本語を描画可能です。

cv2.putText(img, text, org, fontFace, fontScale, color)

やや煩雑ですが、opencvライブラリで日本語テキストを描画するには、残念ながらこれが最善策でしょう。

日本語描画の例は以下のサンプルコードの通りです。

# -*- coding: utf-8 -*-
import cv2
import os
import numpy as np
from PIL import Image, ImageDraw, ImageFont

def pillow_opencv(img_pillow):
    img_opencv_rgb = np.array(img_pillow, dtype=np.uint8)
    img_opencv_bgr = np.array(img_opencv_rgb)[:, :, ::-1]
    cv2.imwrite("draft.jpg", img_opencv_bgr)
    img = cv2.imread("draft.jpg")
    os.remove("draft.jpg")
    return img

def opencv_pillow(img_opencv):
    img_opencv_rgb = img_opencv[:, :, ::-1]
    img_pillow = Image.fromarray(img_opencv_rgb)
    return img_pillow

def cv2_putJapanese(img, text, org, fontFace, fontScale, color):
    x, y = org
    b, g, r = color
    colorRGB = (r, g, b)
    img_pillow = opencv_pillow(img)
    draw = ImageDraw.Draw(img_pillow)
    font_pillow = ImageFont.truetype(font=fontFace, size=fontScale)
    _, h = draw.textsize(text, font=font_pillow)
    draw.text(xy=(x,y-h), text=text, fill=colorRGB, font=font_pillow)
    img_opencv = pillow_opencv(img_pillow)
    return img_opencv

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

img = cv2.putText(img, text="Hello World!!", org=(600,2000), fontFace=cv2.FONT_HERSHEY_SIMPLEX, color=(255,0,132), fontScale=10, thickness=10, lineType=cv2.LINE_AA)
img = cv2_putJapanese(img, text="あいうえお", org=(500,1500), fontFace="/Users/「PCのユーザ名」/Library/Fonts/ipaexg.ttf", fontScale=500, color=(0,0,255))
img = cv2.putText(img, text="ABCDE", org=(400,1000), fontFace=cv2.FONT_HERSHEY_DUPLEX, fontScale=25, color=(0,106,255), thickness=15)
img_text = cv2_putJapanese(img, text="日本語描画", org=(300,500), fontFace="/Users/「PCのユーザ名」/Library/Fonts/ipaexg.ttf", fontScale=500, color=(0, 213, 255))

# 画像を表示
cv2.imshow("Mt.rainier", img_text)
# キーボードが押されるまで表示
cv2.waitKey(0)
# キーボードが押されたらウィンドウを閉じる
cv2.destroyAllWindows()

日本語が正しく描画されていることがわかります。

なお、引数fontFaceにはPCに保存されている日本語フォントファイル(.ttf)のパスを指定します。

macにおけるパスのコピー方法は以下の通りです。

IPAexゴシックフォントのパスを Finderで表示
フォントファイルのパスをコピー

日本語フォント「IPAexゴシック」のフォントがない方はこちらを参考にしてダウンロードできます。

画像の書き出し・保存 cv2.imwrite()

作成した画像を書き出し・保存するには、cv2.imwrite()メソッドを使用します。

cv2.imwrite(filename, img)

のようにそれぞれ引数を指定して画像を書き出し・保存できます。

# -*- coding: utf-8 -*-
import cv2

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

# さまざまな円を描画
img = cv2.circle(img, center=(1500,1500), radius=1000, color=(255, 0, 132), thickness=50, lineType=cv2.LINE_AA)
img = cv2.circle(img, center=(2600,1800), radius=50, color=(0, 183, 255), thickness=10)
img = cv2.circle(img, center=(400,2700), radius=2000, color=(0, 106, 255), thickness=25)
img_circle = cv2.circle(img, center=(500,300), radius=300, color=(77, 255, 0), thickness=-1, lineType=cv2.LINE_4)

# 画像を表示
cv2.imshow("Mt.rainier", img_circle)
# キーボードが押されるまで表示
cv2.waitKey(0)
# キーボードが押されたらウィンドウを閉じる
cv2.destroyAllWindows()

# 画像を書き出し・保存
cv2.imwrite("mtrainier_insertCircle.jpg", img_circle)

同一ディレクトリに「mtrainier_insertCircle.jpg」の画像ファイルが保存されています。


まとめ

今回はopencvライブラリの基礎的な使い方を具体的に紹介しました。

他にもpythonの役立つ情報を投稿しておりますので、ぜひ参考にしてみてください。

よかったらシェアしてね!
目次