这里就是我想要做到:

我拍照的一个网络摄像头在固定的时间间隔。有点像一个时间间隔的事情。然而,如果没有真正改变,那就是,很多图片 看起来 同样,我不想要保存最新的快照。

我想有一些办法的量化差异,并且我将要凭经验确定一个阈值。

我在寻找简单,而不是完美的。我使用的是蟒蛇。

有帮助吗?

解决方案

总的想法

备选案文1:负载的这两个图像作为阵列(scipy.misc.imread)和计算元件明智的(像素素)的差别。计算的规范的差别。

备选2:负载的这两个图像。计算某些要素的矢量的每个的他们(像一个柱状图)。计算之间的距离要素的矢量,而不是图像。

然而,有一些决定作出第一次。

的问题

你应该回答这些问题,首先:

  • 是图像的相同的形状和尺寸?

    如果不是,可能需要调整或作物。PIL库将帮助做到这一点在蟒蛇。

    如果他们采用相同的设置和相同的设备,他们可能是相同的。

  • 是的图像以及对齐?

    如果不是,你可能会想要跑的交叉相关的第一个,找到更好的准的第一个。这具有的功能做到这一点。

    如果摄像机和现场仍然是,图像的可能以及对齐。

  • 是曝光影像总是一样的吗?(是明度/对比,同样的?)

    如果不是,您可能想要 恢复正常 图像。

    但是要小心,在一些情况下,这个可以做更多的是错误的。例如,一个单一的亮点在一个黑暗的背景将使图像的归一化非常不同。

  • 是颜色的重要信息?

    如果你想要通知的颜色变化,你将会有一矢量的颜色值每点,而不是一个标值作为在灰度的图像。你需要更多注意在编写这样的代码。

  • 都有不同的图像中的边缘?可能是他们的移动?

    如果是的话,你可以适用的边缘探测算法第(例如梯度计算与Sobel或Prewitt变换,适用于一些阈值),然后进行比较边缘上的第一次图像的边缘。

  • 是有噪音像?

    所有的传感器污染的图像与一些噪声量。低成本的传感器具有更多噪音。你可能希望适用于一些噪音减少之前,你比较的图像。模糊是最简单(但不是最好的)的方式在这里。

  • 什么样的改变你想的通知?

    这可能会影响的选择标准使用之间的差异的图像。

    考虑使用曼哈顿的准则(总和的绝对值)或零规范(元件的数目不等于零)来衡量有多少像已经改变。前者将告诉你多少像是关闭的,后者将告诉唯一像素的不同而不同。

我猜你的图像以及对齐,同样大小和形状,可能有不同的接触。为了简单起见,我将它们转化为灰度,即使他们的颜色(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

如何进行比较。 img1img2 是2D这阵列:

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 是这一阵列在这里,因此,所有操作元件明智的:

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

P.S.整个 compare.py 脚本。

更新:相关技术

作为该问题是关于一个视频序,其框架是可能几乎相同,你看起来不寻常的东西,我想提及的一些替代办法,这可能是相关的:

  • 背景差和分段(检测前景的对象)
  • 疏光流(检测运动)
  • 比较图或某些其他统计数据,而不是图像

我强烈建议你考虑看看"学习开源"的书,Chapters9(图像零部件和分段)和10(追踪和运动)。前教使用的背景减的方法,后者提供了一些信息光流的方法。所有的方法都是实现在该版本的图书馆。如果您使用的蟒蛇,我建议使用开源≥2.3,并且它的 cv2 蟒蛇的模块。

最简单的版本背景减:

  • 学习的平均值μ和标准偏差σ每一象素的背景
  • 比较前素值的范围(μ-2σ,μ+2σ)或(μ-∑,μ+σ)

更先进的版本使考虑到时间序列的每一像素和处理非静态的场景(如移动树木或草).

这个想法的光流是采取两个或多个框架,并分配速度,矢量的每一像素(密光流),或他们中的一些(稀疏光流动)。估计疏光流,可以使用 卢卡斯计方法 (这也是实现在该版本).显然,如果有大量的流动(高平均在最大值的速度字段),那么什么是移动的框架,并随后的图像更大的不同。

比较图可以帮助侦测的突然变化之间连续的框架。这个方法用在 Courbon et al.,2010年:

相似的连续的框架。 之间的距离两个连续的框架进行测量。如果太高,它意味着第二架而被损坏,并因此将图像被消除。的 克–莱距离, 或共同熵,在柱状图的两个框架:

$$ d(p,q) = \sum_i p(i) \log (p(i)/q(i)) $$

哪里 pq 是的直方图的框架是使用。阈值固定在0.2.

其他提示

一个简单的解决方案:

将图像编码为 jpeg ,并在 filesize 中查找实质性更改。

我已经实现了类似于视频缩略图的功能,并且具有很多成功和可扩展性。

您可以使用 PIL 中的功能比较两个图像。

import Image
import ImageChops

im1 = Image.open("splash.png")
im2 = Image.open("splash2.png")

diff = ImageChops.difference(im2, im1)

diff对象是这样的图像,其中每个像素是从第一图像中减去第二图像中的该像素的颜色值的结果。使用差异图像,您可以做几件事。最简单的是diff.getbbox()功能。它将告诉您包含两个图像之间所有更改的最小矩形。

您可以使用PIL中的函数实现此处提到的其他内容的近似值。

两种流行且相对简单的方法是:(a)已经建议的欧几里德距离,或(b)归一化的互相关。与简单的互相关相比,归一化的互相关对于光照变化往往更加稳健。维基百科给出了规范化互相关的公式。也存在更复杂的方法,但它们需要更多的工作。

使用类似numpy的语法,

dist_euclidean = sqrt(sum((i1 - i2)^2)) / i1.size

dist_manhattan = sum(abs(i1 - i2)) / i1.size

dist_ncc = sum( (i1 - mean(i1)) * (i2 - mean(i2)) ) / (
  (i1.size - 1) * stdev(i1) * stdev(i2) )

假设i1i2是2D灰度图像数组。

尝试一件微不足道的事情:

将两个图像重新采样为小缩略图(例如64 x 64),并将缩略图逐个像素地与特定阈值进行比较。如果原始图像几乎相同,则重新采样的缩略图将非常相似或甚至完全相同。该方法处理可能发生的噪声,尤其是在低光场景中。如果你去灰度可能会更好。

我解决具体问题,如何计算,如果他们是"不够"。我想你能弄明白如何减素之一。

首先,我要采取一堆图像 没有什么 改变,并找出最大数量的任何像素的变化,只是因为变化的捕获、噪声成像系统,JPEG压缩的文物,并且每时每刻变化的照明。也许你会发现,1或2位的差异是可以预期的,即使在没有移动。

然后对于"真正的"试验,你想要一个标准是这样的:

  • 同样,如果达到P素相差不超过E.

所以,也许,如果E=0.02,P=1000,这将意味着(大约),这将是"不同的"如果任何单一像素的变化超过-5的单位(假设的8位图片),或者,如果超过1000素有任何错误。

这是目的主要是作为一个很好的"分类"技术的迅速识别的图像,是密切足以不需要进一步审查。图像,"不"然后可能更多,更详细/昂贵的技术,就不会有误报,如果摄像机摇摇位,例如,或是更强大到光照的变化。

我运行开放源项目, OpenImageIO, 包含一个实用工具称为"idiff"比较差异与阈值这样的(甚至更复杂,实际上).甚至如果你不想使用这个软件,你可能想看看源来看看我们如何做它。这是使用商业上相当一点和这个阈值技术的开发,以便我们可以有一个测试呈现和图像处理软件,用"参考图像",可能有微小差异,从平台到平台上,或者作为我们做了一些小的调整,以tha算法,所以我们想要一个"匹配内容的"操作。

给出的大部分答案都不会涉及照明等级。

在进行比较之前,我首先将图像标准化为标准光照水平。

另一种测量两幅图像之间相似性的简单方法:

import sys
from skimage.measure import compare_ssim
from skimage.transform import resize
from scipy.ndimage import imread

# get two images - resize both to 1024 x 1024
img_a = resize(imread(sys.argv[1]), (2**10, 2**10))
img_b = resize(imread(sys.argv[2]), (2**10, 2**10))

# score: {-1:1} measure of the structural similarity between the images
score, diff = compare_ssim(img_a, img_b, full=True)
print(score)

如果其他人对比较图像相似性的更有效方法感兴趣,我将教程和网页应用程序,用于使用类似图像进行测量和可视化Tensorflow。

我在工作中遇到了类似的问题,我正在重写我们的图像转换端点,我想检查新版本是否与旧版本产生相同或几乎相同的输出。所以我写了这个:

https://github.com/nicolashahn/diffimg

对相同大小的图像进行操作,并以每像素级别测量每个通道的值差异:R,G,B(,A),取这些通道的平均差异,然后取平均值所有像素的差异,并返回一个比率。

例如,对于10x10的白色像素图像,并且相同的图像但是一个像素已变为红色,该像素的差异为1/3或0.33 ...(RGB 0,0,0对255, 0,0)和所有其他像素为0.总共100个像素,0.33 ... / 100 =图像差异〜0.33%。

我相信这对于OP的项目非常有用(我意识到这是一个非常古老的帖子,但是发布给未来的StackOverflowers,他们也希望在python中比较图像)。

您是否看过查找类似图片的算法问题?看看是否有建议。

我建议对你的帧进行小波变换(我用Haar变换写了一个C扩展名);然后,比较两张图片中最大(按比例)小波因子的指标,你应该得到一个数值相似近似。

我很抱歉,如果回复已经太晚了,但是因为我一直在做类似的事情,我认为我可以以某种方式做出贡献。

也许使用OpenCV,您可以使用模板匹配。假设你正在使用网络摄像头,如你所说:

  1. 简化图像(可能是阈值处理?)
  2. 应用模板匹配并使用minMaxLoc检查max_val
  3. 提示:max_val(或min_val取决于所使用的方法)将为您提供数字,大数字。要获得百分比差异,请使用与同一图像匹配的模板 - 结果将是您的100%。

    伪代码示例:

    previous_screenshot = ...
    current_screenshot = ...
    
    # simplify both images somehow
    
    # get the 100% corresponding value
    res = matchTemplate(previous_screenshot, previous_screenshot, TM_CCOEFF)
    _, hundred_p_val, _, _ = minMaxLoc(res)
    
    # hundred_p_val is now the 100%
    
    res = matchTemplate(previous_screenshot, current_screenshot, TM_CCOEFF)
    _, max_val, _, _ = minMaxLoc(res)
    
    difference_percentage = max_val / hundred_p_val
    
    # the tolerance is now up to you
    

    希望它有所帮助。

如何计算两张图片的曼哈顿距离。这给你n * n值。然后你可以做一些像行平均值来减少n值和一个函数来获得一个单值。

我在三脚架上使用相同的相机拍摄的jpg图像有很多运气 (1)大大简化(如从3000像素宽到100像素宽甚至更少) (2)将每个jpg阵列展平成单个矢量 (3)将序列图像与简单相关算法成对相关,得到相关系数 (4)求相关系数得到r平方(即一个图像中的变异部分由下一个变化解释) (5)一般在我的申请中,如果r-square <!> lt; 0.9,我说这两个图像是不同的,之间发生了一些事情。

这在我的实现中非常强大且快速(Mathematica 7)

值得玩一下您感兴趣的图像部分并通过将所有图像裁剪到该小区域来进行聚焦,否则将远离相机,但重要的变化将被遗漏。

我不知道如何使用Python,但我确定它也有相关性,不是吗?

您可以计算两幅图像的直方图,然后计算出 Bhattacharyya系数,这是一个非常快速的算法,我用它来检测板球视频中的镜头变化(在C中使用openCV)

查看 isk-daemon 如何实施Haar Wavelet。您可以使用它的imgdb C ++代码来计算动态图像之间的差异:

  

isk-daemon是一个开源数据库服务器,能够将基于内容的(可视)图像搜索添加到任何与图像相关的网站或软件。

     

该技术允许任何与图像相关的网站或软件的用户在小工具上绘制他们想要找到的图像,并让网站回复最相似的图像,或者只是在每个图像细节页面上请求更多类似的照片。

我遇到了同样的问题并编写了一个简单的python模块,它使用枕头的ImageChops比较两个相同大小的图像,以创建黑/白差异图像并总结直方图值。

您可以直接获得此分数,或者与完整黑色与白色差异相比获得百分比值。

它还包含一个简单的is_equal函数,可以在图像传递下(并包括)提供模糊阈值。

这种方法不是很精细,但也许可以用于解决同一问题的其他人。

https://pypi.python.org/pypi/imgcompare/

一种更有原则性的方法是使用全局描述符来比较图像,例如GIST或CENTRIST。哈希函数,如此处所述,提供了类似的解决方案。

import os
from PIL import Image
from PIL import ImageFile
import imagehash

#just use to the size diferent picture
def compare_image(img_file1, img_file2):
    if img_file1 == img_file2:
        return True
    fp1 = open(img_file1, 'rb')
    fp2 = open(img_file2, 'rb')

    img1 = Image.open(fp1)
    img2 = Image.open(fp2)

    ImageFile.LOAD_TRUNCATED_IMAGES = True
    b = img1 == img2

    fp1.close()
    fp2.close()

    return b





#through picturu hash to compare
def get_hash_dict(dir):
    hash_dict = {}
    image_quantity = 0
    for _, _, files in os.walk(dir):
        for i, fileName in enumerate(files):
            with open(dir + fileName, 'rb') as fp:
                hash_dict[dir + fileName] = imagehash.average_hash(Image.open(fp))
                image_quantity += 1

    return hash_dict, image_quantity

def compare_image_with_hash(image_file_name_1, image_file_name_2, max_dif=0):
    """
    max_dif: The maximum hash difference is allowed, the smaller and more accurate, the minimum is 0.
    recommend to use
    """
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    hash_1 = None
    hash_2 = None
    with open(image_file_name_1, 'rb') as fp:
        hash_1 = imagehash.average_hash(Image.open(fp))
    with open(image_file_name_2, 'rb') as fp:
        hash_2 = imagehash.average_hash(Image.open(fp))
    dif = hash_1 - hash_2
    if dif < 0:
        dif = -dif
    if dif <= max_dif:
        return True
    else:
        return False


def compare_image_dir_with_hash(dir_1, dir_2, max_dif=0):
    """
    max_dif: The maximum hash difference is allowed, the smaller and more accurate, the minimum is 0.

    """
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    hash_dict_1, image_quantity_1 = get_hash_dict(dir_1)
    hash_dict_2, image_quantity_2 = get_hash_dict(dir_2)

    if image_quantity_1 > image_quantity_2:
        tmp = image_quantity_1
        image_quantity_1 = image_quantity_2
        image_quantity_2 = tmp

        tmp = hash_dict_1
        hash_dict_1 = hash_dict_2
        hash_dict_2 = tmp

    result_dict = {}

    for k in hash_dict_1.keys():
        result_dict[k] = None

    for dif_i in range(0, max_dif + 1):
        have_none = False

        for k_1 in result_dict.keys():
            if result_dict.get(k_1) is None:
                have_none = True

        if not have_none:
            return result_dict

        for k_1, v_1 in hash_dict_1.items():
            for k_2, v_2 in hash_dict_2.items():
                sub = (v_1 - v_2)
                if sub < 0:
                    sub = -sub
                if sub == dif_i and result_dict.get(k_1) is None:
                    result_dict[k_1] = k_2
                    break
    return result_dict


def main():
    print(compare_image('image1\\815.jpg', 'image2\\5.jpg'))
    print(compare_image_with_hash('image1\\815.jpg', 'image2\\5.jpg', 6))
    r = compare_image_dir_with_hash('image1\\', image2\\', 10)
    for k in r.keys():
        print(k, r.get(k))


if __name__ == '__main__':
    main()
  • 输出:


    真的
    image2\5.jpg image1\815.jpg
    image2\6.jpg image1\819.jpg
    image2\7.jpg image1\900.jpg
    image2\8.jpg image1\998.jpg
    image2\9.jpg image1\1012.jpg

  • 例如图片:

    • 815.jpg
      815.jpg

    • 5.jpg
      5.jpg

我认为您可以简单地计算两个图像的亮度之间的欧氏距离(即sqrt(差异的平方和,逐个像素)),并且如果它落在某个经验阈值之下则认为它们相等。你最好把它包装成一个C函数。

有许多指标用于评估两个图像是否看起来像/看起来多少。

我不会在这里使用任何代码,因为我认为它应该是一个科学问题,而不是技术问题。

一般来说,问题与人类对图像的感知有关,因此每种算法都支持人类视觉系统特征。

经典方法是:

可见差异预测器:用于评估图像保真度的算法( https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1666/0000 /Visible-differences-predictor--an-algorithm-for-the-assessment-of/10.1117/12.135952.short?SSO=1

图像质量评估:从错误可见性到结构相似性( http: //www.cns.nyu.edu/pub/lcv/wang03-reprint.pdf

FSIM:图像质量评估的功能相似性指数( https ://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf

其中,SSIM(图像质量评估:从错误可见性到结构相似性)是最容易计算的,其开销也很小,如另一篇论文所述[!>“基于梯度相似性的图像质量评估<! > QUOT; ( https://www.semanticscholar .ORG /纸/图像质量评估基于-ON-梯度柳林/ 2b819bef80c02d5d4cb56f27b202535e119df988 )。

还有更多其他方法。如果您对艺术感兴趣/非常关心,请查看Google学术搜索并搜索类似<!>“视觉差异<!>”,<!>“图像质量评估<!>”等内容

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top