Görüntü karşılaştırma - hızlı algoritma


393

Resimlerin temel bir tablo oluşturmak ve daha sonra yeni görüntünün temel bir (veya yakın) kopyası olup olmadığını belirlemek için herhangi bir yeni görüntüleri karşılaştırmak arıyorum.

Örneğin: Aynı görüntünün 100'lü kez depolanmasını azaltmak istiyorsanız, bir kopyasını saklayabilir ve ona referans bağlantıları sağlayabilirsiniz. Yeni bir görüntü girildiğinde, yinelenen ... fikirler olmadığından emin olmak için mevcut bir görüntüyle karşılaştırmak mı istiyorsunuz?

Benim bir fikrim küçük bir kük resme küçültmek ve sonra rastgele 100 piksel konumu seçmek ve karşılaştırmaktı.

Yanıtlar:


459

Aşağıda bu sorunun çözülmesine yönelik üç yaklaşım bulunmaktadır (ve diğerleri de vardır).

  • Birincisi bilgisayar görüşünde standart bir yaklaşım, kilit nokta eşleştirme. Bu, uygulanması için arka plan bilgisi gerektirebilir ve yavaş olabilir.

  • İkinci yöntem sadece temel görüntü işlemeyi kullanır ve potansiyel olarak ilk yaklaşımdan daha hızlıdır ve uygulanması kolaydır. Bununla birlikte, anlaşılabilirlikte kazandığı şey, sağlamlıktan yoksundur - eşleştirme, ölçeklendirilmiş, döndürülmüş veya renksiz görüntülerde başarısız olur.

  • Üçüncü yöntem hem hızlı hem de sağlamdır, ancak uygulanması en zor olan yöntemdir.

Keypoint Eşleme

100 rastgele puan toplamaktan daha iyi 100 önemli puan seçmek . Görüntünün bazı bölümleri diğerlerinden (özellikle kenarlarda ve köşelerde) daha fazla bilgiye sahiptir ve bunlar akıllı görüntü eşleşmesi için kullanmak isteyeceğiniz bilgilerdir. Google "temel nokta çıkarma " ve "temel nokta eşleme " ile konuyla ilgili oldukça az sayıda akademik makale bulacaksınız. Bu günlerde, farklı ölçekler, rotasyonlar ve ışıklandırma altındaki görüntüleri eşleştirebildikleri için SIFT anahtar noktaları tartışmasız en popüler olanlardır. Bazı SIFT uygulamaları burada bulunabilir .

Keypoint eşleşmesinin bir dezavantajı, naif bir uygulamanın çalışma süresidir: O (n ^ 2m); burada n, her görüntüdeki anahtar nokta sayısıdır ve m, veritabanındaki görüntü sayısıdır. Bazı akıllı algoritmalar, en yakın eşleşmeyi dörtlü veya ikili alan bölümleme gibi daha hızlı bulabilir.


Alternatif çözüm: Histogram yöntemi

Daha az sağlam ancak potansiyel olarak daha hızlı olan bir başka çözüm, her görüntü için özellik histogramları oluşturmak ve görüntüyü giriş görüntüsünün histogramına en yakın şekilde seçmektir. Bunu bir lisans olarak uyguladım ve 3 renk histogramı (kırmızı, yeşil ve mavi) ve iki doku histogramı, yön ve ölçek kullandık. Aşağıdaki ayrıntıları vereceğim, ancak bu sadece veritabanı görüntüleri çok benzer görüntüler eşleme için iyi çalıştı unutmayın. Yeniden ölçeklendirilmiş, döndürülmüş veya renksiz görüntüler bu yöntemle başarısız olabilir, ancak kırpma gibi küçük değişiklikler algoritmayı bozmaz

Renk histogramlarını hesaplamak basittir - sadece histogram kovalarınız için aralığı seçin ve her aralık için o aralıktaki bir renkle piksel sayısını hesaplayın. Örneğin, "yeşil" histogramı düşünün ve histogramımız için 4 kova seçtiğimizi varsayalım: 0-63, 64-127, 128-191 ve 192-255. Sonra her piksel için yeşil değere bakarız ve uygun kovaya bir çetele ekleriz. Konuşmayı bitirdiğimizde, yeşil kanal için normalleştirilmiş bir histogram elde etmek için her bir grup toplamını görüntünün tamamındaki piksel sayısına böleriz.

Doku yönü histogramı için, görüntü üzerinde kenar algılaması yaparak başladık. Her kenar noktasının, kenara dik yönde işaret eden normal bir vektörü vardır. Normal vektörün açısını 0 ve PI arasındaki 6 kovadan birine ölçtük (kenarlar 180 derecelik simetriye sahip olduğu için -PI ile 0 arasındaki açıları 0 ile PI arasında dönüştürdük). Her yöndeki kenar noktalarının sayısını hesapladıktan sonra, her kovayı görüntüdeki toplam kenar nokta sayısına bölerek normalleştirdiğimiz doku yönünü temsil eden normalleştirilmemiş bir histogramımız var.

Doku ölçeği histogramını hesaplamak için, her kenar noktası için, en yakın kenar noktasına olan mesafeyi aynı yönde ölçtük. Örneğin, A kenar noktasının 45 derecelik bir yönü varsa, algoritma 45 derecelik (veya makul bir sapma içinde) başka bir kenar noktası bulana kadar bu yönde yürür. Her kenar noktası için bu mesafeyi hesapladıktan sonra, bu değerleri bir histograma döküyoruz ve toplam kenar noktası sayısına bölerek normalleştiriyoruz.

Artık her görüntü için 5 histogramınız var. İki görüntüyü karşılaştırmak için, her bir histogram kovası arasındaki farkın mutlak değerini alır ve sonra bu değerleri toplarsınız. Örneğin, A ve B görüntülerini karşılaştırmak için,

|A.green_histogram.bucket_1 - B.green_histogram.bucket_1| 

yeşil histogramdaki her bir kova için diğer histogramları tekrarlayın ve ardından tüm sonuçları toplayın. Sonuç ne kadar küçük olursa, maç o kadar iyi olur. Veritabanındaki tüm görüntüler için tekrarlayın ve en küçük sonuçla eşleşen kazanır. Muhtemelen üstünde bir eşik bulunmasını istersiniz, bu algoritma üzerinde hiçbir eşleşme bulunmadığı sonucuna varılır.


Üçüncü Seçim - Anahtar Noktalar + Karar Ağaçları

Muhtemelen diğer ikisinden daha hızlı olan üçüncü bir yaklaşım semantik texton ormanları kullanmaktır (PDF). Bu, basit anahtar noktaların çıkarılmasını ve görüntüyü sınıflandırmak için bir koleksiyon karar ağaçlarının kullanılmasını içerir. Bu, basit SIFT anahtar noktası eşleşmesinden daha hızlıdır, çünkü maliyetli eşleştirme sürecini önler ve anahtar noktaları SIFT'den çok daha basittir, bu nedenle anahtar noktası çıkarma çok daha hızlıdır. Bununla birlikte, histogram yönteminin eksik olduğu önemli bir özellik olan SIFT yönteminin dönme, ölçek ve aydınlatmaya karşı değişmezliğini korur.

Güncelleme :

Benim hatam - Semantic Texton Forests makalesi özellikle görüntü eşleştirme değil, bölge etiketleme ile ilgili. Eşleşen orijinal kağıt şudur: Randomize Ağaçlar kullanarak Keypoint Tanıma . Ayrıca, aşağıdaki makaleler fikirleri geliştirmeye ve son teknolojiyi temsil etmeye devam etmektedir (c. 2010):


Histogram yaklaşımı en mantıklı görünüyor. Sana (4 ile aynı görüntüyü tedavi) görüntü döndü kıyaslanan ihtimale her taraftan bu gerçekleştirmek için görüntüyü döndürebilirsiniz farz ediyorum - sayesinde
meade

4
@meade Doğru. Dikkate alınacak başka bir şey: Sorununuza bağlı olarak, algoritmanızda 5 histogramın tümünü kullanmanız gerekmeyebilir. Doku yönü histogramını atmak, resmin döndürülmüş sürümlerini eşleştirmenize olanak tanır. Doku ölçeği histogramını atmak görüntünün yeniden ölçeklendirilmiş sürümlerini eşleştirmenize olanak tanır. Benzerliği karşılaştırma yeteneğinizi kaybedeceksiniz, ancak durumunuza bağlı olarak bu bir sorun olmayabilir. Ayrıca, doku bilgisini hesaplamak algoritmanın en maliyetli kısmı olduğu için, algoritmanızı da hızlandıracaktır.
Kyle Simek

@redmoskito: Bir sorum var. Örneğin yeşil histogramın sayısal değerini nasıl elde edersiniz? Yani diğer görüntü histogramı ile çıkarabilirsiniz? Diyelim ki 0-63 kovaya ait 3 piksel ve 64-127'ye ait 5 piksel yeşil bir histogramımız var. Değer nedir?
dinamik

3
@Ikaso tam olarak aynı görüntü ise, muhtemelen böyle bir şey kullanmak istemezsiniz ve basit CRC veya MD5 karşılaştırmasını kullanmayı düşünmezsiniz. Farklı değilse veya meta veriler değişmiş gibi bu yeterli değilse, histogram yöntemi de yeterlidir. görüntüleriniz aynı ancak döndürülmüş veya ölçeklendirilmişse, histogram tabanlı bir yöntem yeterli olabilir, ancak belki başarısız olabilir. resimleriniz renk değiştirdiyse, ilgi noktası tabanlı algoritmalar kullanmanız gerekir.
reox

5
Günümüzde SIFT'e FAST dedektörü ve ikili tanımlayıcılar (BRIEF, BRISK, ORB, FREAK, BinBoost) gibi birçok hızlı alternatifin mevcut olduğunu eklemek istiyorum. İkili tanımlayıcılar hakkında bir eğitim burada bulunabilir: gilscvblog.wordpress.com/2013/08/26/…
GilLevi

85

Bildiğim en iyi yöntem Algısal Karma kullanmaktır. Böyle bir karma için iyi bir açık kaynak uygulaması var gibi görünüyor:

http://phash.org/

Ana fikir, orijinal görüntü dosyasındaki göze çarpan özellikleri belirleyerek ve bu özelliklerin kompakt bir temsilini (görüntü verilerini doğrudan hash etmek yerine) karma yaparak her görüntünün küçük bir karma koduna veya 'parmak izine' indirgenmesidir. Bu, yanlış pozitiflik oranının, görüntüleri küçük parmak izi boyutunda bir görüntüye indirgemek ve parmak izlerini karşılaştırmak gibi basit bir yaklaşımla çok azaldığı anlamına gelir.

phash çeşitli karma türleri sunar ve görüntüler, ses veya video için kullanılabilir.


Bu yöntemde kimler ilgi çekici olabilir github.com/ameingast/cocoaimagehashing
Alexey Voitenko

@AlexeyVoitenko Bu, phash.org tarafından varsayılan yapılandırmasında üretilen karmalarla uyumlu mu?
Michael

1
Deneyimlerime göre phash aynı görüntünün farklı boyutlarını bulmak için iyi çalışıyor, ancak benzer görüntüler için değil. Örneğin, aynı nesnenin iki farklı fotoğrafı çok farklı karmalara sahip olabilir.
Rena

39

Bu yazı benim çözümümün başlangıç ​​noktasıydı, burada birçok iyi fikir vardı, bu yüzden sonuçlarımı paylaşacaktım. Ana fikir, phash hızını kullanarak anahtar nokta tabanlı görüntü eşleşmesinin yavaşlığını aşmanın bir yolunu buldum.

Genel çözüm için birkaç strateji uygulamak en iyisidir. Her algoritma belirli görüntü dönüştürme türleri için en uygunudur ve bundan yararlanabilirsiniz.

Üstte en hızlı algoritmalar; en yavaş (daha doğru olsa da). Daha hızlı seviyede iyi bir eşleşme bulunursa yavaş olanları atlayabilirsiniz.

  • kesin kopyalar için dosya karması tabanlı (md5, sha1 vb.)
  • yeniden ölçeklendirilmiş görüntüler için algısal karma (phash)
  • değiştirilmiş görüntüler için özellik tabanlı (SIFT)

Phash ile çok iyi sonuçlar alıyorum. Hassasiyet, yeniden ölçeklendirilmiş görüntüler için iyidir. Değiştirilmiş (algısal olarak) görüntüler (kırpılmış, döndürülmüş, yansıtılmış vb.) İçin iyi değildir. Karma hızıyla başa çıkmak için samanlık karmasını korumak için bir disk önbelleği / veritabanı kullanmalıyız.

Phash ile ilgili gerçekten güzel bir şey, karma veritabanınızı oluşturduktan sonra (ki benim için yaklaşık 1000 resim / sn'dir), aramalar çok, çok hızlı olabilir, özellikle de tüm karma veritabanını bellekte tutabildiğinizde. Bir karma sadece 8 bayt olduğu için bu oldukça pratiktir.

Örneğin, 1 milyon görüntünüz varsa, 1 milyon 64 bit karma değerleri (8 MB) dizisini gerektirir. Bazı CPU'larda bu L2 / L3 önbelleğine sığar! Pratik kullanımda 1 Giga-hamm / sn üzerinde bir corei7 karşılaştırması gördüm, bu sadece CPU için bir bellek bant genişliği sorunudur. 64 milyar CPU (8 GB RAM gerekir) için 1 Milyar görüntü veritabanı pratiktir ve aramalar 1 saniyeyi geçmez!

Değiştirilmiş / kırpılmış görüntüler için SIFT gibi bir dönüşüm-değişmez özellik / anahtar nokta dedektörü gibi görünmektedir. SIFT, kırpma / döndürme / ayna vb. Tespit edecek iyi anahtar noktaları üretecektir. Ancak tanımlayıcı karşılaştırması, phash tarafından kullanılan çekiçleme mesafesine kıyasla çok yavaştır. Bu büyük bir sınırlamadır. Maksimum IxJxK tanımlayıcı bir görüntüyü aramakla karşılaştırıldığı için çok fazla karşılaştırma vardır (I = num haystack görüntüleri, J = samanlık görüntüsü başına hedef anahtar noktaları, K = iğne görüntüsü başına hedef anahtar noktaları).

Hız sorununu aşmak için, bulunan her anahtar noktanın çevresinde phash kullanmayı, alt dikdörtgeni belirlemek için özellik boyutunu / yarıçapını kullanarak denedim. Bunu iyi yapmanın hilesi, farklı alt rekt seviyeleri (iğne görüntüsünde) oluşturmak için yarıçapı büyütmek / küçültmektir. Genellikle ilk seviye (ölçeklendirilmemiş) eşleşir, ancak genellikle birkaç tane daha alır. Bunun neden çalıştığından% 100 emin değilim, ancak phash'ın çalışması için çok küçük özelliklerin etkinleştirildiğini hayal edebiliyorum (phash görüntüleri 32x32'ye kadar ölçeklendirir).

Başka bir sorun, SIFT'in kilit noktaları en iyi şekilde dağıtmayacağıdır. Görüntünün çok fazla kenarı olan bir bölümü varsa, anahtar noktaları orada kümelenir ve başka bir alanda elde edemezsiniz. Dağıtım geliştirmek için OpenCV GridAdaptedFeatureDetector kullanıyorum. Hangi ızgara boyutunun en iyi olduğundan emin değilim, küçük bir ızgara kullanıyorum (görüntü yönüne bağlı olarak 1x3 veya 3x1).

Özellik saptama işleminden önce muhtemelen tüm samanlık görüntülerini (ve iğneyi) daha küçük bir boyuta ölçeklemek istersiniz (maksimum boyut boyunca 210 piksel kullanıyorum). Bu, görüntüdeki gürültüyü azaltacaktır (bilgisayar görme algoritmaları için her zaman bir sorun), ayrıca dedektörü daha belirgin özelliklere odaklayacaktır.

İnsanların görüntüleri için yüz algılamayı deneyebilir ve ölçeklendirilecek görüntü boyutunu ve ızgara boyutunu (örneğin 100 piksel olacak şekilde ölçeklendirilmiş en büyük yüz) belirlemek için kullanabilirsiniz. Özellik dedektörü çoklu ölçek seviyelerini (piramitleri kullanarak) açıklar, ancak kaç seviye kullanacağı konusunda bir sınırlama vardır (bu elbette ayarlanabilir).

Önemli nokta dedektörü, muhtemelen istediğiniz özellik sayısından daha azını döndürdüğünde en iyi şekilde çalışır. Örneğin, 400 ister ve 300 geri alırsanız, bu iyi. Her seferinde 400 tane geri alırsanız, muhtemelen bazı iyi özelliklerin dışarıda bırakılması gerekiyordu.

İğne görüntüsünün samanlıkta görüntülerden daha az anahtar noktası olabilir ve yine de iyi sonuçlar alabilirsiniz. Daha fazlasını eklemek size büyük kazançlar sağlamaz, örneğin J = 400 ve K = 40 ile isabet oranım yaklaşık% 92'dir. J = 400 ve K = 400 ile isabet oranı sadece% 96'ya kadar çıkıyor.

Ölçekleme, döndürme, aynalama vb. Çözmek için çekiçleme fonksiyonunun aşırı hızından yararlanabiliriz. Çok geçişli bir teknik kullanılabilir. Her bir yinelemede, alt dikdörtgenleri dönüştürün, yeniden karıklayın ve arama işlevini tekrar çalıştırın.


8

Cartman'ın işaret ettiği gibi, tam kopyaları bulmak için her türlü hash değerini kullanabilirsiniz.

Yakın görüntüleri bulmak için bir başlangıç ​​noktası burada olabilir . Bu, CG şirketleri tarafından yenilenen görüntülerin hala aynı sahneyi gösterip göstermediğini kontrol etmek için kullanılan bir araçtır.


7

İşe yarayacak bir fikrim var ve büyük olasılıkla çok hızlı olacak. Bir görüntüyü 80x60 çözünürlük veya karşılaştırılabilir olarak alt örnekleyebilir ve gri skalaya dönüştürebilirsiniz (alt örneklemeden sonra daha hızlı olacaktır). Karşılaştırmak istediğiniz her iki görüntüyü de işleyin. Daha sonra, iki görüntü (sorgu görüntüsü ve her biri db'den) arasındaki normalleştirilmiş kare farklarının toplamını veya her iki görüntü de benzerse 1'e daha yakın olan daha iyi Normalize Çapraz Korelasyonu çalıştırın. Ardından görüntüler benzerse, aynı görüntüler olduğunu doğrulamak için daha karmaşık tekniklere geçebilirsiniz. Açıkçası bu algoritma, veritabanınızdaki görüntü sayısı açısından doğrusaldır, bu yüzden modern donanımda saniyede 10000 görüntüye kadar çok hızlı olacaktır. Döndürmeye değişmezliğe ihtiyacınız varsa, bu küçük görüntü için baskın bir gradyan hesaplanabilir, ve sonra tüm koordinat sistemi kanonik yöne döndürülebilir, ancak bu daha yavaş olacaktır. Ve hayır, burada ölçeklemek için değişmezlik yok.

Daha genel bir şey veya büyük veritabanları (milyon görüntü) kullanmak istiyorsanız, görüntü alma teorisine bakmanız gerekir (son 5 yılda bir sürü kağıt çıktı). Diğer cevaplarda bazı işaretçiler var. Ancak aşırıya kaçabilir ve önerilen histogram yaklaşımı işi yapar. Yine de birçok farklı hızlı yaklaşımın kombinasyonunun daha iyi olacağını düşünürdüm.


7

Şirketim her ay üreticilerden gelen yaklaşık 24 milyon görüntü içeriyor . Kataloğumuza yüklediğimiz görüntülerin yeni görüntüler olmasını sağlamak için hızlı bir çözüm arıyordum .

İdeal bir çözüm bulmaya çalışmak için internette geniş çapta arama yaptığımı söylemek istiyorum. Kendi kenar algılama algoritmamı bile geliştirdim.
Birden fazla modelin hızını ve doğruluğunu değerlendirdim. Beyaz arka plana sahip görüntülerim aşamalı olarak son derece iyi çalışıyor. Gibi redcalx dedi, ben phash veya ahash öneriyoruz. MD5 Karma veya diğer şifreleme karma'larını KULLANMAYIN . Tabii, sadece EXACT resim eşleşmesini istemiyorsanız. Görüntüler arasında meydana gelen herhangi bir yeniden boyutlandırma veya manipülasyon farklı bir karma verir.

Phash / ahash için Şuna bir göz atın: imagehash

Kodumu ve doğruluğumu göndererek * redcalx 'in gönderisini uzatmak istedim.

Ne yaptığım:

from PIL import Image
from PIL import ImageFilter
import imagehash

img1=Image.open(r"C:\yourlocation")
img2=Image.open(r"C:\yourlocation")
if img1.width<img2.width:
    img2=img2.resize((img1.width,img1.height))
else:
    img1=img1.resize((img2.width,img2.height))
img1=img1.filter(ImageFilter.BoxBlur(radius=3))
img2=img2.filter(ImageFilter.BoxBlur(radius=3))
phashvalue=imagehash.phash(img1)-imagehash.phash(img2)
ahashvalue=imagehash.average_hash(img1)-imagehash.average_hash(img2)
totalaccuracy=phashvalue+ahashvalue

İşte bazı sonuçlarım:

item1  item2  totalsimilarity
desk1  desk1       3
desk1  phone1     22
chair1 desk1      17
phone1 chair1     34

Bu yardımcı olur umarım!


6

Görüntünün boyutunu neredeyse simge boyutuna, örneğin 48x48'e düşürmenin, sonra gri skalaya dönüştürmenin, ardından pikseller veya Delta arasındaki farkı almanın iyi çalışması gerektiğine inanıyorum. Gerçek piksel rengi yerine piksel rengindeki değişikliği karşılaştırdığımız için, görüntünün biraz daha açık veya koyu olması önemli değildir. Çok açık / koyu olan pikseller kaybolacağından büyük değişiklikler önemli olacaktır. Bunu tek bir satıra ya da doğruluğu artırmak için istediğiniz kadar uygulayabilirsiniz. Karşılaştırılabilir bir Anahtar oluşturmak için en fazla 47x47 = 2,209 çıkarma yapmanız gerekir.


3

100 rastgele nokta seçmek, benzer (veya bazen de farklı) görüntülerin aynı olarak işaretleneceği anlamına gelebilir, ki bu istediğiniz şey değildir. Görüntüler farklı biçimlerde (png, jpeg, vb.), Farklı boyutlara sahipse veya farklı meta verilere sahipse MD5 karmaları çalışmaz. Tüm görüntüleri daha küçük bir boyuta küçültmek iyi bir seçenektir, piksel için piksel karşılaştırması yapmak, iyi bir görüntü kütüphanesi / hızlı dil kullandığınız sürece çok uzun sürmemelidir ve boyut yeterince küçüktür.

Onları küçültmeyi deneyebilirsiniz, o zaman aynılar daha büyük bir boyutta başka bir karşılaştırma yapın - hız ve doğruluk için iyi bir kombinasyon olabilir ...


Tam kopyalar arıyorsanız, ancak farklı biçimler / meta verilerle, gerçek piksel değerlerinin bir karmasını (örn. MD5) yapabilirsiniz. Imagemagick bunu bir imza olarak adlandırır (kriptografik imzalama ile ilgili değildir). Ayrıca, JPEG eserlerinin etkisini azaltmak için önce piksel başına 4 bit olarak kısaltabilir veya hafifçe yeniden renklendirilmiş görüntülerle eşleşmek için gri tonlamaya dönüştürebilirsiniz.
Rena

2

Çok sayıda resminiz varsa, olasılıklı ancak etkili bir sonuç için birden fazla karma kullanan bir Bloom filtresine bakın . Görüntü sayısı çok fazla değilse, md5 gibi bir şifreleme karması yeterli olmalıdır.


Yani (Bloom filtresini anlamaya çalışmak) - Bu, temel görüntüde rastgele piksel noktalarını seçtiğiniz, rastgele pikselin kırmızı / yeşil / mavi değerini aldığınız anlamına mı geliyor - sonra yeni görüntüyle karşılaştırmalı mı? ve sonra iki görüntünün ne kadar benzer olduğunu belirlemek için bir olasılık seviyesi (% 90 eşleşme) kullanın?
meade

5
Bu bir benzerlik kontrolü değil, bir denklik kontrolü. Benzerliğe ihtiyacınız varsa, karma doğru yaklaşım değildir. Bloom'un arkasındaki fikir, benzersiz tanımlama olasılığını artırmak için çoklu karma algoritmalar kullanmaktır. Rasgele noktalar seçmek, bir karma algoritması için en iyi yaklaşım değildir, çünkü her seferinde farklı sonuçlar verir.
jdigital
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.