Menetapkan nilai RGB dari gambar Geotiff ke data LiDAR, menggunakan R


10

Saya telah memberikan gambar Geotiff dan data Lidar terkait (x, y, z) dalam koordinat UTM. Saya perlu menggabungkan data Lidar dengan nilai RGB dari gambar.

Itu berarti, pada akhirnya, saya perlu memplot (3D) setiap titik warna awan LiDAR yang dikodekan dengan nilai RGB yang sesuai dari gambar Geotiff.

Saya mengubah data Lidar menjadi shapefile menggunakan QGIS. Apa yang harus saya lakukan selanjutnya?

Di R, saya mencoba plot3Dfungsinya, tetapi tidak berhasil. Saya melampirkan dokumen teks , shapefile, dan gambar tif

Edit:

Saya telah melakukan program berikut seperti yang ditunjukkan di bawah ini:

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

Tetapi ketika mencoba untuk merencanakan grafik, itu menunjukkan kesalahan berikut:

Kesalahan dalam [.data.frame(x @ data, i, j, ..., drop = FALSE): argumen yang tidak digunakan (1)

Edit:

Saya mendapatkan model 3D tanpa RGB seperti yang ditunjukkan di bawah ini:

masukkan deskripsi gambar di sini



1
Anda membingungkan istilah dengan cara yang membuat pertanyaan, dan kode Anda, tidak masuk akal. Poligon mewakili area diskrit sedangkan titik eksplisit x, lokasi y. Sepertinya Anda membaca kelas fitur titik dan bukan poligon. Jika demikian, Anda tidak ingin "fun = mean" dalam fungsi ekstrak. Saya juga akan menunjukkan bahwa R bukan perangkat lunak yang ideal untuk plot 3D awan titik besar. Tambahan, maksud Anda baik untuk visualisasi tetapi karena masalah paralaks dari 2D yang diproyeksikan ke data 3D, Anda tidak dapat menggunakan ini secara analitis.
Jeffrey Evans

Apakah ada cara untuk menggabungkan file shapefile dan TIFF, sehingga saya dapat menggunakan beberapa perangkat lunak lain untuk merencanakannya.
bibinwilson

qustion itu sederhana. Saya membutuhkan plot 3D dari satu nilai RGB GEOTIFF IMAGE + XYZ.
bibinwilson

2
Jika Anda tidak harus menggunakan R, Anda dapat menggunakan filter pewarnaan PDAL: pdal.io/stages/filters.colorization.html
Pete Gadomski

Jawaban:


11

Terima kasih telah menjelaskan pertanyaan Anda karena sebelumnya tidak terlalu jelas. Anda dapat membaca raster multiband menggunakan fungsi stack atau brick dalam paket raster dan menetapkan nilai RGB terkait ke objek sp SpatialPointsDataFrame menggunakan ekstrak, juga dari raster. Pemaksaan objek data.frame (yang dihasilkan dari read.csv) ke objek titik sp, yang dapat diteruskan untuk mengekstrak, dicapai menggunakan paket sp.

Plot 3D berasal dari paket rgl. Karena plotnya interaktif dan tidak diteruskan ke file, Anda dapat membuat file menggunakan rgl.snapshot. Fungsi rgb dasar mengambil tiga nilai RGB dan membuat warna R nilai tunggal yang sesuai. Dengan membuat vektor, sesuai dengan data, Anda dapat mewarnai plot menggunakan argumen col tanpa mendefinisikan warna sebagai dimensi aktual (yang tampaknya menjadi kebingungan awal Anda).

Ini adalah contoh boneka cepat.

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

Dan, berikut adalah contoh yang berfungsi dengan data yang Anda berikan.

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

Saya mencoba kode di atas dengan data sampel yang disediakan oleh poster. Ini memang berhasil, tetapi warna RGB agak berantakan. Saya memiliki beberapa atap berwarna seperti jalan dan sebaliknya. Apakah ini mungkin karena terlalu sedikit ketepatan dalam digit sampel txt lidardata?
umbe1987

3

Alternatif untuk membuat data LiDAR dan nilai RGB dalam 3D adalah FugroViewer .

Di bawah ini, ada contoh dengan data sampel yang mereka berikan. Saya menggunakan file berhak Bmore_XYZIRGB.xyzyang terlihat seperti ini:

masukkan deskripsi gambar di sini

Saat membuka di Fugro Viewer pilih bidang terkait yang tersedia dalam file (dalam hal ini, file .xyz):

masukkan deskripsi gambar di sini

Kemudian, warnai titik-titik menggunakan data RGB, pilih alat Color Points by Encoding RGB Image Values(lihat panah merah pada tangkapan layar di bawah). Aktifkan 3Dtombol untuk visualisasi 3D.

masukkan deskripsi gambar di sini


3

Sunting: seperti yang disebutkan oleh Mathiaskopo, versi terbaru dari LAStools menggunakan lascolor ( README ).

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

Pilihan lain adalah menggunakan las2las sebagai berikut:

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

Versi terbaru menggunakan lascolor: lascolor -i LiDAR.las -image image.tif -odix _rgb -olas
Mathiaskopo

2

Kode ini menggunakan gdal, numpy dan matplotlib untuk mengekstraksi nilai x, y, z dari raster dan untuk memiliki model 3Dnya.

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

Saya menggunakan kode di atas dengan? Slope lenght raster (GTiff, 50 rows x 50 kolom) dan saya mendapatkan hasil sebagai berikut:

masukkan deskripsi gambar di sini


1
sebenarnya saya mendapatkan model 3D. Tetapi saya perlu memiliki RGB yang sesuai untuk setiap piksel, saya perlu mengekstraknya dari gambar GEOTiff dan perlu memasukkannya ke dalam model 3D
bibinwilson

Apakah kode saya bermanfaat untuk mendapatkan model 3D Anda?
xunilk
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.