图像c ++,opencv中均匀性/同质性的测量
Posted
技术标签:
【中文标题】图像c ++,opencv中均匀性/同质性的测量【英文标题】:Measure of uniformity / homogeniy in an Image c++, opencv 【发布时间】:2017-09-27 09:30:13 【问题描述】:我想使用一个指标,它可以很好地表示灰度图像中的均匀性/均匀性。
这是一个非均匀图像的示例:
这是一个统一图像的示例:
关于什么是好的解决方案有什么想法吗??
编辑:图像没有恒定的比例,即图像的宽度和高度是变化的。添加更多上下文。我在一个项目中使用它来从侧视图 pov 区分公共汽车和卡车。所以我添加的两个图像是卡车和公共汽车两个***之间的区域。我观察到的是,该地区对于公共汽车来说是统一的,而对于卡车来说是不统一的。为了更精确地定义该区域,其宽度等于两个***之间的距离,高度等于整个***的高度。为什么我使用这个区域:因为我正在接收公共汽车和卡车的灰度图像。整个车辆没有必要适合图像,即很可能车辆的顶部(即略高于窗户)对我来说可能不可用,这就是这种方法的原因。
这里附加的图像是 RGB 格式,而我收到的项目图像是灰度级的。我没有必要收到整车的图像。下面的图片对我来说是最好的场景。
但是,这些区域并不固定,取决于公共汽车和卡车的大小。所以我想用一个度量来衡量这些区域的均匀性。
【问题讨论】:
请花时间阅读How to Ask问题。 为什么不只检查像素值的标准差? @PasserBy ...你能告诉我我应该在哪里改进吗?? 这是一个相当困难的问题。所有依赖灰度色散的方法本质上都是测量噪声/纹理,而不是均匀度。如果您告诉我们评估一致性的目的,也许这个问题会更容易回答。 嗯,就整个场景的不均匀性而言,我猜这两个图像之间没有显着差异。无论如何,它们比你想象的要相似得多。您最好依靠窗户的检测,或与这些车辆类型的先验形状相关的任何其他线索... 【参考方案1】:测试整个图像的局部均匀性的一种方法(有点幼稚)是反复模糊图像并将最近的模糊与之前的模糊之间的(绝对或平方)差异求和。例如,对于您的前两张图像,重复的模糊对类似渐变的图像的影响很小,而对于第一张图像,每次连续的变化都会大得多。考虑这个 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。
所以所有这些方法都至少会产生一个数量级的差异,这应该很容易检测到。但困难可能在于选择什么参数,高斯的标准差应该是多少,窗口的大小等。您可以尝试根据大小来确定它们,例如采用图像大小的一小部分的高斯窗口。
注意:这里我没有费心缩放图像大小;您应该将所有总和除以图像中的像素数(即取平均值),以使其具有比例不变性。
【讨论】:
【参考方案2】:我建议计算 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
类似的结果可以通过计算大窗口的DoG图像(高斯差),然后使用平均图像值作为度量(值越小图像越均匀)。
【讨论】:
欢迎来到 Stack Overflow!确实这是一个很好的方法,但最好是你可以扩展你的答案,以便其他没有专业知识的人可以理解为什么傅立叶系数的大小会给出这样的度量。不是每个来到这个网站的人都会知道傅里叶变换是什么/做什么:)。 两张车辆图像的 DFT 非常相似。 据我了解,车轮之间存在一些 ROI,其均匀性用于识别车辆。 比较模糊图像和清晰图像的光谱有什么关系?问题是关于统一与非统一的。 @YvesDaoust 均匀图像是可能“最模糊”的图像 - 它只有几个强度级别【参考方案3】:怎么样:
计算所有像素的平均值 然后将实际像素值的差异与计算的平均值相加?
图像中的多样性越多,计算值就越高 - 这应该可以粗略估计图像的均匀性/均匀性。
【讨论】:
抱歉编辑晚了,我想要一个独立于比例的指标。 可能还应该除以像素数。 @AyushPandey 可以解决缩放问题。此外,您需要采用绝对和或平方差,否则您可能会抵消(例如,如果图像是 50% 的白色,50% 的黑色)。 任何仅基于像素值直方图的方法,例如您的建议,都是不合适的。因为您可以拍摄任何图像并通过增加灰度级以扫描线顺序重新分配像素。这将使直方图完全保持不变,但图像看起来像一个完全平滑的渐变。 我已经添加了上下文。如果你能抽出一些时间来完成它。以上是关于图像c ++,opencv中均匀性/同质性的测量的主要内容,如果未能解决你的问题,请参考以下文章