İki görüntü arasındaki farkı nasıl ölçebilirim?


179

İşte ne yapmak istiyorum:

Bir web kamerasıyla düzenli aralıklarla fotoğraf çekiyorum. Zaman atlamalı bir şey gibi. Ancak, hiçbir şey gerçekten değişmediyse, yani resim hemen hemen aynı görünüyorsa , en son anlık görüntüyü saklamak istemiyorum.

Farkı ölçmenin bir yolu olduğunu hayal ediyorum ve ampirik olarak bir eşik belirlemem gerekecekti.

Mükemmellikten ziyade sadelik arıyorum. Python kullanıyorum.


Yanıtlar:


269

Genel fikir

Seçenek 1: Her iki görüntüyü de diziler ( scipy.misc.imread) olarak yükleyin ve öğe bazında (piksel piksel) bir fark hesaplayın. Farkın normunu hesaplayın.

Seçenek 2: Her iki görüntüyü de yükleyin. Her biri için bir özellik vektörü hesaplayın (histogram gibi). Görüntüler yerine özellik vektörleri arasındaki mesafeyi hesaplayın.

Ancak, ilk olarak alınacak bazı kararlar vardır.

Sorular

Önce bu soruları cevaplamalısınız:

  • Görüntüler aynı şekil ve boyutta mı?

    Değilse, yeniden boyutlandırmanız veya kırpmanız gerekebilir. PIL kütüphanesi Python'da bunu yapmanıza yardımcı olacaktır.

    Aynı ayarlarla ve aynı cihazla alınırlarsa, muhtemelen aynıdırlar.

  • Görüntüler iyi hizalanmış mı?

    Değilse, önce en iyi hizalamayı bulmak için önce çapraz korelasyonu çalıştırmak isteyebilirsiniz. SciPy'nin bunu yapacak işlevleri vardır.

    Kamera ve sahne hala hareket ediyorsa, görüntüler iyi hizalanmış olabilir.

  • Görüntülerin pozlanması her zaman aynı mıdır? (Hafiflik / kontrast aynı mıdır?)

    Değilse, görüntüleri normalleştirmek isteyebilirsiniz .

    Ancak dikkatli olun, bazı durumlarda bu iyi olmaktan daha yanlış olabilir. Örneğin, karanlık bir arka plandaki tek bir parlak piksel normalleştirilmiş görüntüyü çok farklı hale getirir.

  • Renk bilgisi önemli mi?

    Renk değişikliklerini fark etmek istiyorsanız, gri tonlamalı görüntüdeki gibi bir skaler değer yerine nokta başına bir renk değerleri vektörünüz olacaktır. Bu kodu yazarken daha fazla dikkat etmeniz gerekir.

  • Görüntüde farklı kenarlar var mı? Hareket etmeleri muhtemel mi?

    Evetse, önce kenar algılama algoritmasını uygulayabilirsiniz (örneğin, Sobel veya Prewitt dönüşümü ile degradeyi hesaplayın, bir miktar eşik uygulayın), ardından ilk görüntüdeki kenarları ikinci kenarlarla karşılaştırın.

  • Görüntüde parazit var mı?

    Tüm sensörler görüntüyü bir miktar gürültü ile kirletir. Düşük maliyetli sensörler daha fazla gürültüye sahiptir. Görüntüleri karşılaştırmadan önce biraz gürültü azaltma uygulamak isteyebilirsiniz. Bulanıklık, buradaki en basit (ancak en iyi değil) yaklaşımdır.

  • Ne tür değişiklikler fark etmek istiyorsunuz?

    Bu, görüntüler arasındaki fark için kullanılacak norm seçimini etkileyebilir.

    Görüntünün ne kadar değiştiğini ölçmek için Manhattan normu (mutlak değerlerin toplamı) veya sıfır normu (sıfıra eşit olmayan öğe sayısı) kullanmayı düşünün. Birincisi görüntünün ne kadar kapalı olduğunu söyleyecek, ikincisi sadece kaç pikselin farklı olduğunu söyleyecektir.

Misal

Resimlerinizin muhtemelen farklı pozlamayla iyi hizalanmış, aynı boyut ve şekilde olduğunu varsayıyorum. Basit olması için renkli (RGB) görüntüler olsalar bile gri tonlamaya dönüştürürüm.

Bu ithalatlara ihtiyacınız olacak:

import sys

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

Ana işlev, iki görüntüyü okuyun, gri tonlamaya dönüştürün, sonuçları karşılaştırın ve yazdırın:

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

Nasıl karşılaştırılır. img1ve img22D SciPy dizileri burada:

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)

Dosya renkli bir görüntü ise, imreadyoğunluk elde etmek için 3B dizi, ortalama RGB kanalları (son dizi ekseni) döndürür. Gri tonlamalı görüntüler için buna gerek yoktur (örn. .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

Normalleştirme önemsizdir, [0,255] yerine [0,1] olarak normalleştirmeyi seçebilirsiniz. arrburada bir SciPy dizisidir, bu nedenle tüm işlemler element bazındadır:

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

mainİşlevi çalıştırın :

if __name__ == "__main__":
    main()

Şimdi bunları bir senaryoya koyabilir ve iki görüntüye karşı koşabilirsiniz. Görüntüyü kendisiyle karşılaştırırsak, fark yoktur:

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

Görüntüyü bulanıklaştırır ve orijinalle karşılaştırırsak, bazı farklar vardır:

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

PS Tüm karşılaştırma.py betiği.

Güncelleme: ilgili teknikler

Soru, karelerin neredeyse aynı olacağı ve sıra dışı bir şey aradığınız bir video dizisiyle ilgili olduğundan, alakalı olabilecek bazı alternatif yaklaşımlardan bahsetmek istiyorum:

  • arka plan çıkarma ve bölümleme (ön plandaki nesneleri algılamak için)
  • seyrek optik akış (hareketi algılamak için)
  • görüntüler yerine histogramları veya diğer istatistikleri karşılaştırma

“OpenCV'yi Öğrenme” kitabına, Bölüm 9'a (Görüntü parçaları ve segmentasyon) ve 10'a (İzleme ve hareket) bir göz atmanızı şiddetle tavsiye ederim. Birincisi Arkaplan çıkartma yöntemini kullanmayı öğretir, ikincisi optik akış yöntemleri hakkında bilgi verir. Tüm yöntemler OpenCV kütüphanesinde uygulanır. Python kullanıyorsanız, OpenCV ≥ 2.3 ve cv2Python modülünü kullanmanızı öneririm .

Arka plan çıkarmanın en basit sürümü:

  • arka planın her pikseli için ortalama değer μ ve standart sapma σ öğrenin
  • geçerli piksel değerlerini (μ-2σ, μ + 2σ) veya (μ-σ, μ + σ) aralıklarıyla karşılaştırın

Daha gelişmiş sürümler, her piksel için zaman serilerini dikkate alır ve statik olmayan sahneleri (hareketli ağaçlar veya çim gibi) işler.

Optik akış fikri, iki veya daha fazla kare almak ve her piksele (yoğun optik akış) veya bazılarına (seyrek optik akış) hız vektörü atamaktır. Seyrek optik akışı tahmin etmek için Lucas-Kanade yöntemini kullanabilirsiniz ( OpenCV'de de uygulanır). Açıkçası, çok fazla akış varsa (hız alanının maksimum değerlerinden yüksek ortalama), o zaman çerçevede bir şey hareket eder ve sonraki görüntüler daha farklıdır.

Histogramları karşılaştırmak, ardışık kareler arasındaki ani değişiklikleri tespit etmeye yardımcı olabilir. Bu yaklaşım Courbon ve ark., 2010'da kullanılmıştır :

Ardışık çerçevelerin benzerliği. Birbirini takip eden iki kare arasındaki mesafe ölçülür. Çok yüksekse, ikinci karenin bozuk olduğu ve böylece görüntünün ortadan kaldırıldığı anlamına gelir. Kullback-Leibler mesafesi iki kare histogramda veya karşılıklı entropi:

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

burada p ve q , çerçevelerin histogramlarıdır. Eşik 0,2 ile sabitlenmiştir.


Ben olsun RuntimeWarning: invalid value encountered in double_scalarshattında 44 (on return (arr-amin)*255/rng) ve bir ValueError: array must not contain infs or NaNshat 30 (on z_norm = norm(diff.ravel(), 0))
BioGeek

@BioGeek, rngsıfıra eşitse. Sadece bir çek ekleyin ve ayarlayınrng = 1
haisi

76

Basit bir çözüm:

Görüntüyü bir jpeg olarak kodlayın ve dosya boyutunda önemli bir değişiklik arayın .

Video küçük resimlerine benzer bir şey uyguladım ve çok başarılı ve ölçeklenebilirdim.


3
Bu çok kolay, basit bir çözümdür ve herhangi bir piksel açısından karşılaştırmadan çok daha iyidir. Web kameranızın görüntüsünde biraz parazit varsa veya görüntü bir piksel bile kaydırılırsa, doğrudan bir karşılaştırma tüm bu anlamsız değişiklikleri alır. Daha sağlam bir yaklaşım, ayrık kosinüs dönüşümünü hesaplamak ve daha sonra frekans alanındaki görüntüleri karşılaştırmak olacaktır. JPEG sıkıştırmasını bu şekilde kullanmak, Fourier teorisine dalmadan avantajların çoğunu sağlar.
AndrewF

Beğendim. Diğer çözümler de çalışmasına rağmen, bunun ortak bir durum için büyük bir avantajı vardır: "temel" görüntüyü kaydetmek istemezseniz ne olur? sadece dosya boyutunu bir karma olarak kaydedin ve sonra sadece sayıları çıkarma ile karşılaştırın. Benim durumumda 4 resim var, bunlardan biri çok benzil, diğerleri 3 kesinlikle farklı. Sadece aynı boyutlara, jpg ve substract'a ölçeklendirin. Gerçekten hoş.
Diego Andrés Díaz Espinoza

60

PIL işlevlerini kullanarak iki görüntüyü karşılaştırabilirsiniz .

import Image
import ImageChops

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

diff = ImageChops.difference(im2, im1)

Diff nesnesi, her pikselin, ikinci görüntüdeki o pikselin renk değerlerinin ilk görüntüden çıkarılmasının sonucu olduğu bir görüntüdür. Fark görüntüsünü kullanarak birkaç şey yapabilirsiniz. En basit olanı diff.getbbox()işlevdir. İki resminiz arasındaki tüm değişiklikleri içeren minimum dikdörtgeni size söyleyecektir.

Muhtemelen burada belirtilen diğer şeylerin yaklaşıklarını PIL işlevlerini kullanarak da uygulayabilirsiniz.


2
Fark görüntüsünü kaydetmek istiyorum. görüntü farkını tutan diff nesnesi anlamına gelir. nasıl kaydederim?
Sagar

2
@Anthony, görüntü adını belirten diff nesnesinde save () öğesini çağırabilirsiniz. bunun gibi: diff.save ("diff.png") sizin için fark görüntüsünü kaydedecektir.
Sagar

20

İki popüler ve nispeten basit yöntem şunlardır: (a) daha önce önerilen Öklid mesafesi veya (b) normalleştirilmiş çapraz korelasyon. Normalleştirilmiş çapraz korelasyon, aydınlatma değişikliklerine basit çapraz korelasyondan belirgin şekilde daha dayanıklı olma eğilimindedir. Wikipedia normalleştirilmiş çapraz korelasyon için bir formül verir . Daha sofistike yöntemler de var, ancak biraz daha fazla iş gerektiriyorlar.

Numpy benzeri sözdizimi kullanarak,

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

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

dist_ncc = sum ((i1 - ortalama (i1)) * (i2 - ortalama (i2))) / (
  (i1.boyut - 1) * stdev (i1) * stdev (i2))

varsayarak i1ve i22D gri tonlama görüntü dizilerdir.


3
Görüntü çapraz korelasyon fonksiyonları SciPy (yerleşik olarak docs.scipy.org/doc/scipy/reference/generated/... ) ve FFT kullanarak hızlı versiyonu STScI piton mevcuttur ( stsci.edu/resources/software_hardware/pyraf/ stsci_python )
Endolit

14

Denemek için önemsiz bir şey:

Her iki görüntüyü de küçük küçük resimlere (örn. 64 x 64) yeniden örnekleyin ve küçük resimleri piksel pikseli belirli bir eşikle karşılaştırın. Orijinal görüntüler hemen hemen aynıysa, yeniden örneklenen küçük resimler çok benzer veya hatta tamamen aynı olacaktır. Bu yöntem, özellikle düşük ışıklı ortamlarda oluşabilecek gürültü ile ilgilenir. Gri tonlamaya giderseniz daha iyi olabilir.


ama pikselleri nasıl karşılaştırırsınız?
taşıyıcı

Küçük resimlere sahip olduğunuzda, pikselleri tek tek karşılaştırabilirsiniz. Renkli olarak çalışıyorsanız, RGB değerlerinin "mesafesini" veya gri tonlamalıysanız gri tonları arasındaki farkı hesaplarsınız.
Ateş Goral

1
msgstr "pikselleri tek tek karşılaştırın". Bu ne anlama geliyor? Piksel başına 64 ^ 2 piksel testinden BİRİ başarısız olursa test başarısız mıdır?
Federico A.Ramponi

"Küçük bir pikseli pikselleri belirli bir eşikle karşılaştır" ile kastettiğim, pikselleri karşılaştırmak için bulanık bir algoritma bulmaktır. Hesaplanan fark (bulanık algoritmanıza bağlı olarak) belirli bir eşiği aşarsa, görüntüler "aynı değildir".
Ateş Goral

1
Çok basit bir örnek, "bulanık algoritma" olmadan: her bir piksel ile paralel döngü (piksel # karşılaştırma n görüntü içinde 1 piksel # için n görüntü # 2) ve bir değişkene değer farkını ekleyin
MK12

7

Özellikle "yeterince farklı" ise nasıl hesaplanacağı sorusunu ele alıyorum. Sanırım pikselleri tek tek nasıl çıkaracağınızı anlayabilirsiniz.

İlk olarak, hiçbir şey değişmeden bir sürü görüntü alırdım ve sadece çekimdeki değişiklikler, görüntüleme sistemindeki gürültü, JPEG sıkıştırma eserleri ve aydınlatmadaki andaki değişiklikler nedeniyle herhangi bir pikselin maksimum miktarını öğrenirim . Belki de hiçbir şey hareket etmese bile 1 veya 2 bitlik farkların beklendiğini göreceksiniz.

Daha sonra "gerçek" test için şöyle bir kriter istiyorsunuz:

  • en fazla P pikseli E'den farklı değilse aynıdır.

Yani, belki, E = 0.02, P = 1000 ise, herhangi bir tek piksel ~ 5 birimden fazla (8 bit görüntü varsayarak) veya 1000'den fazla olursa, "farklı" anlamına gelir. piksellerin hiç hatası yoktu.

Bu, esas olarak, daha fazla incelemeye ihtiyaç duymayacak kadar yakın görüntüleri hızlı bir şekilde tanımlamak için iyi bir "triyaj" tekniği olarak tasarlanmıştır. "Başarısız" görüntüler daha sonra, örneğin kamera biraz sarsıldığında veya aydınlatma değişikliklerine karşı daha sağlam olsaydı, yanlış pozitifleri olmayacak daha ayrıntılı / pahalı bir teknik olabilir.

Bu gibi eşiklerle (aslında daha ayrıntılı) farklılıkları karşılaştıran "idiff" adlı bir yardımcı program içeren bir açık kaynak proje, OpenImageIO , çalıştırın . Bu yazılımı kullanmak istemeseniz bile, nasıl yaptığımızı görmek için kaynağa bakmak isteyebilirsiniz. Ticari olarak biraz kullanılıyor ve bu eşikleme tekniği, platformdan platforma veya küçük değişiklikler yaptığımız gibi "referans görüntüler" ile render ve görüntü işleme yazılımı için bir test paketine sahip olabilmemiz için geliştirildi. Bu yüzden bir "tolerans dahilinde eşleşme" işlemi istedik.


6

İş yerinde benzer bir sorun yaşadım, görüntü dönüştürme uç noktamızı yeniden yazıyordum ve yeni sürümün eski sürümle aynı veya neredeyse aynı çıktıyı üretip üretmediğini kontrol etmek istedim. Bu yüzden şunu yazdım:

https://github.com/nicolashahn/diffimg

Aynı boyuttaki ve piksel başına düzeydeki görüntüler üzerinde çalışan, her kanaldaki değer farkını ölçer: R, G, B (, A), bu kanalların ortalama farkını alır ve ardından tüm pikseller ve bir oran döndürür.

Örneğin, 10x10 görüntü beyaz piksel ve aynı görüntü ancak bir piksel kırmızıya dönüştüğünde, bu pikseldeki fark 1/3 veya 0,33 ... (RGB 0,0,0 vs 255,0,0 ) ve diğer tüm pikseller 0'dır. Toplam 100 piksel ile 0,33 ... / 100 = görüntüdeki ~% 0,33'lik bir fark.

Bunun OP'nin projesi için mükemmel çalışacağına inanıyorum (bunun çok eski bir yazı olduğunu anlıyorum, ancak gelecekteki StackOverflowers için de python'daki görüntüleri karşılaştırmak istiyoruz).


5

Verilen cevapların çoğu aydınlatma seviyeleriyle ilgilenmeyecektir.

Karşılaştırmayı yapmadan önce görüntüyü standart ışık seviyesine normalleştirirdim.


Periyodik görüntüler çekiyor ve bitişik çiftleri ayırıyorsanız, biri ışıkları açtıktan sonra muhtemelen ilkini koruyabilirsiniz.
walkytalky

5

İki görüntü arasındaki benzerliği ölçmenin bir başka güzel ve basit yolu:

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)

Diğerleri görüntü benzerliğini karşılaştırmak için daha güçlü bir yolla ilgileniyorsa, Tensorflow'u kullanarak benzer görüntüleri ölçmek ve görselleştirmek için bir öğretici ve web uygulamasını bir araya getirdim.


3
Evet, skimagebu uygulama için kullanmak gerçekten güzel. Çok kullanıyorum from skimage.measure import compare_ssim, compare_mse. skimage.measure dokümanlar .
ximiki

3

Benzer resimler sorusu bulmak için Algoritma gördünüz mü ? Önerileri görmek için göz atın.

Çerçevelerinizin dalgacık dönüşümünü öneririm (Haar dönüşümünü kullanarak bunun için bir C uzantısı yazdım); daha sonra, iki resim arasındaki en büyük (orantılı) dalgacık faktörlerinin indekslerini karşılaştırarak, sayısal bir benzerlik yaklaşımı elde etmelisiniz.


2

Bu cevap vermek için çok geç olursa özür dilerim, ama benzer bir şey yaptığım için bir şekilde katkıda bulunabileceğimi düşündüm.

Belki OpenCV ile şablon eşleştirmeyi kullanabilirsiniz. Söylediğiniz gibi bir web kamerası kullandığınızı varsayarsak:

  1. Görüntüleri basitleştirin (eşik olabilir mi?)
  2. Şablon eşleşmesini uygulayın ve min_val değerini minMaxLoc ile kontrol edin

İpucu: max_val (veya kullanılan yönteme bağlı olarak min_val) size rakamlar, büyük sayılar verecektir. Yüzde farkını elde etmek için, aynı resimle şablon eşleşmesini kullanın - sonuç% 100'ünüz olacaktır.

Örnek vermek için sözde kod:

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

Umarım yardımcı olur.


1

Dünya nakliyecileri mesafesi tam olarak ihtiyacınız olan şey olabilir. Olabilir Abit olsa gerçek zamanlı olarak uygulamaya ağır.


Bu cevabın güzel bir şekilde adreslendiğini gerçekten hissetmiyorum: "Mükemmellikten ziyade basitlik arıyorum. Python kullanıyorum."
PilouPili

Bu soru iş parçacığının çok fazla trafik aldığı ve çoğu izleyicide çizdiği başlık, iki resim arasındaki farkın nasıl ölçüleceğiyle ilgili olduğunu düşünüyorum, burada değeri var.
Danoram

1

İki görüntünün Manhattan Mesafesini hesaplamaya ne dersiniz ? Bu size n * n değerleri verir. Sonra n değerini azaltmak için satır ortalaması gibi bir şey ve tek bir değer elde etmek için bunun üzerinde bir işlev yapabilirsiniz.


1

Ben (1) büyük ölçüde basitleştirerek bir tripod üzerinde aynı kamera ile çekilen jpg görüntüleri ile çok şans var (3000 piksel genişlik 100 piksel genişlik veya daha az gitmek gibi) (2) her jpg dizi tek bir düzleştirme vektör (3) r-karesi elde etmek için korelasyon katsayısı (4) kare korelasyon katsayısı elde etmek için basit bir korelasyon algoritması ile sıralı görüntüleri sıralı olarak ilişkilendirme (yani bir görüntüde değişkenlik oranı, bir sonraki uygulamada varyasyon ile açıklanan) r-kare <0.9 ise, iki görüntünün farklı olduğunu ve aralarında bir şey olduğunu söylüyorum.

Bu benim uygulamamda sağlam ve hızlı (Mathematica 7)

Görüntünün ilgilendiğiniz kısmı ile oynamaya ve tüm görüntüleri o küçük alana kırparak odaklanmaya değer, aksi takdirde kameradan uzak ama önemli bir değişiklik kaçırılır.

Python'u nasıl kullanacağımı bilmiyorum, ama eminim ki korelasyonlar da var, değil mi?


1

her iki görüntünün histogramını hesaplayabilir ve daha sonra Bhattacharyya Katsayısını hesaplayabilirsiniz , bu çok hızlı bir algoritmadır ve bir kriket videosundaki çekim değişikliklerini tespit etmek için kullandım (openCV kullanarak C)


Görüntülerdeki katsayıyı kendileri hesaplayabilir misiniz?
endolith

Görüntüler için histogramları hesaplamanız gerekir (histogramın gereksinimine göre kutu boyutu ile).
vishalv2050

1

Haar Dalgacıklarının isk-daemon tarafından nasıl uygulandığını kontrol edin . Anında görüntüler arasındaki farkı hesaplamak için bu imgdb C ++ kodunu kullanabilirsiniz:

isk-daemon, görüntü ile ilgili herhangi bir web sitesine veya yazılıma içerik tabanlı (görsel) görsel arama ekleyebilen açık kaynaklı bir veritabanı sunucusudur.

Bu teknoloji, görüntü ile ilgili herhangi bir web sitesi veya yazılımın kullanıcılarının hangi görüntüyü bulmak istedikleri bir widget üzerinde çizim yapmasına izin verir ve web sitesinin kendilerine en benzer görüntüleri yanıtlamasını veya her görüntü detay sayfasında daha benzer fotoğraflar talep etmesini sağlar.


1

Aynı sorunu yaşadım ve siyah / beyaz bir fark görüntüsü oluşturmak ve histogram değerlerini özetlemek için yastığın ImageChops'u kullanarak iki aynı boyuttaki görüntüyü karşılaştıran basit bir python modülü yazdım.

Bu skoru doğrudan veya tam siyah veya beyaz farkla karşılaştırıldığında yüzde değeri elde edebilirsiniz.

Aynı zamanda basit bir is_equal işlevi içerir ve görüntünün eşit olarak geçtiği (ve dahil olduğu) bir bulanık eşik sağlama olasılığı vardır.

Yaklaşım çok ayrıntılı değil, ama aynı sorunla mücadele eden başkaları için de yararlı olabilir.

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


1

Biraz daha ilkeli bir yaklaşım, GIST veya CENTRIST gibi görüntüleri karşılaştırmak için küresel bir tanımlayıcı kullanmaktır. Burada tarif edildiği gibi bir karma fonksiyonu da benzer bir çözüm sağlar.


1
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', 7))
    r = compare_image_dir_with_hash('image1\\', 'image2\\', 10)
    for k in r.keys():
        print(k, r.get(k))


if __name__ == '__main__':
    main()
  • çıktı:

    Yanlış
    Gerçek
    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

  • örnek resimler:

    • 815.jpg
      815.jpg

    • 5.jpg
      5.jpg


0

İki görüntünün parlaklığı arasında öklid mesafesini (yani, kare (farklılıkların kareleri, piksel olarak piksel)) hesaplayabilir ve bu bazı ampirik eşiğin altına düştüğünde bunları eşit olarak düşünebilirsiniz. Ve bir C fonksiyonunu sararak daha iyi yaparsınız.


0

İki görüntünün nasıl göründüğünü / ne kadar benzediğini değerlendirmek için birçok metrik var.

Burada herhangi bir koda girmeyeceğim, çünkü bunun teknik bir sorun dışında bilimsel bir sorun olması gerektiğini düşünüyorum.

Genel olarak, soru insanların görüntüler üzerindeki algısıyla ilgilidir, bu nedenle her algoritmanın insan görsel sistem özellikleri üzerinde desteği vardır.

Klasik yaklaşımlar:

Görünür farklılıklar tahmincisi: görüntü doğruluğunun değerlendirilmesi için bir algoritma ( https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1666/0000/Visible-differences-predictor--an-algorithm-for-the- değerlendirmesi-bölgesinin / 10,1117 / 12.135952.short? GGG = 1 )

Görüntü Kalitesi Değerlendirmesi: Hata Görünürlüğünden Yapısal Benzerliğe ( http://www.cns.nyu.edu/pub/lcv/wang03-reprint.pdf )

FSIM: Görüntü Kalitesi Değerlendirmesi için Bir Özellik Benzerlik Endeksi ( https://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf )

Bunların arasında, SSIM (Görüntü Kalitesi Değerlendirmesi: Hata Görünürlüğünden Yapısal Benzerliğe) hesaplanması en kolay olanıdır ve başka bir makalede "Degrade Benzerliğine Dayalı Görüntü Kalitesi Değerlendirmesi" ( https: //www.semanticscholar) .org / paper / Görüntü-Kalite-Değerlendirme-Gradyan-Dayalı-Liu-Lin / 2b819bef80c02d5d4cb56f27b202535e119df988 ).

Daha birçok yaklaşım var. Google Akademik'e bir göz atın ve sanatla ilgileniyorsanız / gerçekten önemsiyorsanız "görsel fark", "görüntü kalitesi değerlendirmesi" vb.


0

Ortalama kare hatası hesaplanarak numpy kullanan basit ve hızlı bir çözüm var:

before = np.array(get_picture())
while True:
    now = np.array(get_picture())
    MSE = np.mean((now - before)**2)

    if  MSE > threshold:
        break

    before = now
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.