2012-11-27 17 views
6

画像のシルエットを抽出したいと思い、MatplotLibの輪郭関数を使用してそれをしようとしています。これは私のコードです:Pythonで外部輪郭やシルエットを抽出する

from PIL import Image 
from pylab import * 

# read image to array 
im = array(Image.open('HOJA.jpg').convert('L')) 

# create a new figure 
figure() 

# show contours with origin upper left corner 
contour(im, origin='image') 
axis('equal') 

show() 

これは私の元の画像です:

Original

そして、これが私の結果である:

Contour

しかし、私はちょうど外を表示したいです輪郭、シルエット。この例では、読み込んだ行だけです。

どうすればいいですか?私はcontour関数のドキュメントを読んだが、私が望むものを得ることはできない。

これをPythonで行うより良い方法が分かっている場合は教えてください! (MatplotLib、OpenCVなど)

答えて

12

輪郭のアプローチに固執したい場合は、白の背景と葉の間に画像を「閾値化」する値を持つlevel引数を追加するだけです。

ヒストグラムを使用して適切な値を見つけることができます。しかし、この場合、255よりわずかに低い値があります。だから、

:あなたはいくつかの深刻な画像処理を行いたい場合は

contour(im, levels=[245], colors='black', origin='image') 

enter image description here

あなたはScikit-画像をチェックアウトしていることを確認します。それは私がパフォーマンスのためのOpenCVを使用してrecommandうなど

http://scikit-image.org/docs/dev/auto_examples/

+0

偉大な答え!そしてScikit-Imageについてのアドバイスをありがとう、私はそれをチェックアウトします! – Xithias

0

いくつかのエッジ検出algoritmsが含まれています。 cv2バインディングを使用してPythonからアクセス可能な関数findContourがあります。 この機能は、外部輪郭のみを返すように設定できます。

また、画像のしきい値を設定する必要があります。 OpenCVのソリューションをしたい人のために

+0

OpenCVを使用して外部輪郭を抽出するコードを投稿できますか? – Xithias

+0

私はあなたにお答えしようとしていました。あまりにも遅いようです! –

4

、ここにある:この例では

ret,thresh = cv2.threshold(image,245,255,0) 
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) 

tam = 0 

for contorno in contours: 
    if len(contorno) > tam: 
     contornoGrande = contorno 
     tam = len(contorno) 

cv2.drawContours(image,contornoGrande.astype('int'),-1,(0,255,0),2) 

cv2.imshow('My image',image) 

cv2.waitKey() 
cv2.destroyAllWindows() 

、私が唯一最大の輪郭を描きます。 「イメージ」は単一チャネルの配列でなければならないことに注意してください。

しきい値関数、findContours関数、およびdrawContours関数のパラメータを変更して、必要なものを取得する必要があります。オープンCV 2.4にバグがあるため

  • drawContours Documentation
  • findContours Documentation
  • threshold Documentation
    • 私はdrawContours機能の「int型への変換を行います。3バージョンを使用し、この変換を行わないとプログラムが中断します。 This is the bug