我正在处理一个有形状的图像,我正在尝试计算有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
做到了:
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)
那么你总是可以自己实现欧拉特征。 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