python 中定义孔填充函数(根据数学定义)的问题

Problem with defining a hole filing function (according to mathematical definition) in python

我是 python 的新手,所以请考虑一下 :) 在对 binary 图像应用“关闭”后,我试图 fill holes 没有使用任何内置函数。我想在我的头部 Ct 图片上做这样的事情(在下面)。 continously erosion with a structuring element(+) (similar to the equation on it) 所以我写了这段代码,但是我的初始点还是有问题。

def holefiling(img,B):
    initial= np.zeros_like(img)
    imginv = cv.bitwise_not(img)
    i=np.random.choice(img.shape[0])
    j=np.random.choice(img.shape[1])
    while img[i,j]!=np.max(img):#FINDING A WHITE HOLE WITH THE brightest intensities
        i=np.random.choice(img.shape[0])
        j=np.random.choice(img.shape[1])
    
    initial[i,j]=imginv[i,j]
    #initial=cv.bitwise_not(initial)#?
    for k in (0,10000):#10000 times of doing this algoryithm might solve all of it
        erosion = cv.erode(initial,B,iterations = 1) #X_k erosion with structuring element B
        X_k=initial & erosion
        initial=X_k
    Output=X_k | img
    return Output

kernel=cv.getStructuringElement(cv.MORPH_CROSS,(3,3))# defining a 3*3 cross(+) structure
Holefilled=holefiling(closing,kernel)

#showing the result
plt.figure()
plt.suptitle('fingerprint.tif')

plt.subplot(131)
plt.title(r'${Original_{img}}$')
plt.imshow(img, cmap='gray', vmin=0, vmax=np.max(img))
plt.axis(False)

plt.subplot(132)
plt.title(r'${closing}$')
plt.imshow(closing, cmap='gray', vmin=0, vmax=np.max(closing))
plt.axis(False)

plt.subplot(133)
plt.title(r'${Holefilled}$')
plt.imshow(Holefilled, cmap='gray', vmin=0, vmax=np.max(Holefilled))
plt.axis(False)

结果显示图片没有任何变化,我很困惑为什么会这样。 (其实我以为初始点一定是在最亮的地方,而且在什么都没有发生的情况下,一定是通过增加迭代来改变的。)这里可以看到结果: zooming on the results

我认为问题可能与其中之一有关。 1.the 初始点必须在孔之间的某个位置,但我不知道如何:| 2.the替换代码中X_k的过程有点问题 3.structuring element (cross +) 应该是别的东西(这个选项的可能性太低了 :D ) 所以,请所有可以帮助我的人,提前非常感谢。

霍尔填充过程的初始点

我找到了我的问题的答案,但对于那些人来说,这可能也是他们的问题。我不会删除我的问题并想添加我的答案。 我解决了寻找首字母的问题,您可能想知道如何解决?所以我决定找到一个零值的孔点,而它周围 4 条线的点的总和具有类似于填充线的值。 (如果要填充黑色区域内的白洞,则应找到一个值为 1 且其周围四条线的点之和为零的点) 这是我的代码:

def holefiling(img,B):
img1 = np.array(img)  
#imginv
thresh = 0/5
binarr = np.where(img1>thresh, 0, 1)# if i wrote: np.where(img>thresh, 1,0) the color would be reversed
# Covert numpy array back to image 
binimg = np.asmatrix(binarr)
#binimg1  = cv.threshold(img, thresh, 255, cv.THRESH_BINARY)
imginv=binimg.astype('uint8')  

hf=13 #depends on situation of the hole
#finding an initial point:
#1.defining a black initial
initial= np.zeros_like(img)

#finding a white pixel inside a black area:
#separating each pixel of the image but not around the edges: [hf:img.shape[0]-hf]
for i in range(0+hf,img.shape[0]-hf):
    for j in range(0+hf,img.shape[1]-hf):
        #print(np.sum(img[i-hf:i+hf,j+hf]))
        #print(img[78,236])
        #checking if the i,j pixel is black while around it has white lines according to the equations of these lines below and vice-versa
        if np.sum(img[i-hf:i+hf,j-hf])>=hf+hf/2 and np.sum(img[i-hf:i+hf,j+hf])>=hf+hf/2 and np.sum(img[i-hf,j-hf:j+hf])>=1/2 and np.sum(img[i+hf,j-hf:j+hf])>=1/2 and img[i,j]==0:
            #finally the initial point for the holefiling process
            """ print(img[i,j])
            print(img[j,i]) """
            i_init=i
            j_init=j
            print(i_init,j_init)
            initial[i_init,j_init]=imginv[i_init,j_init]

        #print(i_init,j_init)
        """ elif np.sum(img[i-hf:i+hf,j-hf])>=hf and np.sum(img[i-hf:i+hf,j+hf])>=hf and np.sum(img[i-hf,j-hf:j+hf])>=hf and np.sum(img[i+hf,j-hf:j+hf])>=hf and img[i,j]==0:
            print(i,j)
            i_init=i
            j_init=j
            initial[i_init,j_init]=img[i_init,j_init] """
print(img[i_init,j_init])
#initial[i_init,j_init]=imginv[i_init,j_init]
plt.figure()
plt.title(r'${InitialPoints}$')
plt.imshow(initial, cmap='gray', vmin=0, vmax=np.max(initial))
plt.axis(False)
plt.show()        
#initial[i_init,j_init]=img[i_init,j_init]
for k in range(100):#ten times of doing this algorithym might solve all of it
    dialation=cv.dilate(initial,B,iterations=1)
    X_k=imginv & dialation #img | dialation
    
    #if you want to check the code and wanna know how it works in each iteration, simply run this part down below
    """ plt.figure
    plt.subplot(144)
    plt.imshow(X_k, cmap='gray', vmin=0, vmax=np.max(initial))
    plt.axis(False)
    plt.subplot(141)
    plt.imshow(initial, cmap='gray', vmin=0, vmax=np.max(initial))
    plt.axis(False)
    plt.subplot(142)
    plt.imshow(dialation, cmap='gray', vmin=0, vmax=np.max(dialation))
    plt.axis(False)
    plt.subplot(143)
    plt.imshow(imginv, cmap='gray', vmin=0, vmax=np.max(initial))
    plt.axis(False)
    plt.show() """
    initial=X_k

#complementing X_k in order to have both images in complent mode
""" binarrinv = np.where(X_k>0, 0, 1)# if i wrote: np.where(img>thresh, 1,0) the color would be reversed
# Covert numpy array back to image 
binimginv = np.asmatrix(binarrinv)
imgOut=binimginv.astype('uint8')#imgOut """
Output=(X_k | img)# since the img and imgout are the complement of what we had in the slides so if we use intersection between two complements is equal to the union of two original images
return Output`

为了检查它是如何工作的,我 运行 下面的代码:

img= cv.imread('HeadCT.tif',0)
img = np.array(img)  
# Put threshold to 100 according to question to make it binary
thresh = 100
binarr = np.where(img>thresh, 1, 0)
# Covert numpy array back to image 
binimg = np.asmatrix(binarr)
binimg1=binimg.astype('uint8')
kernel=cv.getStructuringElement(cv.MORPH_ELLIPSE,(20,20))# defining a 20*20 ELLIPSE structure
closing = cv.morphologyEx(binimg1, cv.MORPH_CLOSE, kernel)# closing with Kernel
kernel1=cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))# defining a 3*3 ellipse structure
#testing my function

Holefilled1=holefiling(closing,kernel1)#for one of the holes
plt.figure()
plt.suptitle('HeadCT.tif')

plt.subplot(131)
plt.title(r'${Original_{img}}$')
plt.imshow(binimg1, cmap='gray', vmin=0, vmax=np.max(binimg1))
plt.axis(False)

plt.subplot(132)
plt.title(r'${closing_{on_{original img}}}$')
plt.imshow(closing, cmap='gray', vmin=0, vmax=np.max(closing))
plt.axis(False)

plt.subplot(133)
plt.title(r'${Holefilled_{after_{closing}}}$')
plt.imshow(Holefilled1, cmap='gray', vmin=0, vmax=np.max(Holefilled1))
plt.axis(False)

plt.show()

这里是输入图像HeadCt.tif 这是它的输出Results of hole-filling after closing 您也可以使用此结果来查找对象的边界。 我希望你和我一样喜欢它。 :)