Python OpenCV-在二进制图像中查找黑色区域

Python OpenCV-在二进制图像中查找黑色区域,python,opencv,colors,detection,threshold,Python,Opencv,Colors,Detection,Threshold,Opencv的python包装器中是否有任何方法/函数可以在二进制图像中查找黑色区域?(如Matlab中的regionprops) 到目前为止,我加载源图像,通过阈值将其转换为二值图像,然后将其反转以突出显示黑色区域(现在为白色) 我不能使用第三方库,如cvblobslob或cvblob在反转二进制图像以将黑色区域变为白色区域后,应用cv.FindContours函数。它将为您提供所需区域的边界 稍后,您可以使用cv.BoundingRect获得区域周围的最小边界矩形。一旦你得到矩形顶点,你可以

Opencv的python包装器中是否有任何方法/函数可以在二进制图像中查找黑色区域?(如Matlab中的regionprops) 到目前为止,我加载源图像,通过阈值将其转换为二值图像,然后将其反转以突出显示黑色区域(现在为白色)


我不能使用第三方库,如cvblobslob或cvblob

在反转二进制图像以将黑色区域变为白色区域后,应用cv.FindContours函数。它将为您提供所需区域的边界

稍后,您可以使用cv.BoundingRect获得区域周围的最小边界矩形。一旦你得到矩形顶点,你可以找到它的中心等

或者在找到轮廓后使用cv.矩函数来找到区域的质心。然后在x和y方向使用cv.GetSpatialMoments。opencv手册对此进行了解释

要查找面积,请使用cv.ContourArea函数。

基本上,您可以将该函数与OpenCV为此提供的许多其他函数结合使用

使用的有用功能(惊喜,惊喜,它们都出现在OpenCV文档的页面上):

示例代码(除了
WeightedCentroid
EulerNumber
之外,我拥有Matlab的所有属性-通过使用
findContours
中的
cv2.RETR_树
并查看生成的层次结构,您可以计算出
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]        

使用阈值将其转换成二值图像,使用<代码> CVY-ValdHyb SciPy,/Cuff> FLAG,一步获得阈值+反转。

< P>如果您可以考虑使用另一个自由库,则可以使用<代码> < <代码> >,它具有非常方便的计数区域:

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)

在获得仅包含黑色和白色的遮罩图像之前,白色是给定范围内的对象。

我知道这是一个老问题,但为了完整性,我想指出
cv2.moments()
并不总是适用于小轮廓。在这种情况下,可以使用
cv2.mineClosingCircle()
即使只有一个点,也会始终返回中心坐标(和半径)。不过,我认为…

将其封装在函数中并返回某种结构(例如numpy recarray)很有用当我在做的时候,我还画了一个带标签的图像,其中区域
I
具有强度
I+1
(这是为了避免区域0与背景合并)。+1用于关键字“regionprops”,这节省了我数小时的谷歌搜索时间