如何将多个TIFF合并到Scala中的一个大型Geotiff中?

时间:2019-04-04 10:44:20

标签: scala tiff geotiff geotrellis

我正在使用数字地面模型(DGM)查找水深和水深的项目。我有多个涵盖感兴趣区域的tiff文件,我想将它们合并为一个tiff文件以进行快速处理。 如何使用下面的我自己的代码或其他任何方法将它们组合在一起?

我试图通过并排将图块作为输入然后合并它们来拼接图块,但它抛出GC error的原因可能是因为代码本身存在问题。

import geotrellis.proj4._
import geotrellis.raster._
import geotrellis.raster.io.geotiff._
object waterdepth {
  val directories = List("data")

  //constants to differentiate which bands to use
  val R_BAND = 0
  val G_BAND = 1
  val NIR_BAND = 2

  // Path to our landsat band geotiffs.
  def bandPath(directory: String) = s"../biggis-landuse/radar_data/${directory}"

  def main(args: Array[String]): Unit = {
    directories.map(directory => generateMultibandGeoTiffFile(directory))
  }

  def generateMultibandGeoTiffFile(directory: String) = {
    val tiffFiles = new java.io.File(bandPath(directory)).listFiles.map(_.toString)

    val singleBandGeoTiffArray = tiffFiles.foldLeft(Array[SinglebandGeoTiff]())((acc, el:String) => {
      acc :+ SinglebandGeoTiff(el)
    })

    val tileArray = ArrayMultibandTile(singleBandGeoTiffArray.map(_.tile))

    println(s"Writing out $directory multispectral tif")
    MultibandGeoTiff(tileArray, singleBandGeoTiffArray(0).extent, singleBandGeoTiffArray(0).crs).write(s"data/$directory.tif")

它应该能够从所有单独的文件中创建一个tif文件,但会引发内存错误。

1 个答案:

答案 0 :(得分:1)

您遵循的想法是正确的,可能是由于将大量TIFF加载到内存中而导致OOM发生,因此这并不奇怪。解决方案是为JVM分配更多的内存。但是,您可以尝试进行这种小的优化(可能会起作用):

import geotrellis.proj4._
import geotrellis.raster._
import geotrellis.raster.io.geotiff._
import geotrellis.raster.io.geotiff.reader._

import java.io.File

def generateMultibandGeoTiffFile(directory: String) = {
  val tiffs =
    new File(bandPath(directory))
      .listFiles
      .map(_.toString)
      // streaming = true won't force all bytes to load into memory
      // only tiff metadata is fetched here
      .map(GeoTiffReader.readSingleband(_, streaming = true))

  val (extent, crs) = {
    val tiff = tiffs.head
    tiff.extent -> tiff.crs
  }

  // TIFF segments bytes fetch will start only during the write
  MultibandGeoTiff(
    MultibandTile(tiffs.map(_.tile)), 
    extent, crs
  ).write(s"data/$directory.tif")
}

}