【Python・OpenCV・numpy】画像の塗りつぶし

※当サイトではアフィリエイト広告を利用しています

Python プログラミング 画像処理

【Python・OpenCV・numpy】画像の塗りつぶし

2023-04-27

はじめに

画像データを1色に塗りつぶす方法について解説します。
画像の塗りつぶしは画像データの初期化などで利用する機会が多いと思いますが、本投稿で画像データの初期化時に行う方法と初期化をした後に行う方法について紹介します。

初期化の時に塗りつぶす

初期化時に画素を全て同じ値に塗りつぶして画像を作成する場合、NumPyの機能を用います。
全てを”0”(黒)で初期化する方法と、任意の色で初期化する方法の2種類があります。

Numpy.zeros関数

画素値を0で初期化します。全ての画素値が0になるので黒く塗りつぶされた画像が作成されます。

出力画像 = numpy.zeros(shape[, dtype, order])

引数

名称説明
shape(必須)画像データのshape
dtype(オプション)データ型, デフォルト値はfloat
order(オプション)'C'または'F', デフォルト値は'C'。 メモリへの格納を行優先(C-style)または列優先(F-style)の指定

使い方

RGBのカラー画像として作成する場合のコードです。
引数の画像データのshapeは横方向のピクセル列,縦方向のピクセル行,チャンネル数のtupleとなるので、RGBのカラー画像のの場合、3つ目のチャンネル数は"3"となります。

import cv2
import numpy as np # NumPyに"np"という省略名をつける
 
# 画像のサイズを指定
width = 200     # 幅
height = 100    # 高さ
 
# RGBの画像として作成して、画素の全てを0で埋める(黒く塗りつぶす)。データ型は符号なし8ビット整数を指定。
color_image = np.zeros((height, width, 3), np.uint8)

グレースケール画像として作成する場合のコードです。
引数の画像データのshapeのチャンネル数はグレースケール画像なので"1"となります。

import cv2
import numpy as np # NumPyに"np"という省略名をつける
 
# 画像のサイズを指定
width = 200     # 幅
height = 100    # 高さ
 
# グレースケールの画像として作成して、画素の全てを0で埋める(黒く塗りつぶす)。データ型は符号なし8ビット整数を指定。
gray_image = np.zeros((height, width, 1), np.uint8)

Numpy.full関数

画素値を任意の色で初期化します。

出力画像 = numpy.full(shape, fill_value[, dtype, order])

引数

名称説明
shape(必須)画像データのshape
fill_value必須初期値(色)の指定
dtype(オプション)データ型, デフォルト値はfill_valueと同じデータ型
order(オプション)'C'または'F'。 メモリへの格納を行優先(C-style)または列優先(F-style)の指定。 (デフォルト:'C')

使い方

import cv2
import numpy as np # NumPyに"np"という省略名をつける
 
# 画像のサイズを指定
width = 200     # 幅
height = 100    # 高さ
 
# RGBの画像として作成して、画素の全てを任意の値で埋める([128, 128, 128]で塗りつぶす)。データ型は符号なし8ビット整数を指定。
color_image = np.full((height, width, 3), 128, np.uint8)

初期化の後に塗りつぶす

画像を初期化した後に塗りつぶしたい場合や既にある画像を塗りつぶしたい場合は、OpenCVの関数を用いる方法があります。

cv2.rectangle関数

rectangle関数を用いて全体を塗りつぶします。rectangle関数は塗りつぶしだけでなく、矩形の枠線を描画することもできます。

出力画像 = cv2.rectangle(入力画像, pt1, pt2, color[, thickness[, lineType[, shift]]])

引数

名称説明
入力画像(必須)入力画像
pt1(必須)矩形の頂点座標
pt2(必須)pt1の対角にある矩形の頂点
color(必須)
thicknessオプションラインの太さ。'-1'を指定すると塗りつぶしになります。
lineTypeオプション線の種類(デフォルト:cv.2LINE_8)
shiftオプション整数で指定され、座標は"2^shift"割った値となる

使い方

import cv2
        
# 画像の大きさを取得 h:高さ、w:幅、channels:チャンネル数
h, w, channels = color_image.shape[:3]
# 緑色を作成
green = (0, 255, 0)
# cv2
cv2.rectangle(color_image, (0,0), (w-1,h-1), green, thickness=-1)
cv2.imwrite('images/init_green.jpg', color_image)

ポイント

完全に画像を塗りつぶすために、画像の画角いっぱいに矩形の塗りつぶしをする必要があります。pt1とpt2にはそれぞれ対角の関係にある画像の角の座標を設定します。
使い方のコードではpt1に左上の(0,0)を設定します。pt2には4行目で取得した画像の大きさを設定しますが、0から始まっているので幅、高さの値からそれぞれマイナス1した値を設定します。

cv2.fillPoly関数

fillPoly関数を用いて全体を塗りつぶします。この関数は、ポリゴンの内部を指定の色で塗りつぶすことができます。
rectangle関数と同様に、ポリゴンの枠線を描画することもできます。

出力画像 = cv2.fillPoly(入力画像, pts, color[, lineType[, shift[, offset]]])

引数

名称説明
入力画像(必須)入力画像
pts(必須)塗りつぶすポリゴンの頂点座標
color(必須)
lineTypeオプション線の種類(デフォルト:cv.2LINE_8)
shiftオプション整数で指定され、座標は"2^shift"割った値となる
offsetオプションポリゴンの各頂点に対して、x軸方向とy軸方向を個別に指定するのオフセット値

offset引数は、ポリゴンの各頂点に対して、x軸方向とy軸方向のオフセット値を個別に指定する引数です。具体的には、numpy配列の形式で指定され、各要素は(x, y)というタプルで、それぞれ頂点のx座標とy座標に対応します。つまり、offset引数を使用すると、ポリゴンの各頂点の座標を個別に調整することができます。

使い方

import numpy as np
import cv2

# 画像を生成する
img = np.zeros((200, 200, 3), dtype=np.uint8)

# ポリゴンを描画する
pts = np.array([[50, 50], [100, 50], [100, 100], [50, 100]], np.int32)
pts = pts.reshape((-1,1,2))
cv2.fillPoly(img, [pts], (255, 0, 0))

# ポリゴンをshiftする
shifted_img = np.zeros((200, 200, 3), dtype=np.uint8)
cv2.fillPoly(shifted_img, [pts], (255, 0, 0), shift=3)

# ポリゴンの各頂点を調整する
offset_img = np.zeros((200, 200, 3), dtype=np.uint8)
offset_pts = np.array([[0, 0], [50, 0], [50, 50], [0, 50]], np.int32)
offset_pts = offset_pts.reshape((-1,1,2))
cv2.fillPoly(offset_img, [offset_pts], (0, 255, 0))

# 結果を表示する
cv2.imshow("original image", img)
cv2.imshow("shifted image", shifted_img)
cv2.imshow("offset image", offset_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

このサンプル コードでは、まずimgという200x200の黒い画像を生成し、そこにptsというポリゴンを描画しています。次に、shifted_imgという新しい画像を生成し、shift引数でshift=3を指定したポリゴンを描画しています。最後に、offset_imgという新しい画像を生成し、offset引数を使用して各頂点の座標を微調整したポリゴンを描画しています。

(広告) OpenCV関連書籍をAmazonで探す

おわりに

初期化として使用する最も簡単なものはNumpyをだと思います。cv2.fillPoly関数は初期化としての利用には使いにくいですが、複雑な形状の塗りつぶしに便利な機能になります。

最後までご覧いただきありがとうございました。

■(広告)OpenCVの参考書としてどうぞ!■

参考リンク

-Python, プログラミング, 画像処理
-