R'deki kmeans ile denetimsiz sınıflandırma


10

Bir dizi uydu görüntüsü (5 bant) var ve R'de kmeans tarafından sınıflandırmak istiyorum. Betiğim iyi çalışıyor (resimlerim arasında döngü, görüntüleri data.frame dönüştürmek, küme ve geri dönüştürmek raster):

for (n in files) {
image <- stack(n)    
image <- clip(image,subset)

###classify raster
image.df <- as.data.frame(image)  
cluster.image <- kmeans(na.omit(image.df), 10, iter.max = 10, nstart = 25) ### kmeans, with 10 clusters

#add back NAs using the NAs in band 1 (identic NA positions in all bands), see http://stackoverflow.com/questions/12006366/add-back-nas-after-removing-them/12006502#12006502
image.df.factor <- rep(NA, length(image.df[,1]))
image.df.factor[!is.na(image.df[,1])] <- cluster.image$cluster

#create raster output
clusters <- raster(image)   ## create an empty raster with same extent than "image"  
clusters <- setValues(clusters, image.df.factor) ## fill the empty raster with the class results  
plot(clusters)
}

Benim sorunum: Küme atamaları görüntüden görüntüye farklı olduğundan sınıflandırma sonuçlarını birbiriyle karşılaştıramıyorum. Örneğin, "su" ilk görüntü kümesi numarası 1'de, sonraki 2'de ve üçüncü 10'dadır, bu da su sonuçlarının tarihler arasında karşılaştırılmasını imkansız hale getirir.

Küme atamasını nasıl düzeltebilirim?

Tüm görüntüler için sabit bir başlangıç ​​noktası belirleyebilir miyim (suyun daima önce tespit edilmesini ve böylece 1 olarak sınıflandırılmasını umarak)?

Ve eğer evetse, nasıl?

Yanıtlar:


6

Sanırım yapamazsın ... Önce her sınıfları karşılaştırmak için etiketlemelisin. Kmean, önceden bilgi olmadan denetimsiz olarak sınıflandırır ve bu nedenle herhangi bir sınıf tanımlayamaz.

Referans katmanınız varsa, oy çokluğu ile bir etiketleme yapabilirsiniz. Çoğunluk oylama için 'raster' paket işlevini kullanmaktan çok daha verimli bir kod zonal:

require (data.table)
fun <- match.fun(modal)
vals <- getValues(ref) 
zones <- round(getValues(class_file), digits = 0) 
rDT <- data.table(vals, z=zones) 
setkey(rDT, z) 
zr<-rDT[, lapply(.SD, modal,na.rm=T), by=z]

refRaster sınıfı referans dosyanız nerede , class_filekmeans sonucunuzdur.

zr size ilk sütunda 'bölge' numarasını, ikinci sütunda ise sınıfın etiketini verir.


Bunun mümkün olmadığından korkuyordum. Çoğunluğun oylanmasına ilişkin kod için teşekkür ederiz!
Iris

4

Kümelemeyi bir görüntü yığınına uygulamak için bant bandını değil, tüm görüntü yığınını aynı anda yaparsınız. Aksi takdirde, @nmatton tarafından belirtildiği gibi, istatistik pek mantıklı değildir.

Ancak, bunun mümkün olmadığını kabul etmiyorum, sadece bellek yoğun. Gerçek uydu verilerinde bu büyük bir sorun olacaktır ve belki de yüksek çözünürlüklü verilerde imkansız olacaktır, ancak rasterlerinizi bir kümeleme işlevine aktarılabilen tek bir nesneye zorlayarak bellekte işleyebilirsiniz. Küme sırasında NA değerlerini izlemeniz gerekir, çünkü kümeleme sırasında bunlar kaldırılır ve rasterdeki konumları bilmeniz gerekir, böylece küme değerlerini doğru hücrelere atayabilirsiniz.

Burada bir yaklaşımdan geçebiliriz. Gerekli kütüphaneleri ve bazı örnek verileri ekleyelim (bize çalışmak için 3 bant vermek için RGB R logosu).

library(raster)
library(cluster)
r <- stack(system.file("external/rlogo.grd", package="raster")) 
  plot(r)

İlk olarak, çok bantlı raster yığın nesnesini getValues ​​kullanarak bir data.frame'e zorlayabiliriz. Hiçbir veri ile başa çıkmak nasıl gösterebilirim böylece satır 1, sütun 3 bir NA değeri ekliyorum unutmayın.

r.vals <- getValues(r[[1:3]])
  r.vals[1,][3] <- NA

Burada, işe gidebilir ve küme sonuçlarını atamak için kullanılacak NA olmayan değerlerin hücre dizinini oluşturabiliriz.

idx <- 1:ncell(r)
idx <- idx[-unique(which(is.na(r.vals), arr.ind=TRUE)[,1])]  

Şimdi, 3 bant RGB değerlerinden k = 4 ile bir küme nesnesi oluşturuyoruz. Clara K-Medoids yöntemini kullanıyorum çünkü büyük verilerle iyi ve garip dağılımlarla daha iyi. K-Ortalamalarına çok benzer.

clus <- cluster::clara(na.omit(scale(r.vals)), k=4)

Basitlik için, raster bantlarından birini orijinal raster yığın nesnesimizden çekip NA değerleri atayarak boş bir raster oluşturabiliriz.

r.clust <- r[[1]]
r.clust[] <- NA

Son olarak, indeksi kullanarak, küme değerlerini boş taramadaki uygun hücreye atar ve sonuçları çizeriz.

r.clust[idx] <- clus$clustering
plot(r.clust) 

Büyük rasterler için matrisleri diske yazan ve bloklar üzerinde çalışan bigmemory paketine bakmak isteyebilirsiniz ve mevcut bir k-ortalama fonksiyonu vardır. Ayrıca, bunun tam olarak R için tasarlanmadığını ve bir görüntü işleme veya GIS yazılımının daha uygun olabileceğini unutmayın. SAGA ve Orfeo araç kutusunun resim yığınları için kullanılabilir k-araçları kümelemesi olan her ikisi de ücretsiz yazılım olduğunu biliyorum. Yazılımın R'den çağrılmasını sağlayan bir RSAGA kütüphanesi bile var.


Tüm görüntüler bir kerede yığınlanır ve kümelenirse, sonuç tek bir kümelenmiş görüntü olur, değil mi?
Iris

@Iris, evet, bu tür görüntü kümelemesi bu şekilde çalışır ve uzaktan algılama yazılımındaki uygulamaları takip eder. Açık ve ilgili bir örnek ArcGIS'teki izocluster uygulamasıdır ( desktop.arcgis.com/en/arcmap/10.3/tools/spatial-analyst-toolbox/… )
Jeffrey Evans

O zaman bu anwer hiç yardımcı olmuyor. Benim sorunum, birkaç denetimsiz görüntü sınıflandırmasına göre zaman içinde bir değişiklik algılama yapmaya çalıştı, ancak sınıfları farklı atandı çünkü farklı sonuçları karşılaştırabilir.
Iris

Denetimsiz sınıflandırma, değişiklik tespiti yapmanın uygun bir yolu değildir. Belirli bir görüntüdeki ufak değişiklikler bile piksellerin farklı bir sınıfa atanmasıyla sonuçlanabilir. K-Ortalamalar için küme merkezleri sağlamış olsanız bile bu durum söz konusudur. SpatialEco paketinde değişiklik tespiti için faydalı bir entropi fonksiyonum var. Bir NxN penceresindeki entropiyi hesaplar ve her adımda delta türetirsiniz. Negatif entropi kaybı temsil eder ve pozitif, maksimum entropi altında belirli bir büyüklükteki peyzaj bileşenlerinin kazancını ifade eder.
Jeffrey Evans

Bu eski bir soru ve yıllar önce k-araçlarını kullanma fikrinden vazgeçtim. Ama bir dahaki sefere spatialEco paketini bilmek iyi;)
Iris
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.