Gán các giá trị RGB từ hình ảnh Geotiff cho dữ liệu LiDAR, sử dụng R


10

Tôi đã đưa ra một hình ảnh Geotiff và dữ liệu tương ứng của nó (x, y, z) trong tọa độ UTM. Tôi cần hợp nhất dữ liệu Lidar với các giá trị RGB từ hình ảnh.

Điều đó có nghĩa là, cuối cùng, tôi cần vẽ đồ thị (3D) từng điểm của màu đám mây LiDAR được mã hóa với giá trị RGB tương ứng của nó từ hình ảnh Geotiff.

Tôi đã chuyển đổi dữ liệu của Lidar thành một shapefile bằng cách sử dụng QGIS. Tôi nên làm gì tiếp theo?

Trong R, tôi đã thử plot3Dchức năng này, nhưng, nó không hoạt động. Tôi đang đính kèm tài liệu văn bản , shapefile và hình ảnh tif

Biên tập:

Tôi đã thực hiện chương trình sau như hình dưới đây:

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

Nhưng trong khi cố gắng vẽ đồ thị, nó hiển thị lỗi sau:

Lỗi trong [.data.frame(x @ data, i, j, ..., drop = FALSE): đối số không được sử dụng (1)

Biên tập:

Tôi đã có mô hình 3D mà không có RGB như dưới đây:

nhập mô tả hình ảnh ở đây



1
Bạn đang nhầm lẫn các thuật ngữ theo cách làm cho câu hỏi và mã của bạn, vô nghĩa. Đa giác đại diện cho các khu vực riêng biệt trong khi các điểm là các vị trí x, y rõ ràng. Có vẻ như bạn đang đọc một lớp tính năng điểm chứ không phải đa giác. Nếu đây là trường hợp, bạn không muốn "fun = mean" trong chức năng giải nén. Tôi cũng sẽ chỉ ra rằng R không phải là phần mềm lý tưởng cho các ô 3D của các đám mây điểm lớn. Ngoài ra, ý định của bạn là tốt để trực quan hóa nhưng do các vấn đề thị sai của 2D được chiếu lên dữ liệu 3D, bạn không thể sử dụng phân tích này.
Jeffrey Evans

Có cách nào để hợp nhất shapefile và các tệp TIFF không, để tôi có thể sử dụng một số công cụ phần mềm khác để vẽ chúng ra.
bibinwilson

đốt là đơn giản. Tôi cần một sơ đồ 3D từ một giá trị RGB GEOTIFF IMAGE + XYZ.
bibinwilson

2
Nếu bạn không phải sử dụng R, bạn có thể sử dụng bộ lọc màu của PDAL
Pete Gadomski

Câu trả lời:


11

Cảm ơn bạn đã làm rõ câu hỏi của bạn vì trước đây nó không rõ ràng. Bạn có thể đọc raster multiband bằng cách sử dụng hàm stack hoặc brick trong gói raster và gán các giá trị RGB được liên kết cho một đối tượng Sp SpatialPointsDataFrame bằng trích xuất, cũng từ raster. Sự ép buộc của đối tượng data.frame (kết quả từ read.csv) đến một đối tượng điểm sp, có thể được truyền để giải nén, đạt được bằng cách sử dụng gói sp.

Cốt truyện 3D đến từ gói rgl. Vì cốt truyện là tương tác và không được chuyển đến một tệp, bạn có thể tạo tệp bằng rgl.snapshot. Hàm rgb cơ sở nhận ba giá trị RGB và tạo màu R giá trị đơn tương ứng. Bằng cách tạo một vectơ, tương ứng với dữ liệu, bạn có thể tô màu một ô bằng cách sử dụng đối số col mà không xác định màu là kích thước thực (có vẻ là sự nhầm lẫn ban đầu của bạn).

Dưới đây là một ví dụ giả nhanh chóng.

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

Và, đây là một ví dụ hoạt động với dữ liệu bạn cung cấp.

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

Tôi đã thử mã ở trên với dữ liệu mẫu được cung cấp bởi người đăng. Nó hoạt động, nhưng màu RGB hơi lộn xộn. Tôi có mái nhà màu như đường phố và ngược lại. Đây có phải là chắc chắn do quá ít độ chính xác trong các chữ số của mẫu txt capardata?
umbe1987

3

Một thay thế để kết xuất dữ liệu LiDAR và giá trị RGB trong 3D là FugroViewer .

Dưới đây, có một ví dụ với dữ liệu mẫu họ cung cấp. Tôi đã sử dụng tập tin có tiêu đề Bmore_XYZIRGB.xyztrông như thế này:

nhập mô tả hình ảnh ở đây

Khi mở trong Trình xem Fugro, chọn các trường tương ứng có sẵn trong tệp (trong trường hợp này là tệp .xyz):

nhập mô tả hình ảnh ở đây

Sau đó, tô màu các điểm bằng dữ liệu RGB, chọn công cụ Color Points by Encoding RGB Image Values(xem mũi tên màu đỏ trên ảnh chụp màn hình bên dưới). Bật 3Dnút để hiển thị 3D.

nhập mô tả hình ảnh ở đây


3

Chỉnh sửa: như Mathiaskopo đã đề cập, các phiên bản mới hơn của LAStools sử dụng lascolor ( README ).

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

Một lựa chọn khác là sử dụng las2las như sau:

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

Phiên bản mới nhất đang sử dụng lascolor: lascolor -i LiDAR.las -image image.tif -odix _rgb -olas
Mathiaskopo

2

Mã này sử dụng gdal, numpy và matplotlib để trích xuất các giá trị x, y, z từ raster và để có mô hình 3D của nó.

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

Tôi đã sử dụng đoạn mã trên với một raster độ dài (GTiff, 50 hàng x 50 cột) và tôi đã thu được kết quả như sau:

nhập mô tả hình ảnh ở đây


1
thực sự tôi đang nhận được mô hình 3D. Nhưng tôi cần phải có RGB tương ứng cho mỗi pixel, tôi cần phải trích rằng từ hình ảnh GeoTIFF và nhu cầu để đưa vào mô hình 3D
bibinwilson

Mã của tôi có hữu ích để lấy mô hình 3D của bạn không?
xunilk 18/03/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.