2012-01-29 35 views
11

Có bất kỳ phương pháp/chức năng nào trong trình bao python của Opencv tìm thấy các vùng màu đen trong một hình ảnh nhị phân không? (như regionprops trong Matlab) Cho đến bây giờ tôi tải hình ảnh nguồn của tôi, biến nó thành một hình ảnh nhị phân qua ngưỡng và sau đó đảo ngược nó để làm nổi bật các khu vực màu đen (bây giờ là màu trắng).Python OpenCV - Tìm các khu vực màu đen trong một hình ảnh nhị phân

tôi không thể sử dụng thư viện của bên thứ ba như cvblobslob hoặc cvblob

+1

+1 cho Từ khóa "regionprops" đã lưu lại số giờ của tôi googling – Tarrasch

Trả lời

2

Sau khi đảo ngược hình ảnh nhị phân để chuyển sang màu đen đến các vùng trắng, áp dụng cv.FindContours chức năng. Nó sẽ cung cấp cho bạn ranh giới của khu vực bạn cần.

Sau đó, bạn có thể sử dụng cv.BoundingRect để có hình chữ nhật bao quanh tối thiểu quanh vùng. Khi bạn có các đỉnh hình chữ nhật, bạn có thể tìm thấy trung tâm của nó, v.v.

Hoặc để tìm centroid của khu vực, hãy sử dụng chức năng cv.Moment sau khi tìm đường nét. Sau đó sử dụng cv.GetSpatialMoments theo hướng x và y. Nó được giải thích trong hướng dẫn sử dụng opencv.

Để tìm khu vực, hãy sử dụng hàm cv.ContourArea.

24

Về cơ bản, bạn sử dụng hàm findContours, kết hợp với nhiều chức năng khác mà OpenCV cung cấp cho mục đích đặc biệt này.

chức năng hữu ích được sử dụng (bất ngờ, ngạc nhiên, họ tất cả xuất hiện trên Structural Analysis and Shape Descriptors trang trong OpenCV Documents):

mã ví dụ (Tôi có tất cả các thuộc tính từ Matlab của regionprops trừ WeightedCentroidEulerNumber - bạn có thể làm việc ra EulerNumber bằng cách sử dụng cv2.RETR_TREE trong findContours và nhìn vào hệ thống phân cấp kết quả và tôi chắc chắn rằng WeightedCentroid cũng sẽ không khó.

# 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

Sẽ hữu ích khi kết hợp chức năng này và trả về một số loại cấu trúc (ví dụ: truy vấn gọn gàng) với thông tin trong đó. Trong khi tôi đang ở đó, tôi cũng vẽ một hình ảnh có nhãn nơi mà khu vực 'i' có cường độ' i + 1' (điều này là để tránh vùng 0 sáp nhập với nền). –

0

Chuyển đổi sang hình ảnh nhị phân sử dụng ngưỡng với cờ CV_THRESH_BINARY_INV, bạn nhận được ngưỡng + đảo ngược trong một bước.

0

Nếu bạn có thể xem xét sử dụng một thư viện miễn phí khác, bạn có thể sử dụng SciPy. Nó có một cách rất thuận tiện của khu vực đếm:

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 

Nếu cần thiết bạn có thể sử dụng:

import cv2 as opencv 

image = opencv.inRange(image, lower_threshold upper_threshold) 

trước để có được một hình ảnh mặt nạ, trong đó có chỉ màu đen và trắng, nơi màu trắng là các đối tượng trong phạm vi nhất định.