Assegnare valori RGB dall'immagine Geotiff ai dati LiDAR, usando R


10

Ho fornito un'immagine Geotiff e i corrispondenti dati Lidar (x, y, z) in coordinate UTM. Ho bisogno di unire i dati Lidar con i valori RGB dall'immagine.

Ciò significa che alla fine ho bisogno di tracciare (3D) ogni punto del colore della nuvola LiDAR codificato con il suo corrispondente valore RGB dall'immagine Geotiff.

Ho convertito i dati Lidar in un file di forma usando QGIS. Cosa dovrei fare dopo?

In R, ho provato la plot3Dfunzione, ma non ha funzionato. Allego il documento di testo , lo shapefile e l' immagine tif

Modificare:

Ho fatto il seguente programma come mostrato di seguito:

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)
 }
}

Ma durante il tentativo di tracciare il grafico, mostra il seguente errore:

Errore in [.data.frame(x @ data, i, j, ..., drop = FALSE): argomento non utilizzato (1)

Modificare:

Ho ottenuto il modello 3D senza RGB come mostrato di seguito:

inserisci qui la descrizione dell'immagine



1
Stai confondendo i termini in un modo che rende la domanda e il tuo codice privi di senso. I poligoni rappresentano aree discrete mentre i punti sono posizioni esplicite x, y. Sembra che tu stia leggendo una classe di caratteristiche punto e non un poligono. In questo caso, non si desidera "fun = mean" nella funzione di estrazione. Vorrei anche sottolineare che R non è il software ideale per grafici 3D di nuvole di punti di grandi dimensioni. Inoltre, il tuo intento va bene per la visualizzazione ma a causa di problemi di parallasse del 2D proiettati su dati 3D, non puoi usarlo analiticamente.
Jeffrey Evans,

Esiste un modo per unire lo shapefile e i file TIFF, in modo che io possa utilizzare alcuni altri strumenti software per tracciarli.
Bibinwilson,

qustion è semplice. Ho bisogno di un grafico 3D da un valore RGB GEOTIFF IMAGE + XYZ.
Bibinwilson,

2
Se non è necessario utilizzare R, è possibile utilizzare il filtro di colorazione di PDAL
Pete Gadomski

Risposte:


11

Grazie per aver chiarito la tua domanda in quanto precedentemente non era abbastanza chiara. È possibile leggere un raster multibanda usando la funzione stack o brick nel pacchetto raster e assegnare i valori RGB associati a un oggetto sp SpatialPointsDataFrame usando extract, anche da raster. La coercizione dell'oggetto data.frame (che risulta da read.csv) a un oggetto sp point, che può essere passato per estrarre, viene ottenuta usando il pacchetto sp.

La trama 3D proviene dal pacchetto rgl. Poiché la trama è interattiva e non passata a un file, è possibile creare un file utilizzando rgl.snapshot. La funzione rgb di base accetta tre valori RGB e crea un colore R a valore singolo corrispondente. Creando un vettore, corrispondente ai dati, puoi colorare un grafico usando l'argomento col senza definire il colore come una dimensione effettiva (che sembrava essere la tua confusione iniziale).

Ecco un rapido esempio fittizio.

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")

E, ecco un esempio funzionante con i dati che hai fornito.

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")

Ho provato il codice sopra con i dati di esempio forniti dal poster. Funziona, ma i colori RGB sono un po 'disordinati. Ho dei tetti colorati come strade e viceversa. Probabilmente ciò è dovuto a una precisione troppo ridotta nelle cifre del campione txt lidardata?
umbe1987,

3

Un'alternativa per il rendering dei dati LiDAR e dei valori RGB in 3D è FugroViewer .

Di seguito, c'è un esempio con i dati di esempio che forniscono. Ho usato il file intitolato Bmore_XYZIRGB.xyzche assomiglia a questo:

inserisci qui la descrizione dell'immagine

All'apertura in Fugro Viewer selezionare i campi corrispondenti disponibili all'interno del file (in questo caso, un file .xyz):

inserisci qui la descrizione dell'immagine

Quindi, colora i punti usando i dati RGB, selezionando lo strumento Color Points by Encoding RGB Image Values(vedi la freccia rossa nella schermata qui sotto). Attiva il 3Dpulsante per la visualizzazione 3D.

inserisci qui la descrizione dell'immagine


3

Modifica: come menzionato da Mathiaskopo, le versioni più recenti di LAStools usano lascolor ( README ).

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

Un'altra opzione sarebbe quella di utilizzare las2las come segue:

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

La versione più recente utilizza lascolor: lascolor -i LiDAR.las -image image.tif -odix _rgb -olas
Mathiaskopo

2

Questo codice usa gdal, numpy e matplotlib per estrarre i valori x, y, z da un raster e per avere un modello 3D di esso.

#!/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

Ho usato il codice sopra con un raster di lunghezza inclinata (GTiff, 50 righe x 50 colonne) e ho ottenuto il seguente risultato:

inserisci qui la descrizione dell'immagine


1
in realtà sto ottenendo il modello 3D. Ma devo avere l'RGB corrispondente per ogni pixel, devo estrarlo dall'immagine GEOTiff e devo inserire il modello 3D
bibinwilson

Il mio codice è stato utile per ottenere il tuo modello 3D?
Xunilk,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.