Raster fark: görüntülerin aynı değerlere sahip olup olmadığı nasıl kontrol edilir?


10

Verilen iki tarama katmanının aynı içeriğe sahip olup olmadığını kontrol etmenin bir yolu var mı?

Kurumsal paylaşılan depolama hacmimizle ilgili bir sorunumuz var: Şimdi tam bir yedekleme yapmak 3 günden fazla sürüyor. Ön araştırma, alan tüketen en büyük suçlulardan birinin CCITT sıkıştırmasıyla gerçekten 1 bit katmanlar olarak depolanması gereken açma / kapama rasterleri olduğunu ortaya koyuyor.

tipik bir mevcut / mevcut olmayan tarama

Bu örnek görüntü şu anda 2 bit (3 olası değer) ve dosya sisteminde 11 MB, LZW sıkıştırılmış tiff olarak kaydedildi. 1bit'e dönüştürdükten (2 olası değer) ve CCITT Group 4 sıkıştırmasını uyguladıktan sonra, neredeyse tam bir büyüklükte bir tasarruf sırası olan 1,3 MB'ye indiriyoruz.

(Bu aslında çok iyi davranmış bir vatandaş, 32bit float olarak saklanan başkaları var!)

Bu harika bir haber! Ancak bunu uygulamak için neredeyse 7.000 görüntü var. Bunları sıkıştırmak için bir komut dosyası yazmak basittir:

for old_img in [list of images]:
    convert_to_1bit_and_compress(old_img)
    remove(old_img)
    replace_with_new(old_img, new_img)

... ancak hayati bir test eksik: Yeni sıkıştırılmış sürüm içerikle aynı mı?

  if raster_diff(old_img, new_img) == "Identical":
      remove(old_img)
      rename(new_img, old_img)

Görüntü-A'nın içeriğinin Görüntü-B içeriğiyle otomatik olarak aynı olduğunu (dis) kanıtlayabilen bir araç veya yöntem var mı?

ArcGIS 10.2 ve QGIS'e erişimim var, ancak üzerine yazmadan önce doğruluğu sağlamak için tüm bu görüntüleri manuel olarak inceleme ihtiyacını ortadan kaldırabilecek başka birçok şeye de açığım. Bu yanlışlıkla dönüştürün korkunç olabilir ve gerçekten bir görüntü üzerine yazılacağı vermedi o değerlere kapalı fazla / 'üzerinde daha var. Çoğu toplanması ve üretilmesi binlerce dolara mal oluyor.

çok kötü bir sonuç

güncelleme: En büyük suçlular bir tarafa 100.000 piksel kadar 32bit yüzer, bu yüzden ~ 30GB sıkıştırılmamış.


1
Uygulamanın bir yolu raster_diff(old_img, new_img) == "Identical", farkın mutlak değerinin bölgesel maksimum değerinin 0'a eşit olup olmadığını kontrol etmek olacaktır, burada bölge tüm ızgara kapsamı boyunca alınır. Bu aradığınız bir çözüm yolu mu? (Öyleyse, herhangi bir NoData değerinin de tutarlı olup olmadığını kontrol etmek için rafine edilmesi gerekir.)
whuber

1
@whuber NoData, konuşmada uygun kullanımın kalmasını sağladığınız için teşekkür ederiz .
matt wilkie

bunu kontrol edebiliyorsanız len(numpy.unique(yourraster)) == 2, 2 benzersiz değere sahip olduğunu biliyorsunuz ve bunu güvenle yapabilirsiniz.
RemcoGerlich

@Remco Altta yatan algoritma numpy.unique, farkın sabit olup olmadığını kontrol etmenin diğer birçok yolundan daha fazla (hem zaman hem de alan açısından) daha pahalı olacaktır. Birçok farklılık gösteren (bir orijinali kayıplı sıkıştırılmış bir versiyonla karşılaştırmak gibi) iki çok büyük kayan nokta raster arasında bir farkla karşılaştığında, büyük olasılıkla sonsuza kadar aşağı inecek veya tamamen başarısız olacaktır.
whuber

1
@Aaron, başka şeyler yapmak için projeden çekildim. Bunun bir kısmı, geliştirme süresinin büyümeye devam etmesiydi: otomatik olarak ele alınacak çok sayıda son durum, bu yüzden sorunu düzeltmek yerine görüntüleri üreten insanlara geri atma kararı verildi. (örn. "Disk kotanız X'tir. İçinde nasıl çalışacağınızı öğrenirsiniz.") Ancak gdalcompare.pybüyük bir vaat gösterdi ( cevaba bakın )
matt wilkie

Yanıtlar:


8

Rakiplerinizi numpy dizilerine dönüştürmeyi deneyin ve sonra aynı dizi ve öğelere array_equal ile sahip olup olmadıklarını kontrol edin . Eğer aynıysa, sonuç şöyle olmalıdır True:

ArcGIS:

import arcpy, numpy

raster1 = r'C:\path\to\raster.tif'
raster2 = r'C:\path\to\raster.tif'

r1 = arcpy.RasterToNumPyArray(raster1)
r2 = arcpy.RasterToNumPyArray(raster2)

d = numpy.array_equal(r1,r2)

if d == False:
    print "They differ"

else:
    print "They are the same"

GDAL:

import numpy
from osgeo import gdal        

raster1 = r'C:\path\to\raster.tif'
raster2 = r'C:\path\to\raster.tif'

ds1 = gdal.Open(raster1)
ds2 = gdal.Open(raster2)

r1 = numpy.array(ds1.ReadAsArray())
r2 = numpy.array(ds2.ReadAsArray())

d = numpy.array_equal(r1,r2)

if d == False:
    print "They differ"

else:
    print "They are the same"

Tatlı ve basit görünüyor. İki ayrıntıyı merak ediyorum (teknik olsalar da çok önemli olabilir). İlk olarak, bu çözüm NoData değerlerini doğru şekilde işler mi? İkincisi, hızı, bölge özetleri gibi ızgara karşılaştırmalarına yönelik yerleşik işlevleri kullanmakla nasıl karşılaştırılır?
whuber

1
İyi noktalar @whuber. Komut dosyasına şekil ve öğeleri dikkate alması gereken hızlı bir ayar yaptım. Ortaya koyduğunuz noktaları kontrol edip bulguları rapor edeceğim.
Aaron

1
@whuber ilgili NoDatakullanım, RasterToNumPyArraydizi giriş Raster en NODATA varsayılan değerine göre atar. Matt için geçerli olmasa da, kullanıcı farklı bir değer belirleyebilir. Hızla ilgili olarak, komut dosyasının 2 adet 4 bit raster ile 6210 sütun ve 7650 satır (DOQQ kapsamı) karşılaştırması 4.5 saniye sürdü. Yöntemi herhangi bir bölgesel özetle karşılaştırmadım.
Aaron


4

Http://www.gdal.org/gdalcompare.html gdalcompare.py komut dosyasını deneyebilirsiniz . Komut dosyasının kaynak kodu http://trac.osgeo.org/gdal/browser/trunk/gdal/swig/python/scripts/gdalcompare.py adresindedir ve gereksiz bir python komut dosyası olduğundan kolayca kaldırılmalıdır Mevcut ihtiyaçlarınızı karşılamak için testler yapın ve yenilerini ekleyin. Komut dosyası, iki görüntü bandından görüntü verilerini bantlar halinde okuyarak piksel piksel karşılaştırma yapıyor gibi görünüyor ve bu muhtemelen oldukça hızlı ve tekrar kullanılabilir bir yöntemdir.


1
ilgi çekici, gdal'ı seviyorum, bu senaryo hakkında bilmiyordum. Sonuçları yorumlamak için kullanılan dokümanlar seyrek olup olmadığı ;-). İlk testimde renk yorumlaması ve paletlerdeki farklılıkları bildiriyor, yani mevcut ihtiyaçlarım için çok özel olabilir. Yine de araştırıyorum. (not: bu cevap burada iyi bir uyum için çok kısa, sadece bağlantı cevapları cesaretini kırdı, lütfen etmeyi düşünün).
matt wilkie

1

Her bir görüntü için raster özellik tablonuzu oluşturmanızı öneririm , o zaman tabloları karşılaştırabilirsiniz. Bu tam bir kontrol değildir (ikisi arasındaki farkı hesaplamak gibi), ancak görüntülerinizin aynı histogram değerleriyle farklı olma olasılığı çok küçüktür. Ayrıca, NoData'sız (tablodaki satır sayısından) benzersiz değerlerin sayısını verir. Toplam sayınız resim boyutundan küçükse, NoData piksellerine sahip olduğunuzu bilirsiniz.


Bu 32-bit şamandıralarla çalışır mı? İki tablo oluşturmak ve karşılaştırmak aslında iki raster arasındaki farkın değerlerini (prensipte sadece sıfır ve NoData olmalıdır) incelemekten daha hızlı (veya daha kolay) olabilir mi?
whuber

32 bit şamandıra ile çalışmayacağını ve hızı kontrol etmediğini haklısın. Ancak, öznitelik tablosu oluşturmanın verileri yalnızca bir kez okuması gerekir ve başarısız olacağını bildiğinizde 1 bit sıkıştırmayı önlemeye yardımcı olabilir. Ayrıca görüntülerin boyutunu bilmiyorum, ama bazen bunları hafızaya kaydedemezsiniz.
radouxju

@radouxju görüntüleri bir tarafa 100.000 piksel kadar değişir, bu yüzden ~ 30GB sıkıştırılmamış. O kadar
koçlu bir

ArcGIS yerel işlemlerine bağlı kalmak şartıyla RAM'in bir sorun olmayacağı muhtemel görünüyor. Izgaraları işlerken RAM kullanımı ile oldukça iyidir: dahili olarak işlemi satır satır, satır grupları ve dikdörtgen pencerelerle yapabilir. Bir ızgarayı diğerinden çıkarmak gibi yerel işlemler esasen giriş ve çıkış hızında çalışabilir ve her giriş veri kümesi için yalnızca bir (nispeten küçük) tampon gerektirir. Bir öznitelik tablosu oluşturmak için ek bir karma tablo gerekir - bu yalnızca bir veya iki değer göründüğünde minik olur, ancak keyfi ızgaralar için çok büyük olabilir.
whuber

numpy 2 * 30Go dizileri ile çok fazla takas yapacak, bu artık ArcGIS değil. Baskı ekranına dayanarak resimlerin sınıflandırılmış görüntüler olduğunu varsaydım (çoğu sadece birkaç değerle), bu yüzden çok fazla sınıf beklemiyorsunuz.
radouxju

0

Bulduğum en basit çözüm, rasterler hakkında bazı özet istatistikleri hesaplamak ve bunları karşılaştırmak. Genellikle değişikliklere karşı dayanıklı olan standart sapma ve ortalamaları kullanıyorum, ancak kasıtlı olarak verileri manipüle ederek onları kandırmak mümkün.

mean_obj = arcpy.GetRasterProperties(input_raster, 'MEAN')
mean = float(mean_obj.getOutput(0))
if round(mean, 4) != 0.2010:
    print("raster differs from expected mean.")

std_obj = arcpy.GetRasterProperties(input_raster, 'STD')
std = float(std_obj.getOutput(0))
if round(std, 4) != 0.0161:
    print("raster differs from expected standard deviation.")

2
Bir büyük bu istatistikleri aptal yolu hücre içeriğini sırasını değiştirmek amacıyla olabilir (olabilir ki, ve resim boyutları çok doğru olmadığında, does) olacaktır. Çok büyük rasterlerde ne SD ne de ortalama, dağılmış birkaç küçük değişikliği güvenilir bir şekilde algılayamaz (özellikle birkaç piksel düştüyse). Muhtemelen, kübik evrişimin kullanılması şartıyla (ortalama ve SD'yi koruma amaçlı) ızgaraların toptan yeniden örneklenmesini tespit etmeyeceklerdir. Bunun yerine ızgaraların farkının SD'sini sıfıra karşılaştırmak akıllıca görünecektir.
whuber

0

En kolay yol, bir raster diğerinden çıkarmaktır, sonuç 0 ise, her iki görüntü de aynıdır. Ayrıca sonucu renklendirerek histogramı veya çizimi görebilirsiniz.


Çıkarma bir karşılaştırma yapmak için iyi bir yol gibi görünüyor. Bununla birlikte, histogramın NoData değerleriyle ilgili sorunları tespit etmede çok yararlı olmayacağına inanıyorum. Örneğin, sıkıştırma prosedürünün ızgara çevresindeki tek piksel kenarlığını ortadan kaldırdığını varsayalım (bu olabilir!) Ancak aksi halde doğruydu: tüm farklılıklar yine de sıfır olacaktır. Ayrıca, OP'nin bunu 7000 raster veri seti ile yapması gerektiğini fark ettiniz mi? 7000 parselin incelenmesinden hoşlanacağından emin değilim.
whuber
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.