在python 2.7中使用opencv 2.4查找最大连接组件

在python 2.7中使用opencv 2.4查找最大连接组件,python,opencv,Python,Opencv,我正在使用opencv“2.4.9.1”用python 2.7.12编写代码。 我有一个2d numpy数组,其中包含[0255]范围内的值。 我的目标是找到[x,y]范围内包含值的最大区域 我发现 解释得很好。 唯一的问题是——它是为opencv 3设计的 我可以尝试编写这种类型的函数 [伪代码] def get_component(x,y,list): append x,y to list visited[x][y]=1 if(x+1<m && visited

我正在使用opencv“2.4.9.1”用python 2.7.12编写代码。
我有一个2d numpy数组,其中包含[0255]范围内的值。
我的目标是找到[x,y]范围内包含值的最大区域
我发现 解释得很好。 唯一的问题是——它是为opencv 3设计的

我可以尝试编写这种类型的函数
[伪代码]

def get_component(x,y,list):
  append x,y to list
  visited[x][y]=1
 if(x+1<m && visited[x+1][y]==0)
  get_component(x+1,y,list)
 if(y+1<n && visited[x][y+1]==0)
  get_component(x,y+1,list)
 if(x+1<m)&&(y+1<n)&&visited[x+1][y+1]==0
  get_component(x+1,y+1,list)
 return

MAIN
biggest_component = NULL
biggest_component_size = 0
low = lowest_value_in_user_input_range
high = highest_value_in_user_input_range
matrix a = gray image of size mxn
matrix visited = all value '0' of size mxn
for x in range(m):
 for y in range(n):
  list=NULL
  if(a[x][y]>=low) && (a[x][y]<=high) && visited[x][y]==1:
   get_component(x,y,list)
   if (list.size>biggest_component_size)
    biggest_component = list
Get maximum x , maximum y , min x and min y from above list containing coordinates of every point of largest component to make rectangle R .
Mission accomplished !
def get_组件(x,y,list):
将x,y附加到列表
访问量[x][y]=1

如果(x+1很高兴看到我的答案被链接!事实上,
connectedComponents swithstats()
甚至
connectedComponents()
都是OpenCV 3+函数,所以你不能使用它们。相反,简单的方法是使用
findContours()

您可以计算每个轮廓的
矩()
,矩中包括轮廓的面积

重要提示:OpenCV函数
findContours()
使用8路连接,而不是4路连接(即它还检查对角线连接,而不仅仅是上、下、左、右)。如果需要4路连接,则需要使用不同的方法。如果是这种情况,请告诉我,我可以更新

本着另一篇文章的精神,以下是一般方法:

  • 使用感兴趣的阈值对图像进行二值化
  • 运行
    cv2.findContours()
    获取图像中每个不同组件的轮廓
  • 对于每个轮廓,计算轮廓的
    cv2.moments()
    ,并保留最大面积轮廓(
    m00
    ,从
    moments()
    返回的dict中是轮廓的面积)
  • 如果需要,可以将轮廓保留为点列表,否则,如果希望将其作为遮罩,可以在新的空白图像上绘制轮廓

  • 我今天缺乏创造力,所以你得到了我们的示例图像,因为你没有提供

    import cv2
    import numpy as np
    
    img = cv2.imread('cameraman.png', cv2.IMREAD_GRAYSCALE)
    

    现在,让我们进行二值化以获得一些分离的blob:

    bin_img = cv2.inRange(img, 50, 80)
    

    现在让我们找到轮廓线

    contours = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
    
    # For OpenCV 3+ use: 
    # contours = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[1]
    
    现在是主钻头;在轮廓上循环,找到最大的一个:

    max_area = 0
    max_contour_index = 0
    for i, contour in enumerate(contours):
        contour_area = cv2.moments(contour)['m00']
        if contour_area > max_area:
            max_area = contour_area
            max_contour_index = i
    
    因此,现在我们有了一个按区域划分的最大轮廓索引
    max\u contour\u index
    ,因此您可以通过执行
    轮廓[max\u contour\u index]
    直接访问最大轮廓。当然,您可以按轮廓区域对
    轮廓列表进行排序,并获取第一个(或最后一个,取决于排序顺序)。若要制作一个组件的遮罩,可以使用

    cv2.drawContours(new_blank_image, contours, max_contour_index, color=255, thickness=-1)
    
    注-1将填充轮廓,而不是勾勒轮廓。以下是在原始图像上绘制轮廓的示例:

    看起来不错

    多功能一体:

    def largest_component_mask(bin_img):
        """Finds the largest component in a binary image and returns the component as a mask."""
    
        contours = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
        # should be [1] if OpenCV 3+
    
        max_area = 0
        max_contour_index = 0
        for i, contour in enumerate(contours):
            contour_area = cv2.moments(contour)['m00']
            if contour_area > max_area:
                max_area = contour_area
                max_contour_index = i
    
        labeled_img = np.zeros(bin_img.shape, dtype=np.uint8)
        cv2.drawContours(labeled_img, contours, max_contour_index, color=255, thickness=-1)
    
        return labeled_img
    

    很高兴看到我的答案被链接!事实上,
    connectedComponents swithstats()
    甚至
    connectedComponents()
    都是OpenCV 3+函数,所以你不能使用它们。相反,简单的方法是使用
    findContours()

    您可以计算每个轮廓的
    矩()
    ,矩中包括轮廓的面积

    重要提示:OpenCV函数
    findContours()
    使用8路连接,而不是4路连接(即它还检查对角线连接,而不仅仅是上、下、左、右)。如果需要4路连接,则需要使用不同的方法。如果是这种情况,请告诉我,我可以更新

    本着另一篇文章的精神,以下是一般方法:

  • 使用感兴趣的阈值对图像进行二值化
  • 运行
    cv2.findContours()
    获取图像中每个不同组件的轮廓
  • 对于每个轮廓,计算轮廓的
    cv2.moments()
    ,并保留最大面积轮廓(
    m00
    ,从
    moments()
    返回的dict中是轮廓的面积)
  • 如果需要,可以将轮廓保留为点列表,否则,如果希望将其作为遮罩,可以在新的空白图像上绘制轮廓

  • 我今天缺乏创造力,所以你得到了我们的示例图像,因为你没有提供

    import cv2
    import numpy as np
    
    img = cv2.imread('cameraman.png', cv2.IMREAD_GRAYSCALE)
    

    现在,让我们进行二值化以获得一些分离的blob:

    bin_img = cv2.inRange(img, 50, 80)
    

    现在让我们找到轮廓线

    contours = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
    
    # For OpenCV 3+ use: 
    # contours = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[1]
    
    现在是主钻头;在轮廓上循环,找到最大的一个:

    max_area = 0
    max_contour_index = 0
    for i, contour in enumerate(contours):
        contour_area = cv2.moments(contour)['m00']
        if contour_area > max_area:
            max_area = contour_area
            max_contour_index = i
    
    因此,现在我们有了一个按区域划分的最大轮廓索引
    max\u contour\u index
    ,因此您可以通过执行
    轮廓[max\u contour\u index]
    直接访问最大轮廓。当然,您可以按轮廓区域对
    轮廓列表进行排序,并获取第一个(或最后一个,取决于排序顺序)。若要制作一个组件的遮罩,可以使用

    cv2.drawContours(new_blank_image, contours, max_contour_index, color=255, thickness=-1)
    
    注-1将填充轮廓,而不是勾勒轮廓。以下是在原始图像上绘制轮廓的示例:

    看起来不错

    多功能一体:

    def largest_component_mask(bin_img):
        """Finds the largest component in a binary image and returns the component as a mask."""
    
        contours = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
        # should be [1] if OpenCV 3+
    
        max_area = 0
        max_contour_index = 0
        for i, contour in enumerate(contours):
            contour_area = cv2.moments(contour)['m00']
            if contour_area > max_area:
                max_area = contour_area
                max_contour_index = i
    
        labeled_img = np.zeros(bin_img.shape, dtype=np.uint8)
        cv2.drawContours(labeled_img, contours, max_contour_index, color=255, thickness=-1)
    
        return labeled_img
    

    我将运行此程序并返回报告。顺便说一句,非常清晰。我可以在彩色图像上绘制此轮廓吗(实际上,灰度图像是从中派生出来的)?此外,我还打印了轮廓[max_contour_index]。形状并获得(924,1,2)。它实际上是924点的x,y坐标。我如何提取xmin,xmax,ymin,ymax,因为它将表示我感兴趣的左上和右下坐标的矩形遮罩?当然,但您需要一个3通道彩色图像来绘制。我在上面代码的第一行中以灰度形式读取图像,所以您希望读取彩色图像因此您可以使用
    drawContours()
    color=(b,g,r)
    元组来表示您要绘制的颜色。@user1371666您也可以简单地使用
    boundingRect()
    使用每个轮廓来查找轮廓的边界矩形。请参阅此处的更多信息:@user1371666我无法再现您的错误,可能是因为我使用的是OpenCV 3。当我在带有单个白点的图像上运行此操作时,它会按预期工作。在单点情况下,您能否编辑原始帖子以显示您的
    轮廓列表看起来像?另外请打印出所有其他的v