Python中如何使用VIPS进行逻辑运算和逻辑索引?
How to perform logical operation and logical indexing using VIPS in Python?
我有以下使用 Python 和 OpenCV 的代码。简而言之,我有一堆在不同焦深下拍摄的图像。代码在所有焦深 (z) 中挑选出具有最大高斯拉普拉斯响应的每个 (x,y) 位置的像素,从而创建焦点堆叠图像。函数 get_fmap
创建一个二维数组,其中每个像素将包含具有最大对数响应的焦平面的编号。在下面的代码中,被注释掉的行是我当前的 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 绑定的信息很少。根据我在 Internet 上可以找到的信息,我只能使图像卷积起作用(在我的例子中,它比 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
log_response
和 fmap
在问题代码中被初始化为 3D 数组,而问题文本指出输出 fmap
是一个二维数组。因此,我假设 log_response
和 fmap
将被初始化为二维数组,其形状与每个图像相同。因此,编辑将是 -
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)
在查阅 Python VIPS manual 和一些反复试验之后,我得出了自己的答案。我的 numpy 和 OpenCV 实现可以像这样翻译成 VIPS:
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
。同样,value_if_true 可以是单个值或 Vips 图像。
我有以下使用 Python 和 OpenCV 的代码。简而言之,我有一堆在不同焦深下拍摄的图像。代码在所有焦深 (z) 中挑选出具有最大高斯拉普拉斯响应的每个 (x,y) 位置的像素,从而创建焦点堆叠图像。函数 get_fmap
创建一个二维数组,其中每个像素将包含具有最大对数响应的焦平面的编号。在下面的代码中,被注释掉的行是我当前的 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 绑定的信息很少。根据我在 Internet 上可以找到的信息,我只能使图像卷积起作用(在我的例子中,它比 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
log_response
和 fmap
在问题代码中被初始化为 3D 数组,而问题文本指出输出 fmap
是一个二维数组。因此,我假设 log_response
和 fmap
将被初始化为二维数组,其形状与每个图像相同。因此,编辑将是 -
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)
在查阅 Python VIPS manual 和一些反复试验之后,我得出了自己的答案。我的 numpy 和 OpenCV 实现可以像这样翻译成 VIPS:
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
。同样,value_if_true 可以是单个值或 Vips 图像。