Rを使用して、Geotiff画像からLiDARデータにRGB値を割り当てる


10

Geotiff画像とそれに対応するLidarデータ(x、y、z)をUTM座標で指定しました。Lidarデータを画像のRGB値とマージする必要があります。

つまり、最後に、Geotiff画像からの対応するRGB値でコード化されたLiDARクラウドカラーの各ポイントを(3D)プロットする必要があります。

LidarデータをQGISを使用してシェープファイルに変換しました。次に何をすればいいですか?

Rではそのplot3D機能を試しましたが、うまくいきませんでした。テキストdoc、シェープファイル、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)

編集:

以下に示すように、RGBなしの3Dモデルを取得しました。

ここに画像の説明を入力してください



1
あなたは質問をしている方法で用語を混乱させており、あなたのコードは無意味です。ポリゴンは個別の領域を表し、ポイントは明示的なX、Y位置です。ポリゴンではなくポイントフィーチャクラスを読み取っているようです。この場合、抽出関数で「fun = mean」を使用しないでください。また、Rは大きな点群の3Dプロットには理想的なソフトウェアではないことも指摘しておきます。さらに、あなたの意図は視覚化には問題ありませんが、3Dデータに投影された2Dの視差の問題のため、これを分析的に使用することはできません。
ジェフリーエヴァンス

シェープファイルとTIFFファイルをマージして、他のソフトウェアツールを使用してそれらをプロットできるようにする方法はありますか。
bibinwilson 2015年

質問は簡単です。1つのRGB GEOTIFF IMAGE + XYZ値からの3Dプロットが必要です。
bibinwilson 2015年

2
Rを使用する必要がない場合は、PDALのカラー化フィルターを使用できます。pdal.io/ stages
Pete Gadomski

回答:


11

以前は非常に不明瞭でしたので、質問を明確にしていただきありがとうございます。ラスターパッケージのスタックまたはブリック関数を使用してマルチバンドラスターを読み取り、抽出を使用して関連するRGB値をsp SpatialPointsDataFrameオブジェクトに割り当てることもできます(これもラスターから)。data.frameオブジェクト(read.csvの結果)を、抽出に渡すことができるspポイントオブジェクトに強制変換するには、spパッケージを使用します。

3Dプロットはrglパッケージからのものです。プロットはインタラクティブでファイルに渡されないため、rgl.snapshotを使用してファイルを作成できます。基本rgb関数は3つの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カラーは少し乱雑です。ぼんやりとした屋根が通りのような色になっていて、逆もまた同じです。これは、サンプルtxtのLIDARDATAの桁の精度が少なすぎるためでしょうか?
umbe1987

3

LiDARデータとRGB値を3Dでレンダリングする別の方法はFugroViewerです。

以下に、提供するサンプルデータの例を示します。Bmore_XYZIRGB.xyz次のようなタイトルのファイルを使用しました。

ここに画像の説明を入力してください

Fugro Viewerで開くときに、ファイル(この場合は.xyzファイル)内で使用可能な対応するフィールドを選択します。

ここに画像の説明を入力してください

次に、RGBデータを使用してポイントに色を付け、ツールを選択しますColor Points by Encoding RGB Image Values(下のスクリーンショットの赤い矢印を参照)。3D3D視覚化のボタンをオンにします。

ここに画像の説明を入力してください


3

編集: Mathiaskopoが述べたように、LAStoolsの新しいバージョンではlascolorREADME)を使用しています。

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

上記のコードを?slope lenghtラスター(GTiff、50行x 50列)で使用して、次の結果を得ました。

ここに画像の説明を入力してください


1
実際には3Dモデルを取得しています。しかし、各ピクセルに対応するRGBが必要です。それをGEOTiff画像から抽出して、3Dモデルに入れる必要があります
bibinwilson

私のコードは3Dモデルを取得するのに役立ちましたか?
xunilk 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.