如何在python中执行快速切零边缘?

时间:2018-11-29 16:10:58

标签: arrays python-3.x numpy image-processing

我的二进制图像尺寸为256x256x256,其中前景区域位于一个较小的区域中,并且我有很多零边距。我想通过查找图像中像素非零的点的最小和最大坐标来削减零边缘。它虽然有效,但花费时间。我发布了代码,您能否告诉我如何使它更快?

对于256x256x256的图像大小,大约需要0.13024640083312988秒。这是代码,您可以在https://repl.it/repls/AnxiousExoticBackup

在线运行
import numpy as np
import time

def cut_edge(image, keep_margin):
    '''
    function that cuts zero edge
    '''
    D, H, W = image.shape
    D_s, D_e = 0, D - 1
    H_s, H_e = 0, H - 1
    W_s, W_e = 0, W - 1

    while D_s < D:
        if image[D_s].sum() != 0:
            break
        D_s += 1
    while D_e > D_s:
        if image[D_e].sum() != 0:
            break
        D_e -= 1
    while H_s < H:
        if image[:, H_s].sum() != 0:
            break
        H_s += 1
    while H_e > H_s:
        if image[:, H_e].sum() != 0:
            break
        H_e -= 1
    while W_s < W:
        if image[:, :, W_s].sum() != 0:
            break
        W_s += 1
    while W_e > W_s:
        if image[:, :, W_e].sum() != 0:
            break
        W_e -= 1

    if keep_margin != 0:
        D_s = max(0, D_s - keep_margin)
        D_e = min(D - 1, D_e + keep_margin)
        H_s = max(0, H_s - keep_margin)
        H_e = min(H - 1, H_e + keep_margin)
        W_s = max(0, W_s - keep_margin)
        W_e = min(W - 1, W_e + keep_margin)

    return int(D_s), int(D_e)+1, int(H_s), int(H_e)+1, int(W_s), int(W_e)+1

image = np.zeros ((256,256,256),dtype=np.float32)
ones_D_min, ones_D_max, ones_H_min, ones_H_max,ones_W_min, ones_W_max= 100,200, 90,150, 60,200
image[ones_D_min: ones_D_max,ones_H_min:ones_H_max, ones_W_min:ones_W_max]=1
t0=time.time()
ones_D_min_result, ones_D_max_result, ones_H_min_result, ones_H_max_result, ones_W_min_result, ones_W_max_result= cut_edge(image,0)
t1=time.time()
print ('Time consuming ', t1-t0)
print (ones_D_min, ones_D_max, ones_H_min, ones_H_max,ones_W_min, ones_W_max)
print (ones_D_min_result, ones_D_max_result, ones_H_min_result, ones_H_max_result, ones_W_min_result, ones_W_max_result)

2 个答案:

答案 0 :(得分:3)

使用numpy的内置函数可以大大改善您的功能:

def cut_edge(image, keep_margin):
    '''
    function that cuts zero edge
    '''

    #Calculate sum along each axis
    D_sum = np.sum(image, axis=(1,2)) #0
    H_sum = np.sum(image, axis=(0,2)) #1
    W_sum = np.sum(image, axis=(0,1)) #2

    #Find the non-zero values
    W_nz = np.nonzero(W_sum)[0]
    H_nz = np.nonzero(H_sum)[0]
    D_nz = np.nonzero(D_sum)[0]

    #Take the first and last entries for start and end
    D_s = D_nz[0]
    D_e = D_nz[-1]
    H_s = H_nz[0]
    H_e = H_nz[-1]
    W_s = W_nz[0]
    W_e = W_nz[-1]


    if keep_margin != 0:
        D_s = max(0, D_s - keep_margin)
        D_e = min(D - 1, D_e + keep_margin)
        H_s = max(0, H_s - keep_margin)
        H_e = min(H - 1, H_e + keep_margin)
        W_s = max(0, W_s - keep_margin)
        W_e = min(W - 1, W_e + keep_margin)

    return D_s, D_e+1, H_s, H_e+1, W_s, W_e+1

结果:

Time consuming  0.0963144302368164

答案 1 :(得分:1)

您可以使用以下事实:如果sum越过3D数组的轴,则该值仍将是0,其中行(或列或第三维)中没有1,具体取决于哪个{ {1}}参数。然后,通过在其他两个方向之一上使用axisany,您将获得在另一个轴上至少有一个1的索引。使用np.argwheremin将提供您想要的值。这是函数:

max

与使用函数得到的结果相同:

def cut_edge_2(image, keep_margin):
    im_sum0 = (image.sum(0) !=0)
    im_sum1 = (image.sum(1) !=0)
    ones_D = np.argwhere(im_sum1.any(1))
    ones_H = np.argwhere(im_sum0.any(1))
    ones_W = np.argwhere(im_sum0.any(0))
    if keep_margin != 0:
        D, H, W = image.shape
        return (max( 0, ones_D.min() - keep_margin), min(D, ones_D.max() + keep_margin+1), 
                max( 0, ones_H.min() - keep_margin), min(H, ones_H.max() + keep_margin+1),
                max( 0, ones_W.min() - keep_margin), min(W, ones_W.max() + keep_margin+1))
    return (ones_D.min(), ones_D.max() +1, 
            ones_H.min(), ones_H.max() +1,           
            ones_W.min(), ones_W.max() +1)

和一些print (cut_edge(image,0)) #(100, 200, 90, 150, 60, 200) print (cut_edge_2(image,0)) #(100, 200, 90, 150, 60, 200) print (cut_edge(image,60)) #(40, 256, 30, 210, 0, 256) print (cut_edge_2(image,60)) #(40, 256, 30, 210, 0, 256)

timeit

更快。