Sunday, 16 June 2019

raster - Assigning RGB values from Geotiff image to LiDAR data, using R


I have given a Geotiff image and its corresponding Lidar data (x,y,z) in UTM coordinates. I need to merge the Lidar data with the RGB values from the image.


That means, at the end, I need to plot (3D) each point of the LiDAR cloud color coded with its corresponding RGB value from the Geotiff image.


I converted the Lidar data into a shapefile using QGIS. What should I do next?


In R, I tried the plot3D function, but, it did not work. I'm attaching the text doc, shapefile, and tif image


Edit:


I've done the following program as shown below:



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

But while trying to plot the graph, it shows the following error:



Error in [.data.frame(x@data, i, j, ..., drop = FALSE) : unused argument (1)



Edit:



I got the 3D model without the RGB as shown below:


enter image description here



Answer



Thank you for clarifying your question as it was previously quite unclear. You can read a multiband raster using the stack or brick function in the raster package and assign the associated RGB values to an sp SpatialPointsDataFrame object using extract, also from raster. Coercion of the data.frame object (which results from read.csv) to an sp point object,that can be passed to extract, is achieved using the sp package.


The 3D plot comes from the rgl package. Since the plot is interactive and not passed to a file, you can create a file using rgl.snapshot. The base rgb function takes three RGB values and creates a corresponding single-value R color. By creating a vector, corresponding to the data, you can color a plot using the col argument without defining color as an actual dimension (which seemed to be your initial confusion).


Here is a quick dummy example.


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

And, here is a worked example with the data you provided.


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

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...