我正在使用opencv' 2.4.9.1'来编写python 2.7.12中的代码 我有一个2d numpy数组,其中包含范围[0,255]中的值 我的目标是找到范围[x,y]中包含值的最大区域 我发现 How to use python OpenCV to find largest connected component in a single channel image that matches a specific value?很好地解释了。 唯一的问题是 - 它适用于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 !
[/ pseudo code]
我认为这种方法效率不高
你可以建议我的设置功能吗?
感谢。
答案 0 :(得分:2)
很高兴看到我的答案相关联!实际上,connectedComponentsWithStats()
甚至connectedComponents()
都是OpenCV 3+函数,因此您无法使用它们。相反,最简单的方法就是使用findContours()
。
您可以计算每个轮廓的moments()
,并且包含在矩中的是轮廓的面积。
重要说明: OpenCV函数findContours()
使用8路连接,而不是4路(即它还检查对角线连接,而不仅仅是向上,向下,向左,向右)。如果您需要4路,则需要使用不同的方法。如果是这种情况,请告诉我,我可以更新..
本着另一篇文章的精神,这是一般方法:
cv2.findContours()
以获取图像中每个不同组件的轮廓。cv2.moments()
并保持最大区域轮廓(从m00
返回的dict中的moments()
是轮廓区域。我今天缺乏创造力,所以你得到the cameraman作为我们的示例图像,因为你没有提供。
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_contour_index
,所以你可以直接访问最大轮廓contours[max_contour_index]
。您当然可以按轮廓区域对contours
列表进行排序,然后抓取第一个(或最后一个,取决于排序顺序)。如果要制作单个组件的掩码,可以使用
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