【问题标题】:Convert 32-bit float raster to 16-bit in R在 R 中将 32 位浮点栅格转换为 16 位
【发布时间】:2021-03-26 08:27:03
【问题描述】:

我有大约 100 个不同的 4 波段卫星图像 .tif 栅格,它们具有 32 位浮点深度。我需要在缩放像素值时将这些转换为 R 中的 16 位无符号数(不仅仅是丢弃高值),但我不知道从哪里开始,即使是单个栅格,更不用说整个批次了。任何帮助将不胜感激!

使用更多信息进行编辑:我在光栅包文档中搜索了位、像素和深度关键字,但运气不佳。根据 dataType() 下的最小/最大像素值信息判断,我想从 FLT4S(32 位浮点)转到 INT2U(16 位)。我尝试使用 writeRaster() 设置数据类型,如示例中所示,但输出只是黑白图像而不是普通卫星图像。

image
class      : RasterStack 
dimensions : 4300, 8909, 38308700, 4  (nrow, ncol, ncell, nlayers)
resolution : 3, 3  (x, y)
extent     : 691032, 717759, 57492, 70392  (xmin, xmax, ymin, ymax)
crs        : +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
names      :        image.1,        image.2,        image.3,        image.4 
min values : 7.244503e-02, 8.278998e-02, 2.286164e-05, 8.571137e-02 
max values :    0.5347134,    0.3522218,    0.4896736,    0.7308348 

dataType(image) #[1] "FLT4S" "FLT4S" "FLT4S" "FLT4S"
image2 = writeRaster(image, 'new.tif', datatype='INT2U', overwrite=TRUE, format="GTiff")
dataType(image2) #[1] "INT2U"

image2
class      : RasterBrick 
dimensions : 4300, 8909, 38308700, 4  (nrow, ncol, ncell, nlayers)
resolution : 3, 3  (x, y)
extent     : 691032, 717759, 57492, 70392  (xmin, xmax, ymin, ymax)
crs        : +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
source     : new.tif 
names      : new.1, new.2, new.3, new.4 
min values :     0,     0,     0,     0 
max values :     1,     0,     0,     1 

【问题讨论】:

  • 你能改进你的问题吗?你尝试了什么?你想如何扩展?你能提供一个最小的例子吗?你看光栅包的帮助文件了吗?
  • @RobertHijmans,编辑中提供的附加信息。我不确定缩放是如何机械地工作的,例如在 ArcGIS 或 QGIS 中的位深度之间进行转换时,但基本上我希望落入 32 位范围内的每个像素都以 0-65,535 的 16 位范围表示。

标签: r r-raster sp bit-depth


【解决方案1】:

在您的示例中,您的实际值介于 0 和 1 之间。通过写入整数类型,这些都被截断为 0。如果您想写入 INT2U(无符号字节),您可以首先将值缩放到 0 之间和 255。

示例数据

library(raster)
b <- brick(system.file("external/rlogo.grd", package="raster"))
image <- clamp(b/255, 0, 0.6)
#class      : RasterBrick 
#dimensions : 77, 101, 7777, 3  (nrow, ncol, ncell, nlayers)
#resolution : 1, 1  (x, y)
#extent     : 0, 101, 0, 77  (xmin, xmax, ymin, ymax)
#crs        : +proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs 
#source     : memory
#names      : red, green, blue 
#min values :   0,     0,    0 
#max values : 0.6,   0.6,  0.6 

你做什么(截断)

fname <- paste0(tempfile(), ".tif")      
x <- writeRaster(image, fname, datatype='INT2U', overwrite=TRUE)
x
#min values : 0, 0, 0 
#max values : 1, 1, 1 

但请注意使用舍入时的区别

fname <- paste0(tempfile(), ".tif")      
y <- round(image)
z <- writeRaster(y, fname, datatype='INT2U', overwrite=TRUE)

s <- stack(x[[1]], z[[1]]) 
plot(s)

现在进行一些缩放

maxv <- 65535
r <- round(image * maxv)
fname <- paste0(tempfile(), ".tif")
s <- writeRaster(r, fname, datatype='INT2U', overwrite=TRUE)

#s
#min values :     0,     0,     0 
#max values : 39321, 39321, 39321 

使用您的数据,您将获得最大值

round(maxv * c(0.5347134, 0.3522218, 0.4896736, 0.7308348 ))
#[1] 35042 23083 32091 47895

您还可以选择将所有层的最大值设置为maxv,以保持更多变化(但使值不再与其他数据可比)---如果您使用较小的范围,则更相关,例如0-255。

ss <- round(maxv * image / maxValue(image))
#names      :   red, green,  blue 
#min values :     0,     0,     0 
#max values : 65535, 65535, 65535 

上述方法有效,因为最低值为零;如果你有负值,你会这样做

ss <- image - minValue(image)
ss <- round(maxv * ss / maxValue(ss))

在其他情况下,您可能想要使用clamp。所以你需要决定如何扩展

我展示的是线性缩放。还有其他方法。例如,还有scale 方法,用于改进数字的统计分布。 可能是相关的;但这取决于你的目标是什么。

注意。你不说你为什么这样做,那没关系。但如果是为了节省硬盘空间,可以改用压缩(见?writeRaster

【讨论】:

  • 谢谢!您是否有任何特殊原因建议您将其缩放到 0-255(8 位)而不是直接缩放到 0-65,535?我的目标是使用这些图像进行各种光谱分析。
  • 我的错----我在想INT1U(字节数据)!我会修正我的答案
猜你喜欢
  • 2010-12-12
  • 2011-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多