OpenCV – 長方形、円、線、ポリゴンなどを描画する方法

目次
- 1. 概要
- 2. 関数一覧
- 3. 描画系関数の共通仕様
- 4. テキストを描画する – cv2.putText
- 5. テキストの大きさを取得する – cv2.getTextSize
- 6. 長方形を描画する – cv2.rectangle
- 7. 円を描画する – cv2.circle
- 8. 楕円を描画する – cv2.ellipse
- 9. 輪郭を描画する – cv2.drawContours
- 10. マーカーを描画する – cv2.drawMarker
- 11. 凸なポリゴンを描画する – cv2.fillConvexPoly
- 12. ポリゴンを描画する – cv2.fillPoly
- 13. ポリゴンの輪郭線を描画する – cv2.polylines
- 14. 線分を描画する – cv2.line
- 15. 矢印を描画する – cv2.arrowedLine
概要
OpenCV に画像に図形や文字を描画する関数を整理しました。
Advertisement
関数一覧
図形 | 関数 |
---|---|
テキスト | cv2.putText |
長方形 | cv2.rectangle |
円 | cv2.circle |
楕円 | cv2.ellipse |
輪郭 | cv2.drawContours |
マーカー | cv2.drawMarker |
凸なポリゴン | cv2.fillConvexPoly |
ポリゴン | cv2.fillPoly |
ポリゴンの輪郭線 | cv2.polylines |
線分 | cv2.line |
矢印 | cv2.arrowedLine |
描画系関数の共通仕様
- 色は
color
で指定します。1チャンネル画像の場合は int、3チャンネル画像の場合は int の tuple で指定します。(例:color=(255, 0, 0)
) - 線の太さは
thickness
で指定します。負の値を指定した場合は塗りつぶしになります。 - 描画は引数に渡した配列を直接変更します。
- 点の座標や大きさは float ではなく、int で指定します。
テキストを描画する – cv2.putText
注意点として、日本語などの Ascii 文字以外は描画できないため、そのような文字を描画したい場合は Pillow を使います。
lineType=cv2.LINE_AA
を指定すると、アンチエイリアスが有効になり、文字のジャギーが軽減します。
img = cv2.putText(img, text, org, fontFace, fontScale,
color[, thickness[, lineType[, bottomLeftOrigin]]])
引数
名前 | 型 | デフォルト値 |
---|---|---|
img | ndarray | |
入力画像 | ||
text | str | |
文字列 | ||
org | tuple of 2 ints | |
描画位置 (baseline の始点) | ||
fontFace | HersheyFonts | |
フォントの種類 | ||
fontScale | float | |
フォントの倍率 | ||
color | int / tuple of ints | |
色 | ||
thickness | int | 1 |
文字の太さ | ||
line_type | LineTypes | cv2.LINE_8 |
線の描画方法 | ||
bottomLeftOrigin | bool | False |
True の場合、左下を原点として扱う |
返り値
名前 | 説明 | ||
---|---|---|---|
img | 出力画像 |
In [1]:
import cv2
import numpy as np
from IPython.display import Image, display
def imshow(img):
"""ndarray 配列をインラインで Notebook 上に表示する。
"""
ret, encoded = cv2.imencode(".jpg", img)
display(Image(encoded))
img = np.zeros((100, 300, 3), dtype=np.uint8)
cv2.putText(
img,
"Hello World",
(0, 90),
fontFace=cv2.FONT_HERSHEY_SIMPLEX,
fontScale=1.0,
color=(255, 255, 255),
thickness=2,
lineType=cv2.LINE_AA,
)
imshow(img)

Advertisement
テキストの大きさを取得する – cv2.getTextSize
retval, baseLine = cv2.getTextSize(text, fontFace, fontScale, thickness)
引数
名前 | 型 | デフォルト値 |
---|---|---|
text | str | |
文字列 | ||
fontFace | HersheyFonts | |
フォントの種類 | ||
fontScale | float | |
フォントの倍率 | ||
thickness | int | 1 |
文字の太さ |
返り値
名前 | 説明 | ||
---|---|---|---|
(w, h) | 文字の大きさ | ||
baseLine | ベースラインまでの距離 |
引数の解釈は以下のようになっています。
文字を囲む矩形とベースラインを描画する例を紹介します。
In [2]:
img = np.zeros((100, 300, 3), dtype=np.uint8)
text = "Hello World" # 描画する文字
fontface = cv2.FONT_HERSHEY_SIMPLEX # フォントの種類
fontscale = 1.0 # 文字のスケール
thickness = 2 # 文字の太さ
x, y = 50, 50 # ベースラインの始点
# 文字列を描画した際の大きさを取得する。
(w, h), baseline = cv2.getTextSize(text, fontface, fontscale, thickness)
print(f"size: ({w}, {h}), baseline: {baseline}")
# 文字を囲む矩形を描画する。
cv2.rectangle(img, (x, y - h), (x + w, y + baseline), (0, 0, 255), thickness)
# ベースラインを描画する。
cv2.line(img, (x, y), (x + w, y), (0, 255, 255), thickness)
# 文字列を描画する。
cv2.putText(img, text, (x, y), fontface, fontscale, (255, 255, 255), thickness)
imshow(img)
size: (176, 22), baseline: 10
長方形を描画する – cv2.rectangle
img = cv2.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]])
引数
名前 | 型 | デフォルト値 |
---|---|---|
img | ndarray | |
入力画像 | ||
pt1 | tuple of 2 ints | |
長方形の左上の点 | ||
pt2 | tuple of 2 ints | |
長方形の右下の点 | ||
color | int / tuple of ints | |
色 | ||
thickness | int | 1 |
線の太さ。負の値の場合は塗りつぶし。 | ||
line_type | LineTypes | cv2.LINE_8 |
線の描画方法 | ||
shift | int | 0 |
正の値の場合、座標を 1 / shift 倍にスケールする |
返り値
名前 | 説明 | ||
---|---|---|---|
img | 出力画像 |
In [3]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
cv2.rectangle(img, (50, 50), (250, 250), color=(255, 0, 0), thickness=2)
imshow(img)
In [4]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
cv2.rectangle(img, (50, 50), (250, 250), color=(255, 0, 0), thickness=-1)
imshow(img)
円を描画する – cv2.circle
img = cv2.circle(img, center, radius, color[, thickness[, lineType[, shift]]])
引数
名前 | 型 | デフォルト値 |
---|---|---|
img | ndarray | |
入力画像 | ||
center | tuple of 2 ints | |
円の中心 | ||
radius | int | |
円の半径 | ||
color | int / tuple of ints | |
色 | ||
thickness | int | 1 |
線の太さ。負の値の場合は塗りつぶし。 | ||
line_type | LineTypes | cv2.LINE_8 |
線の描画方法 | ||
shift | int | 0 |
正の値の場合、座標を 1 / shift 倍にスケールする |
返り値
名前 | 説明 | ||
---|---|---|---|
img | 出力画像 |
In [5]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
# 塗りつぶさない円
cv2.circle(img, (150, 150), 100, color=(255, 0, 0), thickness=2)
imshow(img)
In [6]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
# 塗りつぶした円
cv2.circle(img, (150, 150), 100, color=(255, 0, 0), thickness=-1)
imshow(img)
Advertisement
楕円を描画する – cv2.ellipse
img = cv2.ellipse(
img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]])
引数
名前 | 型 | デフォルト値 |
---|---|---|
img | ndarray | |
入力画像 | ||
center | tuple of 2 ints | |
楕円の中心 | ||
axes | tuple of 2 ints | |
楕円の長径、短径 | ||
angle | float | |
楕円の回転角度 | ||
startAngle | float | |
円弧の開始角度 | ||
endAngle | float | |
円弧の終了角度 | ||
color | int / tuple of ints | |
色 | ||
thickness | int | 1 |
線の太さ。負の値の場合は塗りつぶし。 | ||
line_type | LineTypes | cv2.LINE_8 |
線の描画方法 | ||
shift | int | 0 |
正の値の場合、座標を 1 / shift 倍にスケールする |
返り値
名前 | 説明 | ||
---|---|---|---|
img | 出力画像 |
楕円を描画する
In [7]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
cv2.ellipse(
img,
(150, 150),
(50, 70),
angle=45,
startAngle=0,
endAngle=360,
color=(255, 0, 0),
thickness=2,
)
imshow(img)
In [8]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
cv2.ellipse(
img,
(150, 150),
(50, 70),
angle=45,
startAngle=0,
endAngle=360,
color=(255, 0, 0),
thickness=-1,
)
imshow(img)
円弧を描画する
In [9]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
cv2.ellipse(
img,
(150, 150),
(50, 70),
angle=45,
startAngle=0,
endAngle=100,
color=(255, 0, 0),
thickness=2,
)
imshow(img)
In [10]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
cv2.ellipse(
img,
(150, 150),
(50, 70),
angle=45,
startAngle=0,
endAngle=100,
color=(255, 0, 0),
thickness=-1,
)
imshow(img)
Advertisement
輪郭を描画する – cv2.drawContours
image = cv2.drawContours(image, contours, contourIdx,
color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])
引数
名前 | 型 | デフォルト値 |
---|---|---|
image | ndarray | |
入力画像 | ||
contours | list of ndarrays | |
輪郭の一覧 | ||
contourIdx | int | |
輪郭一覧のうち、描画する輪郭のインデックス。すべての輪郭を描画する場合は負の値を指定する。 | ||
color | int / tuple of ints | |
色 | ||
thickness | int | 1 |
線の太さ。負の値の場合は塗りつぶし。 | ||
line_type | LineTypes | cv2.LINE_8 |
線の描画方法 | ||
hierarchy | ndarray | None |
輪郭の階層構造。maxLevel を指定する場合に渡す。 | ||
maxLevel | int | int の最大値 |
階層の深さいくつまで描画するか * 0の場合は contourIdx で指定した輪郭のみ描画する * 1以上の場合は、指定した深さの輪郭まで描画する | ||
offset | tuple of 2 ints | (0, 0) |
オフセット |
返り値
名前 | 説明 | ||
---|---|---|---|
image | 出力画像 |
すべての輪郭を描画する
In [11]:
# 画像を読み込む。
img = cv2.imread("sample1.jpg")
# グレースケールに変換する。
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2値化する。
ret, bin_img = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 輪郭抽出する。
contours, hierarchy = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# すべての輪郭を描画する。
dst = cv2.drawContours(img.copy(), contours, -1, color=(0, 255, 0), thickness=3)
imshow(dst)

In [12]:
# 塗りつぶしてすべての輪郭を描画する。
dst = cv2.drawContours(img.copy(), contours, -1, color=(0, 255, 0), thickness=-1)
imshow(dst)

指定した輪郭を描画する
In [13]:
# 指定した輪郭を描画する。
dst = cv2.drawContours(img.copy(), contours, 2, color=(0, 255, 0), thickness=2)
imshow(dst)

In [14]:
# 塗りつぶして指定した輪郭を描画する。
dst = cv2.drawContours(img.copy(), contours, 2, color=(0, 255, 0), thickness=2)
imshow(dst)

Advertisement
単一の輪郭を描画する
単一の輪郭を描画するには、要素が1つのリストにします。
In [15]:
cnt = contours[0]
dst = cv2.drawContours(img.copy(), [cnt], -1, color=(0, 255, 0), thickness=2)
imshow(dst)

マーカーを描画する – cv2.drawMarker
img = cv2.drawMarker(
img, position, color[, markerType[, markerSize[, thickness[, line_type]]]])
引数
名前 | 型 | デフォルト値 |
---|---|---|
img | ndarray | |
入力画像 | ||
position | tuple of 2 ints | |
位置 | ||
color | int / tuple of ints | |
色 | ||
markerType | tuple of 2 ints | |
位置 | ||
markerType | MarkerTypes | cv2.MARKER_CROSS |
マーカーの種類 | ||
markerSize | int | 20 |
マーカーの大きさ | ||
thickness | int | 1 |
線の太さ。負の値の場合は塗りつぶし。 | ||
line_type | LineTypes | cv2.LINE_8 |
線の描画方法 |
返り値
名前 | 説明 | ||
---|---|---|---|
img | 出力画像 |
In [16]:
img = np.zeros((100, 100, 3), dtype=np.uint8)
cv2.drawMarker(
img, (50, 50), color=(255, 0, 0), markerType=cv2.MARKER_TILTED_CROSS, thickness=2
)
imshow(img)
In [17]:
from matplotlib import pyplot as plt
markers = [
"cv2.MARKER_CROSS",
"cv2.MARKER_TILTED_CROSS",
"cv2.MARKER_STAR",
"cv2.MARKER_DIAMOND",
"cv2.MARKER_SQUARE",
"cv2.MARKER_TRIANGLE_UP",
"cv2.MARKER_TRIANGLE_DOWN",
]
fig = plt.figure(figsize=(8, 8), facecolor="w")
for i, marker in enumerate(markers, 1):
img = np.zeros((100, 100, 3), dtype=np.uint8)
cv2.drawMarker(
img, (50, 50), color=(255, 0, 0), markerType=eval(marker), thickness=2
)
ax = fig.add_subplot(3, 3, i)
ax.set_title(marker)
ax.imshow(img[..., ::-1])
ax.set_axis_off()
plt.show()

凸なポリゴンを描画する – cv2.fillConvexPoly
img = cv2.fillConvexPoly(img, points, color[, lineType[, shift]])
引数
名前 | 型 | デフォルト値 |
---|---|---|
img | ndarray | |
入力画像 | ||
points | ndarray | |
点の一覧 | ||
color | int / tuple of ints | |
色 | ||
line_type | LineTypes | cv2.LINE_8 |
線の描画方法 | ||
shift | int | 0 |
正の値の場合、座標を 1 / shift 倍にスケールする |
返り値
名前 | 説明 | ||
---|---|---|---|
img | 出力画像 |
In [18]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
points = np.array([[100, 100], [120, 180], [190, 250], [270, 120], [220, 50]])
cv2.fillConvexPoly(img, points, color=(0, 255, 0))
imshow(img)
Advertisement
ポリゴンを描画する – cv2.fillPoly
img = cv2.fillPoly(img, pts, color[, lineType[, shift[, offset]]])
引数
名前 | 型 | デフォルト値 |
---|---|---|
img | ndarray | |
入力画像 | ||
points | ndarray | |
点の一覧 | ||
color | int / tuple of ints | |
色 | ||
line_type | LineTypes | cv2.LINE_8 |
線の描画方法 | ||
shift | int | 0 |
正の値の場合、座標を 1 / shift 倍にスケールする | ||
offset | tuple of 2 ints | (0, 0) |
オフセット |
返り値
名前 | 説明 | ||
---|---|---|---|
img | 出力画像 |
In [19]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
points = np.array([[100, 50], [120, 180], [50, 250], [270, 120], [220, 50]]).reshape(
1, -1, 2
)
cv2.fillPoly(img, points, color=(0, 255, 0))
imshow(img)
ポリゴンの輪郭線を描画する – cv2.polylines
img = cv2.polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]])
引数
名前 | 型 | デフォルト値 |
---|---|---|
img | ndarray | |
入力画像 | ||
pts | ndarray | |
点の一覧 | ||
isClosed | bool | |
ポリゴンが閉じているかどうか | ||
color | int / tuple of ints | |
色 | ||
thickness | int | 1 |
線の太さ | ||
line_type | LineTypes | cv2.LINE_8 |
線の描画方法 | ||
shift | int | 0 |
正の値の場合、座標を 1 / shift 倍にスケールする |
返り値
名前 | 説明 | ||
---|---|---|---|
img | 出力画像 |
In [20]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
points = np.array([[100, 50], [120, 180], [50, 250], [270, 120], [220, 50]]).reshape(
1, -1, 2
)
cv2.polylines(img, points, isClosed=True, color=(0, 255, 0), thickness=2)
imshow(img)

線分を描画する – cv2.line
img = cv2.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]])
引数
名前 | 型 | デフォルト値 |
---|---|---|
img | ndarray | |
入力画像 | ||
pt1 | tuple of 2 ints | |
線分の始点 | ||
pt2 | tuple of 2 ints | |
線分の終点 | ||
color | int / tuple of ints | |
色 | ||
thickness | int | 1 |
線の太さ | ||
line_type | LineTypes | cv2.LINE_8 |
線の描画方法 | ||
shift | int | 0 |
正の値の場合、座標を 1 / shift 倍にスケールする | ||
offset | tuple of 2 ints | (0, 0) |
オフセット |
返り値
名前 | 説明 | ||
---|---|---|---|
img | 出力画像 |
In [21]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
cv2.line(img, (50, 50), (250, 250), color=(255, 0, 0), thickness=2)
imshow(img)
Advertisement
矢印を描画する – cv2.arrowedLine
img = cv2.arrowedLine(
img, pt1, pt2, color[, thickness[, line_type[, shift[, tipLength]]]])
引数
名前 | 型 | デフォルト値 |
---|---|---|
img | ndarray | |
入力画像 | ||
pt1 | tuple of 2 ints | |
矢印の始点 | ||
pt2 | tuple of 2 ints | |
矢印の終点 | ||
color | int / tuple of ints | |
色 | ||
thickness | int | 1 |
線の太さ。負の値の場合は塗りつぶし。 | ||
line_type | LineTypes | cv2.LINE_8 |
線の描画方法 | ||
shift | int | 0 |
正の値の場合、座標を 1 / shift 倍にスケールする | ||
tipLength | float | 0.1 |
矢印の長さに対する末端の長さ |
返り値
名前 | 説明 | ||
---|---|---|---|
img | 出力画像 |
In [22]:
img = np.zeros((300, 300, 3), dtype=np.uint8)
cv2.arrowedLine(img, (50, 50), (250, 250), color=(255, 0, 0), thickness=2)
imshow(img)
-
前の記事
OpenCV – 画像の要約統計量を計算する方法について 2020.09.02
-
次の記事
OpenCV – メディアンフィルタの仕組みと cv2.medianBlur の使い方 2020.09.03