バイナリ イメージの黒い領域を見つける Opencv の python ラッパーにメソッド/関数はありますか? ( Matlabのregionpropsのように)これまで、ソース画像をロードし、しきい値を介してバイナリ画像に変換し、反転して黒い領域(現在は白)を強調表示しています。
cvblobslob や cvblob などのサードパーティ ライブラリを使用できない
基本的に、findContours
OpenCV が特にこの目的のために提供する他の多くの関数と組み合わせて関数を使用します。
使用された便利な関数 (驚き、驚き、それらはすべてOpenCV ドキュメントの構造解析と形状記述子のページに表示されます):
コード例 (Matlab のandregionprops
を除くすべてのプロパティがあります。inを使用して、結果の階層を調べることで解決できます。また、それほど難しくはないと確信しています。WeightedCentroid
EulerNumber
EulerNumber
cv2.RETR_TREE
findContours
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]
バイナリ イメージを反転して黒から白の領域にした後、cv.FindContours 関数を適用します。必要な領域の境界が表示されます。
後で cv.BoundingRect を使用して、領域の周囲の最小境界四角形を取得できます。長方形の頂点を取得したら、その中心などを見つけることができます。
または、領域の重心を見つけるには、等高線を見つけた後に cv.Moment 関数を使用します。次に、x 方向と y 方向に cv.GetSpatialMoments を使用します。opencvのマニュアルで説明されています。
面積を求めるには、cv.ContourArea 関数を使用します。
フラグ付きのしきい値を使用してバイナリ イメージに変換すると、CV_THRESH_BINARY_INV
しきい値 + 反転が 1 ステップで得られます。
別の無料ライブラリの使用を検討できる場合は、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)
黒と白のみを含むマスク画像を取得する前に、白は指定された範囲内のオブジェクトです。