2015-10-18 99 views
1

我有以下使用Python和OpenCV的代码。简而言之,我有一堆在不同震源深度拍摄的图像。这些代码在所有焦深(z)中具有最大高斯拉普拉斯响应拉普拉斯位置的每个(x,y)位置挑选出像素,从而创建焦点叠加图像。函数get_fmap创建一个2d阵列,其中每个像素将包含具有最大日志响应的焦平面的编号。在以下代码中,注释掉的行是我当前的VIPS实现。它们在函数定义中看起来不兼容,因为它只是部分解决方案。如何在Python中使用VIPS执行逻辑操作和逻辑索引?

# from gi.repository import Vips 

def get_log_kernel(siz, std): 
    x = y = np.linspace(-siz, siz, 2*siz+1) 
    x, y = np.meshgrid(x, y) 
    arg = -(x**2 + y**2)/(2*std**2) 
    h = np.exp(arg) 
    h[h < sys.float_info.epsilon * h.max()] = 0 
    h = h/h.sum() if h.sum() != 0 else h 
    h1 = h*(x**2 + y**2 - 2*std**2)/(std**4) 
    return h1 - h1.mean() 

def get_fmap(img): # img is a 3-d numpy array. 
    log_response = np.zeros_like(img[:, :, 0], dtype='single') 
    fmap = np.zeros_like(img[:, :, 0], dtype='uint8') 
    log_kernel = get_log_kernel(11, 2) 
    # kernel = get_log_kernel(11, 2) 
    # kernel = [list(row) for row in kernel] 
    # kernel = Vips.Image.new_from_array(kernel) 
    # img = Vips.new_from_file("testimg.tif") 
    for ii in range(img.shape[2]):   
     # img_filtered = img.conv(kernel) 
     img_filtered = cv2.filter2D(img[:, :, ii].astype('single'), -1, log_kernel) 
     index = img_filtered > log_response 
     log_response[index] = img_filtered[index] 
     fmap[index] = ii 
    return fmap 

然后fmap将被用来挑选出来自不同焦平面的像素来创建一个焦点堆栈图像

这是一个非常大的图像上完成的,而且我觉得VIPS可能做得更好比OpenCV就此。但是,官方文档仅提供有关Python绑定的信息。根据我在互联网上可以找到的信息,我只能够进行图像卷积工作(在我的情况下,它比OpenCV快一个数量级)。我想知道如何在VIPS中实现这一点,尤其是这些行?

log_response = np.zeros_like(img[:, :, 0], dtype = 'single') 

index = img_filtered > log_response 

log_response[index] = im_filtered[index] 

fmap[index] = ii 

回答

0

咨询Python VIPS manual和一些试验和错误之后,我拿出我自己的答案。我的问题numpy的和OpenCV的实现可以翻译成VIPS这样的:

from gi.repository import Vips 

img = [] 
for ii in range(num_z_levels): 
    img.append(Vips.Image.new_from_file("testimg_z" + str(ii) + ".tif") 

def get_fmap(img) 
    log_kernel = get_log_kernel(11,2) # get_log_kernel is my own function, which generates a 2-d numpy array. 
    log_kernel = [list(row) for row in log_kernel] # Vips.Image.new_from_array takes 1-d list array. 
    log_kernel = Vips.Image.new_from_array(log_kernel) # Turn the kernel into Vips array so it can be used by Vips. 
    log_response = img[0].conv(log_kernel, precision = Vips.Precision.FLOAT) 

    for ii in range(len(img)): 
     img_filtered = img[ii+1].conv(log_kernel, precision = Vips.Precision.FLOAT) 
     log_response = (img_filtered > log_response).ifthenelse(img_filtered, log_response) 
     fmap = (img_filtered > log_response).ifthenelse(ii+1, 0) 

逻辑索引是通过ifthenelse方法实现:

result_img = (test_condition).ifthenelse(value_if_true, value_if_false) 

语法相当灵活。测试条件可以是相同大小的两个图像之间或图像与数值之间的比较,例如, img1 > img2img > 5。像明智一样,value_if_true可以是单个值或Vips图像。

+1

我是vips维护者。你的代码看起来不错。你看到vips'logmat'函数了吗?它可能适合你。它创建一个日志掩码http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/libvips-create.html#vips-logmat从Python使用(例如)'Vips .Image.logmat(2,0.1)'。它会生成近似整数掩码和可分离掩码,这可以提供有用的加速。如果你愿意,你可以使用字符串'“float”'而不是'Vips.Precision.FLOAT'。 – user894763

+1

(第2部分)你需要'索引'图像吗?我认为你可以将其重写为'fmap =(img_filtered> log_response).ifthenelse(ii + 1,0)',我可能错过了一些东西。如果你有任何可以共享的基准,我会很好奇速度和内存使用与opencv相比。 – user894763

+0

尝试:'x = Vips.Image.logmat(2,0.1); x.matrixprint()'查看vips制作的日志文件。添加'precision =“float”'获得一个浮点版本。 – user894763

1

log_responsefmap被初始化为在问题代码3D阵列,而问题文本指出,输出,fmap是2D阵列。因此,我假定log_responsefmap将被初始化为2D阵列,其形状与每个图像相同。因此,该修改将 -

log_response = np.zeros_like(img[:,:,0], dtype='single') 
fmap = np.zeros_like(img[:,:,0], dtype='uint8') 

现在,回到问题的主题,你在每个图像一个接一个上执行2D过滤,并在所有的堆叠图像得到滤波输出的最大指数。如果您不知道cv2.filter2D的文档,它也可以用在多维数组上,从而为我们提供多维数组作为输出。然后,获取所有图像的最大索引就像.argmax(2)一样简单。因此,执行必须是非常有效的,是简单的 -

fmap = cv2.filter2D(img,-1,log_kernel).argmax(2) 
+0

谢谢。提供这个最简单的例子时我犯了一个错误。我编辑了我的帖子。很高兴知道'cv2.filter2d'具有这种用法。我一定会试一试。不过,默认情况下,VIPS使用多个内核,而使用OpenCV时,我必须自己实现这一点。并且向OpenCV添加多处理还会增加一些开销。我不认为'multiprocessing'模块加上OpenCV会执行接近VIPS。我在具有11x11内核的3000x4000图像上测试了高斯滤波。 VIPS在0.0025秒完成任务。 OpenCV花了0.1334秒。 – user3667217

+0

@ user3667217那么,您是否已经在VIPS中实施了该解决方案? Si,在这里分享一个答案?那么,直到今天,我还没有听说过,所以谢谢!让我知道任何其他的想法!那个VIPS,我当然看起来很有趣。 – Divakar

+0

我没有在VIPS中获得完整的解决方案,这就是为什么我会问如何在VIPS中执行逻辑操作和索引。显然,VIPS正在积极开发(目前已经是第8版),但是很少有人知道。我设法做的是离现有的Python手册没有太远。我只知道它执行高斯滤波并使用我自己的内核进行滤波。我仍在探索它。我会在OP中输入代码。 VIPS真的很棒。例如,它花费了0.0011秒的时间读取图像,而openCV花费了0.043秒。它的速度非常快。绝对值得一试! – user3667217