如何量化两个图像之间的差异?
0 387
0

我定期对一种事物进行拍照,看图片有时看起来几乎是一样的,我想有某种方法可以量化这种差异,因为我必须凭借经验来确定一个阈值。 我使用python。

收藏
2021-01-27 11:06 更新 anna •  5042
共 1 个回答
高赞 时间
0

选项1:将两个图像都加载为数组(scipy.misc.imread),然后计算逐个元素(逐像素)的差异。计算差异的范数。

选项2:加载两个图像。计算每个特征向量的某些特征向量(如直方图)。计算特征向量之间的距离,而不是图像。

你应该首先回答以下问题: 1.图像的形状和尺寸是否相同? 如果没有,你可能需要调整大小或裁剪它们。使用Python的PIL库可以做到这一点。如果使用相同的设置和相同的设备拍摄它们,则它们可能是相同的。

2.图像是否正确对齐? 如果不是,则可能要先运行互相关,即首先找到最佳对齐方式。SciPy具有执行此功能的功能。如果相机和场景静止不动,则图像更可能对齐良好。

3.图像的曝光是否总是一样?(亮度/对比度是否相同?)

如果不是,则可能要对图像进行标准化。但是要小心,在某些情况下,这样做可能弊大于利。例如,深色背景上的单个明亮像素将使标准化图像非常不同。

4.颜色信息重要吗? 如果要注意颜色变化,则将计算每个点颜色值的向量,而不是灰度图像中的标量值。编写此类代码时,需要更多注意。

5.图像中是否有明显的边缘?他们可能会移动吗? 如果是,则可以先应用边缘检测算法(例如,使用Sobel或Prewitt变换计算梯度,应用一些阈值),然后将第一个图像上的边缘与第二个图像上的边缘进行比较。

6.图像中是否有噪点? 所有传感器都会在一定程度上污染图像。低成本传感器噪声更大。在比较图像之前一个进行一些降噪处理。在这里,模糊是最简单(但不是最好)的方法。

7.你想注意哪些变化? 这可能会影响要用于图像之间差异的标准的选择。考虑使用曼哈顿范数(绝对值的总和)或零范数(元素数量不等于零)来衡量图像变化了多少。前者将告诉你图像有哪些不同,后者将仅告诉你有多少像素不同。

举个例子 我假设图像对齐良好,大小和形状相同,并且可能具有不同的曝光度。为简单起见,即使它们是彩色(RGB)图像,我也将它们转换为灰度。 你将需要导入这些:

import sys
from scipy.misc import imread
from scipy.linalg import norm
from scipy import sum, average

主要功能,读取两个图像,转换为灰度,比较结果:

def main():
    file1, file2 = sys.argv[1:1+2]
    # read images as 2D arrays (convert to grayscale for simplicity)
    img1 = to_grayscale(imread(file1).astype(float))
    img2 = to_grayscale(imread(file2).astype(float))
    # compare
    n_m, n_0 = compare_images(img1, img2)
    print "Manhattan norm:", n_m, "/ per pixel:", n_m/img1.size
print "Zero norm:", n_0, "/ per pixel:", n_0*1.0/img1.size

如何比较。img1和img2是2D SciPy的阵列:

def compare_images(img1, img2):
    # normalize to compensate for exposure difference, this may be unnecessary
    # consider disabling it
    img1 = normalize(img1)
    img2 = normalize(img2)
    # calculate the difference and its norms
    diff = img1 - img2  # elementwise for scipy arrays
    m_norm = sum(abs(diff))  # Manhattan norm
    z_norm = norm(diff.ravel(), 0)  # Zero norm
return (m_norm, z_norm)

如果文件是彩色图像,则imread返回一个3D数组,平均RGB通道(最后一个数组轴)来获取强度。对于灰度图像(例如.pgm)无需这样做:

def to_grayscale(arr):
    "If arr is a color image (3D array), convert it to grayscale (2D array)."
    if len(arr.shape) == 3:
        return average(arr, -1)  # average over the last axis (color channels)
    else:
        return arr

标准化很简单,你可以选择标准化为[0,1]而不是[0,255]。arr是一个SciPy数组,因此所有操作都是按元素进行的:

def normalize(arr):
    rng = arr.max()-arr.min()
    amin = arr.min()
return (arr-amin)*255/rng

运行main函数:

if __name__ == "__main__":
    main()

现在,你可以将所有内容放入脚本中并运行两个图像。如果我们将图像与其自身进行比较,则没有区别:

$ python compare.py one.jpg one.jpg
Manhattan norm: 0.0 / per pixel: 0.0
Zero norm: 0 / per pixel: 0.0

如果我们模糊图像并与原始图像进行比较,则存在一些差异:

$ python compare.py one.jpg one-blurred.jpg 
Manhattan norm: 92605183.67 / per pixel: 13.4210411116
Zero norm: 6900000 / per pixel: 1.0

Via:https://stackoverflow.com/a/3935002/14964791

收藏
2021-01-27 12:12 更新 karry •  4540