画像から輪郭を抽出して重ね合わせる方法についてメモ
※opencv-python 3.4にて動作確認済み
サンプル画像
昔非常にお世話になったこの画像に今回もお世話になります。
入力画像 | ![]() |
---|---|
グレースケール | ![]() |
dilate⇒diff | ![]() |
二値化 | ![]() |
重ね合わせ | ![]() |
ソースコード
import cv2
def edgeDetect(color):
# カーネルサイズの設定
kernel5 = np.ones((5, 5), np.uint8)
# [1] 画像のグレースケール化とノイズ除去
gray = cv2.fastNlMeansDenoising(
cv2.cvtColor(color, cv2.COLOR_BGR2GRAY), h=20)
# [2] dilate -> diff で線抽出
dilation = cv2.dilate(gray, kernel5, iterations=1)
diff = cv2.subtract(dilation, gray)
diff_inv = 255 - diff
# [3] 線を単色 -> 2値に
_, edge = cv2.threshold(diff_inv, 225, 255, cv2.THRESH_BINARY)
# [4] 線画とモノクロ2値を重ねる
edge = cv2.cvtColor(edge, cv2.COLOR_GRAY2BGR)
img = cv2.bitwise_and(color, edge)
return img
各工程の解説
[1] 画像のグレースケール化とノイズ除去
輪郭抽出するためにまず画像をグレースケール化する。ついでにcv2.fastNlMeansDenoising()
を使用してノイズを除去することでゴミを輪郭として残さないようにする。ノイズの除去量はh
を増やせば増えるが、やりすぎに注意。
fastNlMeansDenoisingの詳細
https://docs.opencv.org/3.0-beta/modules/photo/doc/denoising.html#fastnlmeansdenoising
[2] dilate -> diff で線抽出
cv2.dilate()
とcv2.subtract()
を使うと輪郭がいい感じに抽出できる。最後に255 - diff
で白黒反転している。
[3] 線を単色 -> 2値に
cv2.threshold()
で抽出した線を二値化する。
thresholdの詳細
https://docs.opencv.org/3.0-beta/modules/imgproc/doc/miscellaneous_transformations.html#threshold
[4] 線画とモノクロ2値を重ねる
最後に抽出した輪郭をカラー画像に重ね合わせる。ただし、輪郭はグレースケール画像なのでcv2.cvtColor()
を忘れないようにする。
以上