LoginSignup
15
12

More than 5 years have passed since last update.

Python + OpenCVでGraph Based Segmentation

Last updated at Posted at 2016-08-29

Facebookがセグメンテーションフレームワークをオープンソース化したと聞いて、ちょうどセグメンテーションが必要だったので調べてみた。

Segmenting and refining images with SharpMask

LuaだったりTorchだったりするのは仕方がないとして、今回は教師なしで候補領域を得たかったのだが、このフレームワークは教師ありのようだったので利用を断念して他のものを探した。
そうすると、OpenCVにそのような機能があったので試してみた。

graph_segmentation.py
import cv2
import numpy as np

segmentator = cv2.ximgproc.segmentation.createGraphSegmentation(sigma=0.5, k=300, min_size=1000)
src = cv2.imread('image.jpg')
segment = segmentator.processImage(src)
mask = segment.reshape(list(segment.shape) + [1]).repeat(3, axis=2)
masked = np.ma.masked_array(src, fill_value=0)
for i in range(np.max(segment)):
    masked.mask = mask != i
    y, x = np.where(segment == i)
    top, bottom, left, right = min(y), max(y), min(x), max(x)
    dst = masked.filled()[top : bottom + 1, left : right + 1]
    cv2.imwrite('segment_{num}.jpg'.format(num=i), dst)
パラメータ
sigma 境界線の滑らかさ(複雑な境界線には小さい値、滑らかな境界線には大きい値)
k たぶん、どれくらい候補領域を統合するか(値が小さいと多くの小さい領域、大きいと少ない大きな領域に分割?)
min_size 領域の最小サイズ(たぶん領域のピクセル数)

地味に候補領域だけを切り出すところが難しかった。
Numpyでやる以外にも、OpenCVのboundingRectを使う方法があるらしい。

追記:
segmentator.setSigma(value), segmentator.setK(value), segmentator.setMinSize(value)で値を変更可能。

そのままでは載せられないLenaさんの全身像への適用結果(sigma=0.7, k=1200, min_size=5000)
lena_seg.png

15
12
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
12