Присвоение значений RGB из изображения Geotiff данным LiDAR, используя R


10

Я дал изображение Геотифа и соответствующие ему лидарные данные (x, y, z) в координатах UTM. Мне нужно объединить данные лидара со значениями RGB из изображения.

Это означает, что в конце мне нужно построить (3D) каждую точку цвета облака LiDAR, закодированную с соответствующим значением RGB из изображения Geotiff.

Я преобразовал данные Lidar в шейп-файл, используя QGIS. Что я должен делать дальше?

В R я попробовал plot3Dфункцию, но она не сработала. Я прилагаю текстовый документ , шейп- файл и изображение TIF

Редактировать:

Я сделал следующую программу, как показано ниже:

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

Но при попытке построить график, он показывает следующую ошибку:

Ошибка в [.data.frame(x @ data, i, j, ..., drop = FALSE): неиспользованный аргумент (1)

Редактировать:

Я получил 3D-модель без RGB, как показано ниже:

введите описание изображения здесь



1
Вы путаете термины таким образом, что это делает вопрос, а ваш код бессмысленным. Полигоны представляют собой отдельные области, тогда как точки являются точными местоположениями x, y. Похоже, вы читаете класс точечных объектов, а не полигон. Если это так, вы не хотите, чтобы "fun = mean" в функции извлечения. Я также хотел бы отметить, что R не является идеальным программным обеспечением для трехмерных графиков больших облаков точек. Кроме того, ваше намерение подходит для визуализации, но из-за проблем параллакса 2D, проецируемых на 3D-данные, вы не можете использовать это аналитически.
Джеффри Эванс

Есть ли способ объединить шейп-файл и файлы TIFF, чтобы я мог использовать некоторые другие программные инструменты для их построения.
bibinwilson

Простота проста. Мне нужен 3D-график из одного значения RGB GEOTIFF IMAGE + XYZ.
bibinwilson

2
Если вам не нужно использовать R, вы можете использовать фильтр окраски PDAL
Пит Гадомски,

Ответы:


11

Спасибо за разъяснение вашего вопроса, так как ранее он был совершенно неясен. Вы можете прочитать многоканальный растр, используя функцию стека или кирпича в растровом пакете, и назначить связанные значения RGB для объекта sp SpatialPointsDataFrame, используя извлечение, также из растра. Приведение объекта data.frame (являющегося результатом read.csv) к объекту sp point, который можно передать для извлечения, достигается с помощью пакета sp.

3D-сюжет взят из пакета rgl. Поскольку график является интерактивным и не передается в файл, вы можете создать файл с помощью rgl.snapshot. Базовая функция rgb принимает три значения RGB и создает соответствующий одноцветный R-цвет. Создавая вектор, соответствующий данным, вы можете раскрасить график, используя аргумент col, не определяя цвет в качестве фактического измерения (что, по-видимому, было вашей первоначальной путаницей).

Вот быстрый пример.

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

И вот рабочий пример с предоставленными вами данными.

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

Я попробовал код выше с примерами данных, предоставленных постером. Это работает, но цвета RGB немного грязные. У меня есть крыша сома, окрашенная как улицы и наоборот. Вероятно ли это из-за слишком малой точности в цифрах образца TX LIDARDATA?
umbe1987

3

Альтернативой для визуализации данных LiDAR и значений RGB в 3D является FugroViewer .

Ниже приведен пример с примерами данных, которые они предоставляют. Я использовал файл под названием, Bmore_XYZIRGB.xyzкоторый выглядит так:

введите описание изображения здесь

При открытии в Fugro Viewer выберите соответствующие поля, доступные в файле (в данном случае файл .xyz):

введите описание изображения здесь

Затем раскрасьте точки, используя данные RGB, выбрав инструмент Color Points by Encoding RGB Image Values(см. Красную стрелку на снимке экрана ниже). Включите 3Dкнопку для 3D-визуализации.

введите описание изображения здесь


3

Редактировать: как уже упоминалось Mathiaskopo, более новые версии LAStools используют lascolor ( README ).

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

Другой вариант - использовать las2las следующим образом:

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

В последней версии используется lascolor: lascolor -i LiDAR.las -image image.tif -odix _rgb -olas
Mathiaskopo

2

Этот код использует gdal, numpy и matplotlib для извлечения значений x, y, z из растра и получения его 3D-модели.

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

Я использовал приведенный выше код с растром? Наклонной длины (GTiff, 50 строк х 50 столбцов), и я получил следующий результат:

введите описание изображения здесь


1
на самом деле я получаю 3D-модель. Но мне нужно иметь соответствующий RGB для каждого пикселя, мне нужно извлечь его из изображения GEOTiff и вставить 3D-модель
bibinwilson

Был ли мой код полезен для получения вашей 3D модели?
xunilk
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.