SORU
10 EKİM 2008, Cuma


Nasıl iki resim arasındaki farkı ölçebilir miyim?

Yapmak istediğim şey şu:

Düzenli aralıklarla bir web kamerası ile fotoğraf çekiyorum. Bir nevi hızlandırılmış bir şey gibi. Eğer değişen bir şey varsa, ancak o, bu resim oldukça fazlagörünüyoraynı, en son anlık görüntü saklamak istemiyorum.

Farkları belirlemek için bir yol olduğunu düşünüyorum, ve ampirik bir eşik belirlemek için olurdu.

Sadelik yerine mükemmellik arıyorum. Python kullanıyorum.

CEVAP
14 EKİM 2010, PERŞEMBE


Genel bir fikir

Seçenek 1: diziler (scipy.misc.imread) olarak hem görüntüleri Yüklemek ve element-bilge (piksel piksel) bir farkı hesaplayalım. Farkı norm hesaplamak.

Seçenek 2: Yük her iki görüntü. Bunların her biri için bazı özellik vektörü (histogram gibi) hesaplar. Özellik vektörleri yerine resim arasındaki mesafeyi hesaplamak.

Ancak, ilk yapmak için bazı kararlar var.

Soru

Önce bu soruları cevaplamak gerekir:

  • Aynı şekil görüntü ve boyutlar?

    Eğer değilse, ya da onları yeniden boyutlandırmak kırpma gerekebilir. PİL kütüphane Python ile bunu yapmak için yardımcı olacaktır.

    Eğer aynı ayarlar ve aynı cihaz ile alınsa da, muhtemelen aynı olacak.

  • Resimler iyi hizalanmış?

    Çapraz korelasyon çalıştırmak isteyebilirsiniz değilse, ilk, en iyi uyumu bulmak için. SciPy yapmak gibi işlevleri vardır.

    Eğer kamera ve sahne hala, iyi bir görüntü hizalı olması muhtemeldir.

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

    Eğer değilse, to normalize görüntüler isteyebilirsiniz.

    Ama dikkatli olun, bazı durumlarda bu daha iyi, daha fazla yanlış yapabilir. Örneğin, karanlık bir arka plan üzerinde tek bir parlak piksel normalleştirilmiş görüntü çok farklı olacak.

  • Renk bilgisi önemli?

    Eğer renk değişiklikleri fark etmek istiyorsanız, nokta başına düşen renk değerleri yerine gri ölçekli bir resim olarak skaler bir değer bir vektör olacak. Bu kod yazarken daha fazla dikkat gerekir.

  • Görüntünün belirgin kenarları vardır? Hareket olasılığı var mı?

    Evet, kenar algılama algoritması ilk (örneğin Sobel ile degrade hesaplamak ya, bazı eşik dönüşümü uygulamak Prewitt) uygulamak, ikinci kenarlarına ilk resmin kenarları karşılaştırın.

  • Görüntüdeki gürültü var mı?

    Tüm sensörler gürültü miktar ile görüntüyü kirletiyor. -Maliyeti daha düşük gürültü sensörleri var. Görüntüleri karşılaştırmak için önce biraz gürültü azaltma uygulamak isteyebilirsiniz. Bulanıklık burada en basit (ama en iyisi değil) yaklaşımdır.

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

    Bu norm seçimi resim arasındaki fark için kullanmak etkileyebilir.

    Manhattan norm (mutlak değerlerin toplamı) ya da sıfır norm (eleman sayısı sıfıra eşit değil) görüntüyü nasıl değiştiğini ölçmek için kullanmayı düşünün. Eski imajı ne olacak, ikincisi çok piksel sadece farklı söyler.

Örnek

Görüntü iyi uyumlu, boyutu ve şekli aynı, belki farklı pozlama ile alakası yok. Basitlik için, onları (RGB) renkli görüntüler olsa bile gri tonlama dönüştürmek.

Bu ithalatın gerekir:

import sys

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

Ana fonksiyon, iki resim okuma, gri tonlama dönüştürmek, karşılaştırmak ve sonuçları yazdırmak için:

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ırmak için. img1 img2 SciPy diziler burada 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)

Eğer dosya renkli bir görüntü ise, imread 3 boyutlu bir dizi döndürür, ortalama kanalları (son dizi eksen) yoğunluk elde etmek için RGB. Hayır gri tonlama görüntüleri (*15 örneğin*) için bunu yapmak zorunda:

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 önemsiz, normalleştirmek için [0,1] seçebilirsiniz yerine [0,255]. arr tüm operasyon elemanı-bilge burada SciPy bir dizi:

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

main işlevini çalıştırın:

if __name__ == "__main__":
    main()

Şimdi bir script koy ve iki resim karşı çalıştırabilirsiniz. Eğer kendisi için görüntü karşılaştırdığımızda fark var

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

Biz görüntü bulanık ve özgün karşılaştırırsanız, 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

P. S. compare.py script Tüm.

Güncelleme: ilgili teknikleri

Soru video dizisi ile ilgili olarak, çerçeveler hemen hemen aynı olması muhtemeldir, ve olağandışı bir şey için neresinden bakarsanız bakın, alakalı olabilecek bazı alternatif yaklaşımlar söz etmek istiyorum:

  • arka plan çıkarma ve bölümleme (ön plan nesneleri algılamak için)
  • optik akış (hareket algılama) seyrek
  • karşılaştırma çubuk ya da başka bir istatistik yerine görüntüleri

Ben kesinlikle “kitabı, Bölüm 9 (Görüntü bölümleri ve bölümlendirme) ve 10 (İzleme ve hareket). OpenCV” Öğrenme bir göz alarak öneririz Eski arka Plan çıkarma yöntemi kullanmayı öğretir, ikincisi optik akış yöntemleri hakkında bazı bilgiler verir. Tüm yöntemleri OpenCV Kütüphanesi uygulanır. Eğer Python kullanıyorsanız, OpenCV ≥ 2.3 ve cv2 Python modülünü kullanmanızı öneririm.

Arka plan çıkarma en basit sürümü:

  • arka plan her piksel için ortalama değer, varyans ve standart sapma değeri öğrenin
  • aralığı (µ-2σ,µ 2σ) için geçerli piksel değerleri veya (M-F,M F) karşılaştırın

Daha gelişmiş sürümleri her piksel için dikkate zaman dizi çekmek ve statik olmayan sahneler (hareketli ağaçlar ya da çimen gibi) işlemek.

Optik akış fikri iki veya daha fazla çerçeveleri alın, ve bazıları (seyrek optik Akış) için her piksel (yoğun optik akış) veya hız vektörü atamak için. Seyrek optik akış tahmini için, Lucas-Kanade method (ayrıca OpenCV uygulanır) kullanabilirsiniz. Eğer akış çok fazla ise orada belli ki, (hız alan max değerleri üzerinde yüksek ortalama), sonra bir çerçeve içinde hareket ediyor, ve sonraki görüntüleri daha farklı.

Karşılaştırma çubuk ardışık çerçeveler arasında ani değişiklikleri belirlemek için yardımcı olabilir. Bu yaklaşım Courbon et al, 2010 kullanıldı:

Ardışık Kare benzerlik.İki ardışık çerçeve arasındaki mesafe ölçülür. Eğer çok fazla ise, ikinci Kare bozuk olduğu anlamına gelir ve böylece görüntü ortadan kalkar. ** 28 veya karşılıklı entropi, iki kare çubuk üzerinde:

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

neredepvesçerçevelerin çubuk kullanılır. Eşik değeri 0.2 üzerinde sabittir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Autocar

    Autocar

    11 Mart 2006
  • Jucyber Tutoriais

    Jucyber Tuto

    8 EYLÜL 2009
  • bored before i even began

    bored before

    30 Mart 2009