我想使用一个度量标准,它可以很好地表示灰度图像中的均匀性/均匀性。
这是非均匀图像的示例:
这是统一图像的示例:
关于什么是好的解决方案的任何想法?
编辑:图像没有恒定的比例,即图像的宽度和高度是变化的。添加更多上下文。我在一个项目中使用它来从侧 View pov 区分公共(public)汽车和卡车。所以我添加的两个图像是卡车和公共(public)汽车两个轮子之间的区域。我观察到的是,该地区对于公共(public)汽车来说是统一的,而对于卡车来说是不统一的。为了更精确地定义该区域,其宽度等于两个轮子之间的距离,高度等于整个轮子的高度。为什么我使用这个区域:因为我正在接收公共(public)汽车和卡车的灰度图像。整个车辆没有必要适合图像,即车辆的顶部(即略高于 window )可能对我不可用,这就是为什么这种方法的原因。
这里附加的图像是 RGB 的,而我收到的项目图像是灰度的。我没有必要收到整车的图像。下面的图片对我来说是最好的情况。
然而,这些区域不是恒定的,取决于公共(public)汽车和卡车的大小。所以我想用一个度量来测量这些区域的均匀性。
最佳答案
一种测试整个图像的局部均匀性的方法(有点幼稚)是反复模糊图像并将最近的模糊与之前的模糊之间的(绝对或平方)差异相加。例如,对于您的前两张图像,重复的模糊对类似渐变的图像的影响很小,而对于第一张图像,每次连续的变化都会大得多。考虑这个 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
您可以阅读这些值,例如“直到同质化的模糊数量”。如果您将阈值设置得更小,例如 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 Non-uniform DoG: 0.416841
SSD Uniform DoG: 0.026028
这里的比率大约是 20。
所以所有这些方法都会在它们之间产生至少一个数量级的差异,这应该很容易检测到。但困难可能在于选择什么参数,高斯的标准偏差应该是多少,窗口的大小等。您可以尝试根据大小来确定它们,例如采用高斯窗口,它是图像大小的一小部分。
注意 :这里我没有费心缩放图像大小;您应该将所有总和除以图像中的像素数(即取平均值),以使其具有比例不变性。
关于c++ - 图像c++,opencv中均匀性/同质性的测量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46444286/