2012-01-29 15 views
11

バイナリイメージの黒い領域を見つけるOpenCvのpythonラッパーにはメソッド/関数がありますか? (のように、Matlabののregionprop) これまでは、ソース画像を読み込み、閾値を使って2値画像に変換し、それを反転して黒い領域(白い部分)を強調表示しました。Python OpenCV - バイナリイメージの黒い領域を見つける

Iは、白領域を黒くcv.FindContours関数を適用する二値画像を反転した後にそのようなcvblobslob又はcvblob

+1

+1 Googleの検索時間を節約したキーワード「regionprops」 – Tarrasch

答えて

2

としてサードパーティのライブラリを使用することはできません。それはあなたに必要な地域の境界を与えるでしょう。

後でcv.BoundingRectを使用して、領域の周囲に最小境界矩形を取得できます。一度矩形の頂点を取得すると、その中心などを見つけることができます。

または領域の重心を見つけるには、輪郭を見つけた後にcv.Moment関数を使用します。次に、x、y方向にcv.GetSpatialMomentsを使用します。これはopencvのマニュアルで説明されています。

領域を見つけるには、cv.ContourArea関数を使用します。

24

基本的には、findContours関数を、他の多くの関数と組み合わせて使用​​すると、OpenCVは特にこの目的を果たします。

サンプルコード(私はMATLABのregionpropsWeightedCentroidEulerNumber除くからすべてのプロパティを持っている - あなたはfindContourscv2.RETR_TREEを使用して、得られる階層を見て、EulerNumberを仕事ができますそして、私は確信しているWeightedCentroidもそれほど難しいでしょう。

# grab contours 
cs,_ = cv2.findContours(BW.astype('uint8'), mode=cv2.RETR_LIST, 
          method=cv2.CHAIN_APPROX_SIMPLE) 
# set up the 'FilledImage' bit of regionprops. 
filledI = np.zeros(BW.shape[0:2]).astype('uint8') 
# set up the 'ConvexImage' bit of regionprops. 
convexI = np.zeros(BW.shape[0:2]).astype('uint8') 

# for each contour c in cs: 
# will demonstrate with cs[0] but you could use a loop. 
i=0 
c = cs[i] 

# calculate some things useful later: 
m = cv2.moments(c) 

# ** regionprops ** 
Area   = m['m00'] 
Perimeter  = cv2.arcLength(c,True) 
# bounding box: x,y,width,height 
BoundingBox = cv2.boundingRect(c) 
# centroid = m10/m00, m01/m00 (x,y) 
Centroid  = (m['m10']/m['m00'],m['m01']/m['m00']) 

# EquivDiameter: diameter of circle with same area as region 
EquivDiameter = np.sqrt(4*Area/np.pi) 
# Extent: ratio of area of region to area of bounding box 
Extent  = Area/(BoundingBox[2]*BoundingBox[3]) 

# FilledImage: draw the region on in white 
cv2.drawContours(filledI, cs, i, color=255, thickness=-1) 
# calculate indices of that region.. 
regionMask = (filledI==255) 
# FilledArea: number of pixels filled in FilledImage 
FilledArea = np.sum(regionMask) 
# PixelIdxList : indices of region. 
# (np.array of xvals, np.array of yvals) 
PixelIdxList = regionMask.nonzero() 

# CONVEX HULL stuff 
# convex hull vertices 
ConvexHull = cv2.convexHull(c) 
ConvexArea = cv2.contourArea(ConvexHull) 
# Solidity := Area/ConvexArea 
Solidity  = Area/ConvexArea 
# convexImage -- draw on convexI 
cv2.drawContours(convexI, [ConvexHull], -1, 
        color=255, thickness=-1) 

# ELLIPSE - determine best-fitting ellipse. 
centre,axes,angle = cv2.fitEllipse(c) 
MAJ = np.argmax(axes) # this is MAJor axis, 1 or 0 
MIN = 1-MAJ # 0 or 1, minor axis 
# Note: axes length is 2*radius in that dimension 
MajorAxisLength = axes[MAJ] 
MinorAxisLength = axes[MIN] 
Eccentricity = np.sqrt(1-(axes[MIN]/axes[MAJ])**2) 
Orientation  = angle 
EllipseCentre = centre # x,y 

# ** if an image is supplied with the BW: 
# Max/Min Intensity (only meaningful for a one-channel img..) 
MaxIntensity = np.max(img[regionMask]) 
MinIntensity = np.min(img[regionMask]) 
# Mean Intensity 
MeanIntensity = np.mean(img[regionMask],axis=0) 
# pixel values 
PixelValues = img[regionMask]   
+0

これを関数にラップし、情報が入った何らかの構造(たとえばnumpy recarray)を返すと便利です。私がそれをしている間、私はまた、領域 'i'が強度 'i + 1'を有するラベル付き画像を描く(これは、領域0が背景とマージするのを避けるためである)。 –

0

CV_THRESH_BINARY_INVフラグでしきい値を使用してバイナリイメージに変換、あなたはワンステップで、閾値+反転を取得します。

0

別の無料ライブラリの使用を検討する場合は、SciPyを使用できます。あなたが使用することができ、必要な場合は

from scipy import ndimage 

def count_labels(self, mask_image): 
    """This function returns the count of labels in a mask image.""" 
    label_im, nb_labels = ndimage.label(mask_image) 
    return nb_labels 

:それは区域を数えるのに非常に便利な方法があります

import cv2 as opencv 

image = opencv.inRange(image, lower_threshold upper_threshold) 

を白と黒だけ含まれているマスク画像を取得する前に、白のオブジェクトどこ指定された範囲。

関連する問題