Warning: Undefined variable $position in /home/pystyles/pystyle.info/public_html/wp/wp-content/themes/lionblog/functions.php on line 4897

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

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

概要

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)