OpenCVでconvexHullで穴埋めされた領域を取り出す

概要

Opencvで輪郭を取得して、更に凸包領域を取り出すのはとても簡単にできる。 以下の公式のとおりである。 領域(輪郭)の特徴 — OpenCV-Python Tutorials 1 documentation

ところで、この凸包領域と元の輪郭の間にある凹み領域を入手したくなったので、入手する方法を考えて実装してみた。

結果はこうなった。ちゃんと取得できた。

f:id:KYudy:20181002123159p:plain

実装

実装は以下のようになった。 重要なのはimage_cave = image_baggy - image_tightである。 OpenCVの画像を二値化して得られたNumpyの配列を引き算している。凹み領域は凸包と輪郭の差分として得られた。

import cv2
import numpy as np
import matplotlib.pyplot as plt

def main():
    image = cv2.imread("./figure.png")
    image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    _, image_gray = cv2.threshold(image_gray, 127, 255, 0)

    _, contours, _ = cv2.findContours(image_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    hulls = [cv2.convexHull(contour) for contour in contours]

    image_contour = cv2.drawContours(image_gray.copy(), contours, -1, (0,255,0), 1)
    image_hull = cv2.drawContours(image_gray.copy(), hulls, -1, (0,255,0), 1)

    image_tight = np.zeros((image_gray.shape), np.uint8)
    image_baggy = np.zeros((image_gray.shape), np.uint8)

    for contour, hull in zip(contours, hulls):
        cv2.fillPoly(image_tight, pts =[contour], color=(255,255,255))
        cv2.fillPoly(image_baggy, pts =[hull], color=(255,255,255))

    # diff generates a caved image.
    image_cave = image_baggy - image_tight

    image = np.hstack([image_gray, image_cave])

    cv2.imshow("image", image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


if __name__ == "__main__":
    main()