测试整个图像的局部均匀性的一种方法(有点幼稚)是反复模糊图像并将最近的模糊与之前的模糊之间的(绝对或平方)差异求和。例如,对于您的前两张图像,重复的模糊对类似渐变的图像的影响很小,而对于第一张图像,每次连续的变化都会大得多。考虑这个 Python 程序:
import cv2
import numpy as np
non = cv2.imread('img1.jpg', 0).astype(np.float32)/255
uni = cv2.imread('img2.jpg', 0).astype(np.float32)/255
blur_non = cv2.GaussianBlur(non, (11, 11), 2)
blur_uni = cv2.GaussianBlur(uni, (11, 11), 2)
for i in range(10):
blur_non = cv2.GaussianBlur(blur_non, (11, 11), 2)
blur_uni = cv2.GaussianBlur(blur_uni, (11, 11), 2)
last_blur_non = cv2.GaussianBlur(blur_non, (11, 11), 2)
last_blur_uni = cv2.GaussianBlur(blur_uni, (11, 11), 2)
ssd_blur_non = np.sum((last_blur_non - blur_non)**2)
ssd_blur_uni = np.sum((last_blur_uni - blur_uni)**2)
print('SSD Non-uniform: %f' % ssd_blur_non)
print('SSD Uniform: %f' % ssd_blur_uni)
SSD 不均匀:0.010601
SSD 统一:0.000321
所以我们可以在这里看到,均匀图像的最后两个模糊之间的平方差之和比非均匀图像的小 33 倍。
可以通过设置阈值并查看在差异低于阈值之前需要多少模糊来制定另一个指标:
thresh = 1e-3
blur_count_non = 0
prev_blur_non = cv2.GaussianBlur(non, (11, 11), 2)
blur_non = cv2.GaussianBlur(blur_non, (11, 11), 2)
ssd_blur_non = np.sum((blur_non - prev_blur_non)**2)
while(ssd_blur_non > thresh):
blur_non = cv2.GaussianBlur(prev_blur_non, (11, 11), 2)
ssd_blur_non = np.sum((blur_non - prev_blur_non)**2)
prev_blur_non = blur_non
blur_count_non += 1
blur_count_uni = 0
prev_blur_uni = cv2.GaussianBlur(uni, (11, 11), 2)
blur_uni = cv2.GaussianBlur(blur_uni, (11, 11), 2)
ssd_blur_uni = np.sum((blur_uni - prev_blur_uni)**2)
while(ssd_blur_uni > thresh):
blur_uni = cv2.GaussianBlur(prev_blur_uni, (11, 11), 2)
ssd_blur_uni = np.sum((blur_uni - prev_blur_uni)**2)
prev_blur_uni = blur_uni
blur_count_uni += 1
print('Non-uniform blur count: %d' % blur_count_non)
print('Uniform blur count: %d' % blur_count_uni)
非均匀模糊计数:79
均匀模糊数:5
您可以阅读这些值,例如“直到同质化之前的模糊次数”。如果您使阈值更小,例如 0.01,那么实际上单次运行 while 循环(即两次模糊)会得到您所说的图像在阈值下大部分是同质的。在本例中,两者的比值约为 16。
如果您为上述方法中的每个连续模糊绘制 SSD,您将看到如下内容:
很明显,其中一条线位于另一条线之上。当然,不太均匀的图像在每次模糊之间的总和差异更大,它应该或多或少地保持在顶部,尤其是在开始时。第一种方法类似于在一定次数的迭代中绘制一条垂直线,并在该位置取最小值将对应于更均匀的图像。第二种方法类似于画一条水平线,然后说“哪条线先碰到这条线就是同质线”。不同的方向,相似的想法。然而另一个的想法是相同的:你可以检查SSD中变化之间的区别。这就像“当两点之间的斜率大部分变为水平时,图像是同质的”一样简单。当然,这发生在迭代次数的早期。
另一种流行的模糊方法是取两种不同模糊的差异;又名高斯差为Kamil mentioned。此方法有时用于查找图像中的边缘;如果两个模糊之间存在很大差异,那是因为在图像中的某个点(例如边缘)对模糊有一些不同的响应。但如果它们或多或少类似地模糊,则图像非常平滑。
blur1_non = cv2.GaussianBlur(non, (7, 7), 1)
blur2_non = cv2.GaussianBlur(non, (31, 31), 2)
ssd_blur_non = np.sum((blur1_non - blur2_non)**2)
blur1_uni = cv2.GaussianBlur(uni, (7, 7), 1)
blur2_uni = cv2.GaussianBlur(uni, (31, 31), 2)
ssd_blur_uni = np.sum((blur1_uni - blur2_uni)**2)
print('SSD Non-uniform DoG: %f' % ssd_blur_non)
print('SSD Uniform DoG: %f' % ssd_blur_uni)
SSD 非均匀 DoG:0.416841
SSD 统一狗:0.026028
这里的比例大约是 20。
所以所有这些方法都至少会产生一个数量级的差异,这应该很容易检测到。但困难可能在于选择什么参数,高斯的标准差应该是多少,窗口的大小等。您可以尝试根据大小来确定它们,例如采用图像大小的一小部分的高斯窗口。
注意:这里我没有费心缩放图像大小;您应该将所有总和除以图像中的像素数(即取平均值),以使其具有比例不变性。