图像 c++、opencv 中均匀性/同质性的测量

Measure of uniformity / homogeniy in an Image c++, opencv

我想使用一个度量标准,它可以很好地表示灰度图像中的均匀性/均匀性。

这是一个非均匀图像的例子:

这是统一图像的示例:

有什么好的解决方案吗??

编辑:图像没有恒定的比例,即图像的宽度和高度是变化的。添加更多上下文。我在一个项目中使用它来从侧视图 pov 区分公共汽车和卡车。所以我添加的两个图像是卡车和公共汽车两个轮子之间的区域。我观察到的是,该区域对于公共汽车来说是统一的,而对于卡车来说是不统一的。为了更精确地定义该区域,其宽度等于两个车轮之间的距离,高度等于整个车轮的高度。为什么我使用这个区域:因为我正在接收公共汽车和卡车的灰度图像。没有必要让整个车辆都适合图像,即很可能车辆的顶部,即略高于 window 的部分对我来说可能不可用,这就是为什么采用这种方法。

这里的附加图像是 RGB,而我收到的项目图像是灰度。我没有必要收到整车的图像。下面的图片对我来说是最好的场景。

然而,这些区域不是恒定的,取决于公共汽车和卡车的大小。所以我想用一个指标来衡量这些区域的均匀性。

怎么样:

  • 计算所有像素的平均值
  • 然后将实际像素值与计算平均值的差异相加

?

图像中的多样性越多,计算值就越高 - 这应该可以粗略估计图像的同质性/均匀性。

我建议计算 2D FFT(快速傅立叶变换)。

https://en.wikipedia.org/wiki/Fast_Fourier_transform

它会将我们的图像强度域更改为频域。如果您计算变换结果的幅度,它将产生这样的图像(下图和结果示例): .

下面我附上了两张图片——左边不太均匀,右边比较均匀。您可以在下面看到频域的差异:

您可以计算位于图像中心附近的信号的信噪比(作为图像大小的百分比)。该比率可以很容易地用作度量标准。 FFT 方法在这里有很好的描述:https://books.google.pl/books?id=97QebyNxyaYC&pg=PA51&lpg=PA51&dq=2dFFT+extract+mean+value&source=bl&ots=wV8kc-TrI-&sig=N35TiT3aI5HCYjop6_ORxCpBPMk&hl=pl&sa=X&ved=0ahUKEwikzP7VkMXWAhWCA5oKHfKEDVcQ6AEIMTAB#v=onepage&q=2dFFT%20extract%20mean%20value&f=false

另一个特征提取:http://cns-classes.bu.edu/cn550/Lectures/Lecture13.pdf

计算大window的DoG图像(高斯差值),然后用平均图像值作为度量(值越小图像越均匀),也可以得到类似的结果。

一种测试图像局部均匀性的方法(有点天真)是反复模糊图像并对最近模糊与之前模糊之间的(绝对或平方)差异求和。例如,对于您的前两张图像,重复模糊只会对类似渐变的图像产生很小的变化,而对于第一张图像,第一次连续的变化会大得多。考虑这个 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 Non-uniform: 0.010601
SSD Uniform: 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)

Non-uniform blur count: 79
Uniform blur count: 5

您可以读取这些值,如 "number of blurs until homogeneity." 如果您使阈值更小,比如 0.01,那么实际上 while 循环的单个 运行(即两个模糊)得到你所说的图像在阈值下大多是同质的。本例中,两者之比约为16。


如果您为上述方法中的每个连续模糊绘制 SSD,您将看到如下内容:

很明显,其中一条线位于另一条线之上。当然,不太均匀的图像在每个模糊之间具有更高的总和差异,它应该或多或少地保持在顶部,尤其是在开始时。第一种方法类似于在一定数量的迭代中绘制一条垂直线,并在该位置取最小值将对应于更均匀的图像。第二种方法类似于画一条水平线,然后说 "whichever line hits this first is the homogeneous one." 不同的方向,相似的想法。然而 另一个 思路与此相同:您可以检查 SSD 中 change 之间的区别。这就像 "whenever the slope becomes mostly horizontal between two points, the image is homogenous." 一样简单,而且这当然发生在迭代次数的早期。


另一种流行的模糊方法是取两个不同模糊的差异;又名高斯差分 。这种方法有时用于查找图像中的边缘;如果两个模糊之间存在很大差异,那是因为图像中某些点(如边缘)对模糊有一些不同的响应。但如果它们或多或少类似地模糊,则图像非常平滑。

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 Non-uniform DoG: 0.416841
SSD Uniform DoG: 0.026028

这里的比率大约是 20。


所以所有这些方法之间至少产生一个数量级的差异,应该很容易检测到。但是困难在于选择什么参数,高斯的标准偏差应该是多少,window 的大小等。您可以 尝试将它们作为基础尺寸,例如采用高斯windows,这是图像大小的一小部分。

注意:这里我没有为图像大小缩放;您应该将所有总和除以图像中的像素数(即取平均值)以使其具有比例不变性。