正如它已经多次发布的那样:问题来自应用程序中相关性的不准确定义。
皮尔逊相关系数 确实要求数据是
- 居中,即必须减去平均值
- 归一化,即数据必须除以标准差
对于较大矩阵的每个子矩阵,也必须对掩码进行这种居中和归一化。
在您的示例中,您最终会得到一个相关矩阵:
⎛⎝⎜0.0−1.01.00.0−0.5770.5770.00.00.0⎞⎠⎟
让我们看一下矩阵条目:
0.0 它们在那里,因为其中有包含所有子矩阵的子矩阵。这样一个矩阵的平均值是 1,因此它以对应的矩阵为中心,只有零。因此相关性为零。
1.0 是您希望看到的相关性。对应的子矩阵完美拟合掩码,因此完全相关,即 1
-1.0 是适合掩码的子矩阵的相关性,但子矩阵条目是切换的(即子矩阵为 0,掩码为 1,反之亦然)。这是一个完美的反相关,即-1
0.577 情况:它们发生在子矩阵与掩码偏离一个数字的情况下(即掩码为 0 时为 1,反之亦然)。在您的示例中,它也恰好是一个对称情况,因此有一对与一个开关正相关,一个与相应开关负相关。
这是一个非常丑陋的蛮力代码来说明它。它既没有以任何方式进行优化,也没有针对您的任何其他情况进行测试。我希望它是正确的;)
import numpy as np
In [2]:
img = np.ones([4,4])
img[2,0:2] = 0.0
print(img)
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[0. 0. 1. 1.]
[1. 1. 1. 1.]]
In [3]:
mask = np.ones([2,2])
mask[0,0:2] = 0.0
print(mask)
[[0. 0.]
[1. 1.]]
In [4]:
def simple_convolve(img, mask):
max_row = img.shape[0] - mask.shape[0] + 1
max_col = img.shape[1] - mask.shape[1] + 1
output = np.zeros([max_row, max_col])
for curr_row in range(0, max_row):
for curr_col in range(0, max_col):
for curr_mask_row in range(0, mask.shape[0]):
for curr_mask_col in range(0, mask.shape[1]):
output[curr_row, curr_col] += img[curr_row + curr_mask_row, curr_col + curr_mask_col] * mask[curr_mask_row, curr_mask_col]
return output
def better_convolve(img, mask):
max_row = img.shape[0] - mask.shape[0] + 1
max_col = img.shape[1] - mask.shape[1] + 1
output = np.zeros([max_row, max_col])
mask_mean = mask.mean()
mask_sigma = (((mask - mask_mean)**2).sum())**0.5
mask = mask - mask_mean
mask = mask/mask_sigma
curr_img_mean = 0.0
curr_img_sigma = 0.0
for curr_row in range(0, max_row):
for curr_col in range(0, max_col):
curr_img_mean = 0.0
curr_img_sigma = 0.0
# Compute the mean value of the sub-image of img
ctr = 0.0
for curr_mask_row in range(0, mask.shape[0]):
for curr_mask_col in range(0, mask.shape[1]):
ctr = ctr + 1.0
curr_img_mean += img[curr_row + curr_mask_row, curr_col + curr_mask_col]
curr_img_mean = curr_img_mean / ctr
# Compute the std value of the sub-image of img
ctr = 0.0
for curr_mask_row in range(0, mask.shape[0]):
for curr_mask_col in range(0, mask.shape[1]):
ctr = ctr + 1.0
curr_img_sigma += (img[curr_row + curr_mask_row, curr_col + curr_mask_col] - curr_img_mean)**2.0
curr_img_sigma = curr_img_sigma**0.5
for curr_mask_row in range(0, mask.shape[0]):
for curr_mask_col in range(0, mask.shape[1]):
x = (img[curr_row + curr_mask_row, curr_col + curr_mask_col] - curr_img_mean)
if curr_img_sigma == 0.0:
x = 0.0
else:
x = x/curr_img_sigma
output[curr_row, curr_col] += x * mask[curr_mask_row, curr_mask_col]
return output
In [5]:
simple_convolve(img, mask)
Out[5]:
array([[2., 2., 2.],
[0., 1., 2.],
[2., 2., 2.]])
In [6]:
better_convolve(img, mask)
Out[6]:
array([[ 0. , 0. , 0. ],
[-1. , -0.57735027, 0. ],
[ 1. , 0.57735027, 0. ]])