如何根据孔的数量来计算对象

问题描述 投票:3回答:2

我正在处理一个有形状的图像,我正在尝试计算有1个洞的对象和有2个洞的对象。

我找到了有关它的信息,但它是在MATLAB中Segment out those objects that have holes in it他们使用了Euler特性,我知道在Python中存在skimage库,但我不能使用它。

我也找到了一些代码,但我无法理解。 http://www.cis.rit.edu/class/simg782/homework/hw3/hw3solutions.pdf Page 16。

PRO hw3 4,A,LA,LC,count
;Find all the holes
Ac=A EQ 0
LC=label region(Ac,/ALL)
;Construct an array with the holes filled in
Afill=(A GT 0) OR (LC GT 1)
;Display the arrays
sa=size(A,/dim)
window,/free,xsize=sa[0],ysize=sa[1]
tvlct,rr,gg,bb,/get
tek color
TV,Afill
window,/free,xsize=sa[0],ysize=sa[1]
TV,LC
;Count the objects with holes. First we
;find all the objects and then match up
;the object labels and the hole labels.
LA=label region(Afill)
window,/free,xsize=sa[0],ysize=sa[1]
TV,LA
ha=histogram(LA)
ia=where(ha ge 0)
print,format=’("Objects",3x,"Count",/,(i2,5x,i7))’,$
[transpose(ia),transpose(ha[ia])]
;Each element of ia corresponds to a filled
;object. Object k is labeled ia[k]. For each
;object that is not background,
;determine whether it has holes.
c=0
print
print,"k ia[k] N C"
For k=1,n elements(ia)-1 DO BEGIN
B=bytarr(sa[0],sa[1]); Make an array with one object
ik=Where(LA eq ia[k]); ;Fill in the object
IF MIN(ik) GE 0 THEN B[ik]=1
;Now see if any of the object pixels match the
;hole image LC. Counts if one or more holes.
IF MAX(B AND (LC GT 0)) GT 0 THEN c++
print,[k,ia[k],n elements(ik),c],format=’(I2,1x,I2,3x,I5,2x,I1)’
END
Print,’Number of objects with one or more holes=’,count
tvlct,rr,gg,bb
END
IDL> hw3 4,A,LA,LC,count

我们的想法是计算具有1个孔的对象和具有2个孔的对象,并突出显示它们的边缘。

“一洞物体数量:2”

“有两个孔的物体数量:4”

这是我所拥有的,我用一个简单的cv2.HoughCircles做到了:

python python-3.x image-processing
2个回答
1
投票

Contour Hierarchy可用于根据孔的数量来计算对象。想象一下,你有100个不同大小的盒子,从一个大冰箱到一个小珠宝盒。你想要存储所有100个盒子,所以你把一些盒子放在其他更大的盒子里面。您还希望以后能够找到这些框,因此您可以保留哪个框位于哪个框内的列表。轮廓以相同的方式工作,此列表称为层次结构。

要查找轮廓和层次结构:

img = cv2.imread('/home/stephen/Desktop/test.png', 0)
_, contours, hierarchy = cv2.findContours(img,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)

接下来,遍历每个轮廓以查找其内部是否有任何轮廓

max_num = np.amax(hierarchy) +1
for c, h in zip(contours, hierarchy[0]):
    # If there is at least one interior contour, find out how many there are
    if h[2] != -1:
        # Make sure it's not the 'zero' contour
        if h[0] == -1:
            num_interior_contours = max_num - h[2]
        else: num_interior_contours = h[0]-h[2]
    else: num_interior_contours = 0

绘制或计算内部具有另一个轮廓的轮廓数:

if num_interior_contours == 1:
    cv2.drawContours(img_color, [c], -1, (255,0,255), 2)
# Outline the contour in green if there are two holes.
if num_interior_contours == 2:
    cv2.drawContours(img_color, [c], -1, (0,255,0), 2)

shapes with one hole in pink, with two in green


1
投票

那么你总是可以自己实现欧拉特征。 Steve Eddins在他的MathWorks blog上发表了一篇很好的文章。在那里,他引用机器人视觉,Berthold K. P. Horn,麻省理工学院出版社,1989年,其中原作者(显然,无法访问源)演示了一种计算(4连接)欧拉特征的O(n)方法。然后,Eddins演示了如何在多标签图像上执行相同的操作,以及MATLAB代码示例。

这是我的Numpy转换他的代码以及一些OpenCV来实现你想要的那个漏洞:

import numpy as np
import cv2

def EulerNumbers(L):
    '''
    For a label matrix L containing nonnegative integers, returns a vector e
    such that e[k-1] is the 4-connected Euler number of the binary image (L ==
    k), from k = 1 to max(L).

    Adapted from:
    https://blogs.mathworks.com/steve/2014/10/02/lots-and-lots-of-euler-numbers/
    Accessed on 5.4.2019.
    '''

    Lp = np.pad(L, ((1,0), (1,0)), 'constant')

    I_NW = Lp[ :-1,  :-1];
    I_N  = Lp[ :-1, 1:  ];
    I_W  = Lp[1:  ,  :-1];

    is_upstream_convexity = np.logical_and(L,(L != I_N));
    is_upstream_convexity = np.logical_and(is_upstream_convexity, (L != I_NW));
    is_upstream_convexity = np.logical_and(is_upstream_convexity,  (L != I_W));

    is_upstream_concavity = np.logical_and(L,(L != I_NW));
    is_upstream_concavity = np.logical_and(is_upstream_concavity, (L == I_N));
    is_upstream_concavity = np.logical_and(is_upstream_concavity, (L == I_W));

    upstream_convexity_labels = L[is_upstream_convexity];
    upstream_concavity_labels = L[is_upstream_concavity];

    total_upstream_convexities = np.bincount(upstream_convexity_labels)[1:] #Discard the zero bin, which is the background.
    total_upstream_concavities = np.bincount(upstream_concavity_labels)[1:]

    return total_upstream_convexities - total_upstream_concavities;


#Load the image
BwI = cv2.imread('BwI.png', cv2.IMREAD_GRAYSCALE)

#Label all the connected components
_, L = cv2.connectedComponents(BwI)

#Compute all the Euler numbers
e = EulerNumbers(L)

# All the regions with no holes will have an Euler number of 1. Regions with one hole
# will have an Euler number of 0. Two holes -> -1 etc. 

num_no_holes = np.sum(e==1)
num_single_hole = np.sum(e==0)
num_two_holes = np.sum(e==-1)
num_three_holes = np.sum(e==-2)
num_more_holes = np.sum(e<-2)

print('Number of objects without holes : %d'%num_no_holes)
print('Number of objects with single hole : %d'%num_single_hole)
print('Number of objects with two holes : %d'%num_two_holes)
print('Number of objects with three holes : %d'%num_three_holes)
print('Number of objects with more than three holes: %d'%num_more_holes)

## Example, colourcode all objects by their amount of holes

Euler2Numholes = lambda e : abs(e-1)

#Label each region by the number of holes it has + 1.
# +1 so the holeless ones won't dissappear.
L_holecounts = np.zeros(L.shape, dtype=np.int32)
for i in range(1, np.max(L)):
    L_holecounts[L == i] = Euler2Numholes(e[i-1])+1

#Spread the small range to [0,255]
plot_L = cv2.normalize(L_holecounts, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8UC1) 
#Note that this will break when there are more than 255 labels. The colormap only works with uint8.

#Colormap it
plot_L = cv2.applyColorMap(plot_L, cv2.COLORMAP_JET)

cv2.imshow('The objects colourcoded by their number of holes', plot_L)
cv2.waitKey(0)

产出:

没有孔的物体数量:21 单孔物体数量:2 有两个孔的物体数量:4 具有三个孔的对象数:0 具有三个以上孔的对象数:0

Colour_coded_labels

© www.soinside.com 2019 - 2024. All rights reserved.