gpt4 book ai didi

python - NumPy 模板匹配 SQDIFF 与 `sliding window_view`

转载 作者:行者123 更新时间:2023-12-04 07:27:56 25 4
gpt4 key购买 nike

SQDIFF 定义为 openCV definition . (我相信他们省略了 channel )
SQDIFF
在初级 numpy Python 中应该是

A = np.arange(27, dtype=np.float32)
A = A.reshape(3,3,3) # The "image"
B = np.ones([2, 2, 3], dtype=np.float32) # window
rw, rh = A.shape[0] - B.shape[0] + 1, A.shape[1] - B.shape[1] + 1 # End result size
result = np.zeros([rw, rh])
for i in range(rw):
for j in range(rh):
w = A[i:i + B.shape[0], j:j + B.shape[1]]
res = B - w
result[i, j] = np.sum(
res ** 2
)
cv_result = cv.matchTemplate(A, B, cv.TM_SQDIFF) # this result is the same as the simple for loops
assert np.allclose(cv_result, result)
这是相对较慢的解决方案。我读过 sliding_window_view但不能正确。
# This will fail with these large arrays but is ok for smaller ones
A = np.random.rand(1028, 1232, 3).astype(np.float32)
B = np.random.rand(248, 249, 3).astype(np.float32)
locations = np.lib.stride_tricks.sliding_window_view(A, B.shape)
sqdiff = np.sum((B - locations) ** 2, axis=(-1,-2, -3, -4)) # This will fail with normal sized images
将失败 MemoryError即使结果很容易符合内存。我怎样才能产生与 cv2.matchTemplate 类似的结果以这种更快的方式运行?

最佳答案

作为最后的手段,您可以在切片中执行计算,而不是“一次性”计算。np.lib.stride_tricks.sliding_window_view返回 查看 的数据,所以它不会消​​耗大量的内存。
表达式 B - locations不能使用 View ,并且需要 RAM 来存储形状为 (781, 984, 1, 248, 249, 3) 的浮点元素数组。
用于存储的总 RAM B - locations781*984*1*248*249*3*4 = 569,479,908,096 字节。

为了避免需要存储B - locations立即在 RAM 中,我们可以计算 sqdiff在瓦片中,当“瓦片”计算需要较少的 RAM 时。
一个简单的瓷砖划分使用每一行作为一个瓷砖 - 在 sqdiff 的行上循环,并逐行计算输出。
例子:

sqdiff = np.zeros((locations.shape[0], locations.shape[1]), np.float32)  # Allocate an array for storing the result.

# Compute sqdiff row by row instead of computing all at once.
for i in range(sqdiff.shape[0]):
sqdiff[i, :] = np.sum((B - locations[i, :, :, :, :, :]) ** 2, axis=(-1, -2, -3, -4))

可执行代码示例:
import numpy as np
import cv2

A = np.random.rand(1028, 1232, 3).astype(np.float32)
B = np.random.rand(248, 249, 3).astype(np.float32)
locations = np.lib.stride_tricks.sliding_window_view(A, B.shape)

cv_result = cv2.matchTemplate(A, B, cv2.TM_SQDIFF) # this result is the same as the simple for loops

#sqdiff = np.sum((B - locations) ** 2, axis=(-1, -2, -3, -4)) # This will fail with normal sized images

sqdiff = np.zeros((locations.shape[0], locations.shape[1]), np.float32) # Allocate an array for storing the result.

# Compute sqdiff row by row instead of computing all at once.
for i in range(sqdiff.shape[0]):
sqdiff[i, :] = np.sum((B - locations[i, :, :, :, :, :]) ** 2, axis=(-1, -2, -3, -4))

assert np.allclose(cv_result, sqdiff)

我知道这个解决方案有点令人失望……但它是我能找到的唯一通用解决方案。

关于python - NumPy 模板匹配 SQDIFF 与 `sliding window_view`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68122570/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com