Geotiff görüntüsünden RGB değerlerini R kullanarak LiDAR verilerine atama


10

UTM koordinatlarında bir Geotiff görüntüsü ve karşılık gelen Lidar verilerini (x, y, z) verdim. Lidar verilerini görüntüdeki RGB değerleri ile birleştirmem gerekiyor.

Bu, sonunda, Geotiff görüntüsünden karşılık gelen RGB değeri ile kodlanmış LiDAR bulut renginin her noktasını (3D) çizmem gerektiği anlamına geliyor.

QGIS kullanarak Lidar verilerini bir şekil dosyasına dönüştürdüm. Sonra ne yapmalıyım?

R'de plot3Dişlevi denedim , ama işe yaramadı. Ben takılarak ediyorum metin doc , şekil dosyası ve tif görüntü

Düzenle:

Aşağıda gösterildiği gibi aşağıdaki programı yaptım:

require(raster) 
require(maptools)  # to take shape files
#require(car) # for scatter3D 
require(plot3Drgl)

##setwd("C:\\Users\\Bibin Wilson\\Documents\\R")
##source('Lidar.r')

data = read.csv("C:\\Users\\Bibin Wilson\\Desktop\\Lidar\\lidardata.csv")
#nr = nrow(data)
nc = ncol(data)

nr = 500

require(rgdal)
X = readGDAL("C:\\Users\\Bibin Wilson\\Desktop\\Lidar\\image.tif")

topx = 4.968622208855732e+05;
topy = 5.419739403811632e+06;

final = matrix(nrow = nr, ncol = nc+2)

for(i in 1:nr) {
 x = data[i,1]
 y = data[i,2]
 rr = round((topy-y)/0.0833)
 cc = abs(round((x-topx)/0.0833))
 if(rr == 0) {
  rr = 1
 }
 if(cc == 0) {
  cc = 1
 }
 final[i,1] = x
 final[i,2] = y
 final[i,3] = data[i,3]
 final[i,4] = rr
 final[i,5] = cc
}

for(i in 1:nr) {
 x = final[i,1]
 y = final[i,2]
 z = final[i,3]     
 rr = final[i,4]
 cc = final[i,5]
 if(rr <= 5086 && cc<=3265) {
  r = X[rr,cc,1]/255
  g = X[rr,cc,2]/255
  b = X[rr,cc,3]/255
  c = cbind(r,g,b)
  scatter3D(x,y,z,2,c)
 }
}

Ancak grafiği çizmeye çalışırken, aşağıdaki hatayı gösterir:

Hata [.data.frame(x @ veri, i, j, ..., bırak = YANLIŞ): kullanılmayan argüman (1)

Düzenle:

3D modeli RGB olmadan aşağıda gösterildiği gibi aldım:

resim açıklamasını buraya girin



1
Terimleri soruyu ve kodunuzu saçma sapan bir şekilde karıştırıyorsunuz. Çokgenler ayrık alanları temsil ederken noktalar açık x, y konumlarıdır. Çokgen değil bir nokta özellik sınıfı okuyor gibi görünüyorsunuz. Bu durumda, özüt işlevinde "eğlence = ortalama" istemezsiniz. Ayrıca R'nin büyük nokta bulutlarının 3D grafikleri için ideal bir yazılım olmadığını da belirtmek isterim. Ek olarak, amacınız görselleştirme için iyidir, ancak 3D verilere yansıtılan 2D'nin paralaks sorunları nedeniyle, bunu analitik olarak kullanamazsınız.
Jeffrey Evans

Şekil dosyasını ve TIFF dosyalarını birleştirmenin herhangi bir yolu var mı, böylece onları çizmek için başka yazılım araçlarını kullanabilirim.
bibinwilson

qustion basittir. Bir RGB GEOTIFF IMAGE + XYZ değerlerinden bir 3D arsaya ihtiyacım var.
15:22, bibinwilson

2
R kullanmak zorunda değilseniz, PDAL'ın
Pete Gadomski

Yanıtlar:


11

Sorunuzu daha önce belirsiz olduğu için açıklığa kavuştuğunuz için teşekkür ederiz. Raster paketindeki yığın veya tuğla işlevini kullanarak çok bantlı bir raster okuyabilir ve ilişkili RGB değerlerini, rasterden de ayıklama kullanarak bir sp SpatialPointsDataFrame nesnesine atayabilirsiniz. Data.frame nesnesinin (read.csv dosyasından kaynaklanan) bir sp noktası nesnesine, ayıklamaya aktarılabilen zorlaması, sp paketi kullanılarak gerçekleştirilir.

3D çizim rgl paketinden geliyor. Çizim etkileşimli olduğundan ve bir dosyaya aktarılmadığından, rgl.snapshot kullanarak bir dosya oluşturabilirsiniz. Temel rgb işlevi üç RGB değeri alır ve karşılık gelen tek değerli bir R rengi oluşturur. Verilere karşılık gelen bir vektör oluşturarak, rengi gerçek bir boyut olarak tanımlayan (ilk karışıklığınız gibi görünüyor) col bağımsız değişkenini kullanarak bir arsa renklendirebilirsiniz.

İşte hızlı bir kukla örneği.

require(rgl)
require(sp)

n=100

# Create a dummy datafame object with x,y,z values
lidar <- data.frame(x=runif(n,1,10), y=runif(n,1,10), z=runif(n,0,50))
  coordinates(lidar) <- ~x+y

# Add dummy RGB values 
lidar@data <- data.frame(lidar@data, red=round(runif(n,0,255),0), green=round(runif(n,0,255),0), 
                         blue=round(runif(n,0,255),0)) 

# Create color vector using rgb values
cols <- rgb(lidar@data[,2:4], maxColorValue = 255)

# Interactive 3D plot
plot3d(coordinates(lidar)[,1],coordinates(lidar)[,2],lidar@data[,"z"], col=cols,
       pch=18, size=0.75, type="s", xlab="x", ylab="x", zlab="elevation")

Ve işte sağladığınız verilerle çalışan bir örnek.

require(raster)
require(rgl)

setwd("D:/TMP")

# read flat file and assign names
lidar <- read.table("lidar.txt")
  names(lidar) <- c("x","y","z")

# remove the scatter outlier(s)  
lidar <- lidar[lidar$z >= 255 ,]

# Coerce to sp spatialPointsDataFrame object
coordinates(lidar) <- ~x+y  

# subsample data (makes more tractable but not necessary)  
n=10000 
lidar <- lidar[sample(1:nrow(lidar),n),]

# Read RGB tiff file  
img <- stack("image.tif")
  names(img) <- c("r","g","b")

# Assign RGB values from raster to points
lidar@data <- data.frame(lidar@data, extract(img, lidar))

# Remove NA values so rgb function will not fail
na.idx <- unique(as.data.frame(which(is.na(lidar@data), arr.ind = TRUE))[,1])
  lidar <- lidar[-na.idx,]

# Create color vector using rgb values
cols <- rgb(lidar@data[,2:4], maxColorValue = 255)

# Interactive 3D plot
plot3d(coordinates(lidar)[,1],coordinates(lidar)[,2],lidar@data[,"z"], col=cols,
       pch=18, size=0.35, type="s", xlab="x", ylab="x", zlab="elevation")

Poster tarafından sağlanan örnek verilerle yukarıdaki kodu denedim. Çalışıyor, ancak RGB renkleri biraz dağınık. Sokaklar ve viceversa gibi renkli çatılar var. Bu muhtemelen örnek txt lidardata basamaklarındaki çok az hassasiyetten mi kaynaklanıyor?
Şubat

3

LiDAR verilerini ve RGB değerlerini 3B olarak oluşturmanın bir alternatifi FugroViewer'dır .

Aşağıda, verdikleri örnek verileri içeren bir örnek bulunmaktadır. Bmore_XYZIRGB.xyzAşağıdaki gibi başlıklı dosyayı kullandım :

resim açıklamasını buraya girin

Fugro Viewer'da açarken dosyadaki uygun alanları seçin (bu durumda, bir .xyz dosyası):

resim açıklamasını buraya girin

Ardından, aracı seçerek RGB verilerini kullanarak noktaları renklendirin Color Points by Encoding RGB Image Values(aşağıdaki ekran görüntüsünde kırmızı oka bakın). 3D3D görselleştirme için düğmeyi açın .

resim açıklamasını buraya girin


3

Düzenleme: Mathiaskopo tarafından belirtildiği gibi, LAStools'un daha yeni sürümleri lascolor ( README ) kullanıyor.

lascolor -i LiDAR.las -image image.tif -odix _rgb -olas

Başka bir seçenek las2las'ı aşağıdaki gibi kullanmak olacaktır :

las2las -i input.las --color-source RGB_photo.tif -o output.las --file-format 1.2 --point-format 3 -v    

En yeni sürüm lascolor kullanıyor: lascolor -i LiDAR.las -image image.tif -odix _rgb -olas
Mathiaskopo

2

Bu kod, bir taramadan x, y, z değerlerini ayıklamak ve 3D modeline sahip olmak için gdal, numpy ve matplotlib kullanır.

#!/usr/bin/env python
# -*- coding: utf-8

#Libraries
from osgeo import gdal
from os import system
import struct
import time

import numpy as np
from matplotlib.mlab import griddata
from mpl_toolkits.mplot3d.axes3d import *
from matplotlib import cm
import matplotlib.pyplot as plt

#Function to extract x,y,z values
def getCoorXYZ(band):

    # fmttypes: Byte, UInt16, Int16, UInt32, Int32, Float32 y Float64
    fmttypes = {'Byte':'B', 'UInt16':'H', 'Int16':'h', 'UInt32':'I', 'Int32':'i', 'Float32':'f', 'Float64':'d'}

    print "rows = %d columns = %d" % (band.YSize, band.XSize)

    BandType = gdal.GetDataTypeName(band.DataType)

    print "Data type = ", BandType

    x = []
    y_ = []
    z = []

    inc_x = 0

    for y in range(band.YSize):

        scanline = band.ReadRaster(0, y, band.XSize, 1, band.XSize, 1, band.DataType)
        values = struct.unpack(fmttypes[BandType] * band.XSize, scanline)

        for value in values:
            z.append(value)
            inc_x += 1
            y_.append(inc_x)
            x.append(y+1)           

        inc_x = 0

    return x, y_, z

#Program start here!

system("clear")

nameraster = str(raw_input("raster name = ? "))

start = time.time()

dataset = gdal.Open(nameraster)
band = dataset.GetRasterBand(1)

print "Processing %s" % nameraster

x,y,z = getCoorXYZ(band)

# grid 2D construction
xi = np.linspace(min(x), max(x))
yi = np.linspace(min(y), max(y))
X, Y = np.meshgrid(xi, yi)

# interpolation
Z = griddata(x, y, z, xi, yi)

#Visualization with Matplotlib
fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet,linewidth=1, antialiased=True)
plt.plot

end = time.time()

time_tot = end - start

print "Total time = %.4f s" % time_tot     

plt.show() #necessary for having a static window

Yukarıdaki kodu? Eğim uzunluğu rasteriyle (GTiff, 50 satır x 50 sütun) kullandım ve aşağıdaki sonucu elde ettim:

resim açıklamasını buraya girin


1
aslında 3D modeli alıyorum. Ancak her piksel için karşılık gelen RGB'ye sahip olmalıyım, bunu GEOTiff görüntüsünden çıkarmam ve 3D modeline koymam gerekiyor
bibinwilson

Kodum 3D modelinizi almak için yararlı oldu mu?
xunilk
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.