如何在Python中使用VIP执行逻辑操作和逻辑索引?

如何在Python中使用VIP执行逻辑操作和逻辑索引?,python,opencv,numpy,image-processing,vips,Python,Opencv,Numpy,Image Processing,Vips,我有以下使用Python和OpenCV的代码。简单地说,我有一堆不同焦距的图像。代码在所有焦深(z)中具有最大拉普拉斯高斯响应的每个(x,y)位置拾取像素,从而创建聚焦堆叠图像。函数get_fmap创建一个2d阵列,其中每个像素将包含具有最大对数响应的焦平面的数量。在以下代码中,注释掉的行是我当前的VIP实现。它们在函数定义中看起来不兼容,因为这只是部分解决方案 # from gi.repository import Vips def get_log_kernel(siz, std):

我有以下使用Python和OpenCV的代码。简单地说,我有一堆不同焦距的图像。代码在所有焦深(z)中具有最大拉普拉斯高斯响应的每个(x,y)位置拾取像素,从而创建聚焦堆叠图像。函数
get_fmap
创建一个2d阵列,其中每个像素将包含具有最大对数响应的焦平面的数量。在以下代码中,注释掉的行是我当前的VIP实现。它们在函数定义中看起来不兼容,因为这只是部分解决方案

# 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

log\u response
fmap
在问题代码中被初始化为3D数组,而问题文本说明输出
fmap
是2D数组。因此,我假设
log\u response
fmap
将被初始化为2D数组,其形状与每个图像相同。因此,编辑将是-

log_response = np.zeros_like(img[:,:,0], dtype='single')
fmap = np.zeros_like(img[:,:,0], dtype='uint8')
现在,回到问题的主题,您正在逐个对每个图像执行2D过滤,并获得所有堆叠图像中过滤输出的最大索引。在这种情况下,您不知道根据的文档,它也可以用于多维数组,给我们一个多维数组作为输出。然后,获取所有图像的最大索引非常简单,如
.argmax(2)
。因此,执行工作必须极为有效,而且将非常简单-

fmap = cv2.filter2D(img,-1,log_kernel).argmax(2)
在查阅了相关资料并尝试了一些错误之后,我已经想出了自己的答案。我的numpy和OpenCV实现可以转化为VIP,如下所示:

import pyvips

img = []
for ii in range(num_z_levels):
    img.append(pyvips.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]  # pyvips.Image.new_from_array takes 1-d list array.
    log_kernel = pyvips.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)

    for ii in range(len(img)):
        img_filtered = img[ii+1].conv(log_kernel)
        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>img2
img>5
。与wise一样,value\u if\u true可以是单个值或VIP图像。

谢谢。我在提供这个最小的示例时犯了一个错误。我已经编辑了我的帖子。很高兴知道
cv2.filter2d
有这样的用法。我一定要试一试。然而,VIP默认使用多核,而使用OpenCV时,我必须自己实现这一点。向OpenCV添加多处理也会增加一些开销。我认为
多处理
模块加上OpenCV的性能不会接近VIP。我用11x11内核在3000x4000图像上测试了高斯滤波。VIP在0.0025秒内完成任务。OpenCV花费了0.1334秒。@user3667217那么,您已经在VIP中实现了解决方案了吗?那么,在这里分享答案?嗯,直到今天我才从你那里听说这件事,所以谢谢!让我知道关于这个的任何其他想法!那个VIP,我看起来肯定很有趣。我还没有一个完整的VIP解决方案,这就是为什么我问如何在VIP中执行逻辑操作和索引。显然,VIP正在积极开发(目前已经有第8版),但鲜为人知。我所做的与现有的python手册没有太大的差距。我只让它执行高斯滤波,并使用我自己的内核进行滤波。我还在探索。我将在我的作品中介绍这些代码。贵宾真是太棒了。例如,它花费0.0011秒读取图像,而openCV花费0.043秒。只是速度快得让人难以置信。绝对值得一试@user3667217你和我分享的疯狂的东西!我的意思是我已经使用OpenCV很长时间了。所以,从你所说的来看,这个VIP似乎是一件新鲜事,绝对令人兴奋!总有一天我会试一试的。但在这个问题上,我认为我无法帮助VIP。如果有人对它有更多的见解,那就值得等待了。你有没有试过用TBB开发OpenCV?我上面的结果来自单线程OpenCV。OpenCV+TBB是一种选择,但我找不到很多例子。我还是不认为他们在一起的表现超过了VIP,Thoogh。但当然,VIP在执行的功能数量上要有限得多。我是VIP的维护者。你的代码看起来不错。您是否看到VIP
logmat
功能?这可能对你有用。它从Python中创建一个日志掩码,用作(例如)
Vips.Image.logmat(2,0.1)
。它将生成近似整数掩码和可分离掩码,这可以提供有用的加速。如果愿意,可以使用字符串
“float”
代替
Vips.Precision.float
。(第2部分)是否需要
索引
图像?我想你可以把它改写成
fmap=(img\u filtered>log\u response)。如果是其他(ii+1,0)
,我可能遗漏了什么。如果您有任何可以共享的基准测试,我会很好奇速度和内存使用与opencv相比如何;x、 matrixprint()查看VIP制作的日志垫。添加
precision=“float”
以获得浮点版本。哦,你是维护者!!谢谢你的评论。我上周刚开始使用VIP,但仍然很难找到所有东西的位置。我不能完全理解关于日志内核的等式。它和我的一样吗?(我刚把它贴在我的问题上)。我不需要索引图像,所以你的建议应该更好。图像轴被限制为2^31,像素为2^62的平方。我经常在笔记本电脑上处理200000 x 200000像素的幻灯片图像。它也可以在32位机器上制作这些巨大的图像,不过谢天谢地,现在这已经不那么重要了。
result_img = (test_condition).ifthenelse(value_if_true, value_if_false)