はじめに
OpenCVでは、さまざまな基本的な図形描画の他に、テキストを描画することもできます。cv2.putText
関数は文字を描画する関数です。
この関数の利用は、キャプションとしての文字、物体検出の結果情報、注釈付け、合成、GUI作成など、円を描画するシーンは多岐にわたります。
では、OpenCVでテキストを描画するcv2.putText
関数について、解説していきましょう。
テキストを描画
テキスト描画の使用場面
cv2.putText
関数は、以下のような場面で使用されています。
- 物体検出結果の可視化:
物体検出アルゴリズムで検出された物体の周りに、その物体の名前や確信度をテキストで書き込むことができます。これにより、検出結果を視覚的に確認しやすくなります。 - 警告やエラーメッセージの表示:
異常が検出された際にその旨を画面上にテキストで表示することができます。例えば「侵入者を検出しました」といったメッセージを映像に重ねて表示できます。 - デバッグ情報の表示:
コンピュータビジョンのアプリケーションを開発する際、各フレームの処理時間や特定の変数の値などをリアルタイムで画面上に表示し、デバッグに役立てることができます。
cv2.putText
関数は画像やビデオに付加情報を視覚的に付与する場面で幅広く使われています。フォントの種類やサイズ、色、位置などをカスタマイズすることで、目的に合わせて効果的な表示ができます。
cv2.putText関数
cv2.putText
関数の引数と戻り値は下の通りです。
cv2.putText(入力画像, text, org, fontFace, fontScale, color[, thickness[, lineType[,bottomLeftOrigin]]])
引数
名称 | 説明 |
---|---|
入力画像(必須) | テキストを描画する画像データ |
text(必須) | 描画するテキスト |
org(必須) | テキストの左下の座標。(x座標, y座標)の並びのタプル |
fontFace(必須) | フォントの種類の指定。HersheyFontsを参照。 |
fontScale(必須) | フォントサイズのスケール係数(float) |
color(必須) | テキストの色 (BGR表記) |
thickness(オプション) | テキストの線の太さ(デフォルト:1) |
lineType(オプション) | 線の種類。LineTypesで定義される値を設定します。(デフォルト:cv2.LINE_8) |
bottomLeftOrigin(オプション) | 座標系の原点がどこにあるかを指定(デフォルト:False、画像の左上が原点) |
OpenCVには、組み込みフォントであるHersheyFonts
が用意されています。HersheyFonts
はベクターフォントで、リサイズやスムージングが可能です。主なHersheyFonts
は以下の通りです。
フォントの種類 | 特徴 |
---|---|
cv2.FONT_HERSHEY_SIMPLEX | 標準的なゴシック体 フォント |
cv2.FONT_HERSHEY_PLAIN | 小さいサイズのゴシック体 フォント |
cv2.FONT_HERSHEY_DUPLEX | 通常サイズのゴシック体 フォント(cv2.FONT_HERSHEY_SIMPLEX より太い) |
cv2.FONT_HERSHEY_COMPLEX | 通常サイズのスクリプト体 フォント |
cv2.FONT_HERSHEY_TRIPLEX | 通常サイズのスクリプト体 フォント(cv2.FONT_HERSHEY_COMPLEX より太い) |
cv2.FONT_HERSHEY_COMPLEX_SMALL | 小さいサイズのスクリプト体 フォント |
cv2.FONT_HERSHEY_SCRIPT_SIMPLEX | 手書き風 フォント |
cv2.FONT_HERSHEY_SCRIPT_COMPLEX | 手書き風 フォント(cv2.FONT_HERSHEY_SCRIPT_SIMPLEX より太く、デザインが異なる) |
引数のlineType
はLineTypesに示す3種類のいずれかとなります。デフォルトはcv2.LINE_8
です。
線の種類 | 説明 |
---|---|
cv2.LINE_4 | 4 連結 |
cv2.LINE_8 | 8 連結(デフォルト) |
cv2.LINE_AA | アンチエイリアス処理された線 |
戻り値
入力画像にテキストが描画された状態の画像データが返されます。
使い方
以下にサンプルコードを示します。
import cv2 import numpy as np # 空の画像を作成 image = np.zeros((650, 1000, 3), dtype=np.uint8) # 使用するフォントのリスト fonts = [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_HERSHEY_SCRIPT_SIMPLEX, cv2.FONT_HERSHEY_SCRIPT_COMPLEX] # フォントの名前 font_names = ["FONT_HERSHEY_SIMPLEX", "FONT_HERSHEY_PLAIN", "FONT_HERSHEY_DUPLEX", "FONT_HERSHEY_COMPLEX", "FONT_HERSHEY_TRIPLEX", "FONT_HERSHEY_COMPLEX_SMALL", "FONT_HERSHEY_SCRIPT_SIMPLEX", "FONT_HERSHEY_SCRIPT_COMPLEX"] # 文字色の配列 text_colors = [(0, 0, 255), # 赤 (0, 128, 255), # オレンジ (0, 255, 255), # 黄色 (0, 255, 0), # 緑 (255, 0, 0), # 青 (255, 0, 128), # 紫 (255, 0, 255), # ピンク (255, 255, 255)] # 白 y = 50 # 最初のテキストの垂直位置 font_scale = 1.5 # フォントのスケール thickness = 2 # 線の太さ # 各フォントについてテキストを描画 for i, font in enumerate(fonts): text = font_names[i] text_size, _ = cv2.getTextSize(text, font, font_scale, thickness) x = 50 # テキストの水平位置 color = text_colors[i % len(text_colors)] # 文字色を循環させる cv2.putText(image, text, (x, y), font, font_scale, color, thickness, cv2.LINE_AA) y += text_size[1] + 50 # 次のテキストの垂直位置を計算 # 画像を表示 cv2.imshow("cv2.putText: codevace.com", image) cv2.waitKey(0) cv2.destroyAllWindows()
このコードでは、まず650x1000の真っ黒の画像を作成します。
次に、HersheyFonts
のリストと、それぞれのフォント名のリストを定義します。
その後、ループを使って各フォントについて、そのフォント名のテキストを画像に描画しています。
各テキストの描画位置は、cv2.getTextSize
関数を使ってテキストの実際のサイズを取得し、前のテキストの位置に基づいて配置するためのx、y座標を計算します。
最後に、cv2.imshow
関数を使って画像を表示し、キーが押されるまで待機します。
実行すると、以下のような画像が表示されます。
すこし高度なテキストの描画方法
透過テキスト
背景が透過するように、テキストを描画することもできます。cv2.addWeighted
関数を使った、背景が透過したテキストを描画する方法を紹介します。
以下がサンプルコードをです。
import cv2 import numpy as np # 背景画像を読み込む background_image = cv2.imread("image.jpg") # 背景画像と同じサイズの空の画像を作成 text_image = np.zeros_like(background_image) # 描画するフォントを設定する font = cv2.FONT_HERSHEY_DUPLEX font_scale = 3.0 font_color = (0, 255, 0) # RGB値 (緑) thickness = 10 # 線の太さ # テキストを描画する text = 'Hello, OpenCV!' text_size, _ = cv2.getTextSize(text, font, font_scale, thickness) text_x = (text_image.shape[1] - text_size[0]) / 2 # 画像の中央に配置 text_y = (text_image.shape[0] + text_size[1]) / 2 # 画像の中央に配置 cv2.putText(text_image, text, (int(text_x), int(text_y)), font, font_scale, font_color, thickness, cv2.FILLED) # 画像を合成する alpha = 0.5 # テキスト画像の不透明度 cv2.addWeighted(background_image, 1, text_image, alpha, 0, dst=background_image) # 画像を表示 cv2.imshow("Transparent Text: codevace.com", background_image) cv2.waitKey(0) cv2.destroyAllWindows()
手順は以下の通りです:
- 背景画像を読み込みます。
- テキストレイヤー用の空画像を作成します。
- 空画像にテキストを描画します。
cv2.addWeighted
関数で背景画像とテキストレイヤーを合成します。第4引数がテキストレイヤーの不透明度を表します。- 合成した画像を表示します。
cv2.addWeighted
関数の呼び出し部分がポイントです:
cv2.addWeighted(background_image, 1, text_image, alpha, 0, dst=background_image)
この関数は、background_image
+ alpha*text_image
の計算を各ピクセルで行い、結果をbackground_image
に上書きします。alpha
を0.5とすると、背景画像に50%透過のテキスト画像が重ね合わされた画像になります。
実行すると、背景画像の上に半透明のテキストが重ねられた画像が表示されます。alpha
値を調整することで、テキストの透過度を変更できます。
このようにして、cv2.addWeighted
関数を使うと比較的簡単に、背景が透過したテキストを描画することができます。
cv2.addWeighted
関数についてはこちらの記事で紹介しています。
入力画像として、下の画像を使用しました。
アウトラインテキスト
テキストにアウトラインを付けることもできます。これには2回cv2.putText()
関数を呼び出す必要があります。1回目は背景色でテキストを描画し、2回目は文字色でわずかに線の太さを太くしてテキストを描画します。
import cv2 import numpy as np # 空の画像を作成 image = np.zeros((350, 1000, 3), dtype=np.uint8) # 描画するフォントを設定する font = cv2.FONT_HERSHEY_DUPLEX # フォントの種類 text = 'Hello, OpenCV!' # 描画するテキスト font_scale = 3.5 # フォントの大きさ font_color = (0, 255, 0) # ベース テキスト カラー:緑 thickness = 10 # ベースのテキストの線の太さ outline_color = (0, 0, 255) # アウトライン テキスト カラー:赤 outline_thickness = thickness * 2 # アウトラインテキストの線の太さ # テキストを描画する text_size, _ = cv2.getTextSize(text, font, font_scale, thickness) text_x = (image.shape[1] - text_size[0]) / 2 # 画像の中央に配置 text_y = (image.shape[0] + text_size[1]) / 2 # 画像の中央に配置 # 先にアウトラインのテキストを描画 cv2.putText(image, text, (int(text_x), int(text_y)), font, font_scale, outline_color, outline_thickness, cv2.LINE_AA) cv2.putText(image, text, (int(text_x), int(text_y)), font, font_scale, font_color, thickness, cv2.LINE_AA) # 画像を表示 cv2.imshow("Outline Text: codevace.com", image) cv2.waitKey(0) cv2.destroyAllWindows()
テキストの線の太さをわずかに変えることで、1回目の太い線の内側にベースのテキストが描画されるようになり、アウトラインテキストの効果が出ます。アウトラインの量はoutline_thickness
の値で調整できます。
つまり、2回のcv2.putText()
呼び出しを組み合わせ、テキストの線の太さを変えることで擬似的なアウトラインテキストを実現します。
おわりに
今回はOpenCVを使って画像にテキストを描画する基本的な方法から、すこし高度なテクニックまでご紹介しました。
シンプルなcv2.putText()
関数一つで、画像に情報を視覚的に付与することができます。
タイトルやキャプション、アノテーションなど、用途は多岐に渡ります。フォントの種類、サイズ、色、配置など、様々なオプションを調整することで、テキストのスタイルもカスタマイズ可能です。
さらに、アンチエイリアシングの適用や、外部フォントの利用、合成なども可能です。
また、OpenCVのHersheyFonts
はシンプルでありながら多様なので、多くのシーンで活用できますが、欧文フォントであることが短所と言えます。
日本語の描画は外部フォントを使う方法で実現できます。
この方法は別の記事で紹介したいと思います。
ご質問や取り上げて欲しい内容などがありましたら、コメントをお願いします。
最後までご覧いただきありがとうございました。
参考リンク
OpenCV: putText
Draws a text string.
■(広告)OpenCVの参考書としてどうぞ!■