R을 사용하여 Geotiff 이미지에서 LiDAR 데이터로 RGB 값 할당


10

Geotiff 이미지와 해당 Lidar 데이터 (x, y, z)를 UTM 좌표로 지정했습니다. Lidar 데이터를 이미지의 RGB 값과 병합해야합니다.

즉, 결국에는 Geotiff 이미지의 해당 RGB 값으로 코딩 된 LiDAR 구름 색의 각 점을 (3D) 플롯해야합니다.

QGIS를 사용하여 Lidar 데이터를 shapefile로 변환했습니다. 다음에 어떻게해야합니까?

R에서는 plot3D함수를 시도했지만 작동하지 않았습니다. 텍스트 doc , shapefile 및 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 @ 데이터, I, J, ..., 드롭 = FALSE) 미사용 인수 (1)

편집하다:

아래와 같이 RGB가없는 3D 모델을 얻었습니다.

여기에 이미지 설명을 입력하십시오



1
질문을하는 방식으로 말을 혼란스럽게하고 코드는 말도 안됩니다. 다각형은 불연속 영역을 나타내며 점은 x, y 위치입니다. 다각형이 아닌 점 피쳐 클래스를 읽는 것처럼 보입니다. 이 경우 추출 기능에서 "fun = mean"을 원하지 않습니다. 또한 R은 큰 점 구름의 3D 플롯에 이상적인 소프트웨어는 아니라고 지적합니다. 또한 시각화의 의도는 좋지만 3D 데이터에 투영 된 2D의 시차 문제로 인해 분석적으로 사용할 수 없습니다.
Jeffrey Evans

shapefile과 TIFF 파일을 병합하여 다른 소프트웨어 도구를 사용하여 플롯 할 수있는 방법이 있습니까?
bibinwilson

qustion은 간단하다. 하나의 RGB GEOTIFF IMAGE + XYZ 값에서 3D 플롯이 필요합니다.
bibinwilson

2
R을 사용할 필요가없는 경우 PDAL의 채색
Pete Gadomski

답변:


11

이전에는 확실하지 않은 질문을 명확하게 설명해 주셔서 감사합니다. 래스터 패키지에서 스택 또는 브릭 기능을 사용하여 멀티 밴드 래스터를 읽고 래스터에서 추출을 사용하여 관련 RGB 값을 sp SpatialPointsDataFrame 객체에 할당 할 수 있습니다. sp 패키지를 사용하여 data.frame 객체 (read.csv의 결과)를 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 색상은 약간 지저분합니다. 나는 거리와 그 반대의 솜 지붕을 가지고있다. 샘플 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는 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

이 코드는 래스터에서 x, y, z 값을 추출하고 3D 모델을 만들기 위해 gdal, numpy 및 matplotlib을 사용합니다.

#!/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 rows x 50 columns)와 함께 사용하여 다음 결과를 얻었습니다.

여기에 이미지 설명을 입력하십시오


1
실제로 3D 모델을 받고 있습니다. 그러나 각 픽셀에 해당하는 RGB가 필요합니다. GEOTiff 이미지에서이를 추출하고 3D 모델에 넣어야합니다
bibinwilson

내 코드가 3D 모델을 얻는 데 유용 했습니까?
xunilk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.