什么是GeoTrellis?

GeoTrellis 是一个 Scala 库和框架,它使用 Apache Spark 处理栅格数据。

GeoTrellis 以尽可能快的速度读取、写入和操作栅格数据。它实现了许多地图代数操作以及矢量到栅格或栅格到矢量的操作。

GeoTrellis 还提供了将栅格渲染为 PNG 或将有关栅格文件的元数据存储为 JSON 的工具。它旨在通过 RESTful 端点以 Web 速度(亚秒或更短)提供栅格处理,并提供大型栅格数据集的快速批处理。

为什么是GeoTrellis?

栅格处理传统上是一项缓慢的任务,这促使矢量数据处理作为替代方案的进步。然而,随着每年越来越多的卫星数据被公开,栅格数据不会随处可见。 GeoTrellis 是对不断增长的大规模栅格处理需求的一种解决方案。

配置开发环境

1.安装scala(2.12.10)、sbt并配置环境变量

image-20211218112800558

2.sbt 设置仓库地址步骤

SBT_HOME\sbt\conf下新建repository.properties文件,内容如下

1
2
3
4
5
[repositories]

local

ali: https://maven.aliyun.com/nexus/content/repositories/central/
1
2
3
4
5
6
7
[repositories]
local
aliyun: http://maven.aliyun.com/nexus/content/groups/public
typesafe-ivy-releases: http://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly
sonatype-oss-releases
maven-central
sonatype-oss-snapshots

修改sbtconfig.txt文件,加上如下内容:

1
2
3
4
5
6
-Dsbt.log.format=true
-Dsbt.boot.directory=E:/dev_tools/sbt/.sbt/boot
-Dsbt.ivy.home=E:/dev_tools/sbt/.ivy2
-Dsbt.global.base=E:/dev_tools/sbt/.sbt

-Dsbt.repository.config=E:/dev_tools/sbt/conf/repository.properties

这些是设置sbt下载项目依赖目录。

3.IDEA安装Scala插件

image-20211218113321996

4.sbt换源,解决速度慢的问题

https://segmentfault.com/a/1190000021817234

根据官方文档,首先要设置sbt.override.build.repostrue才能换源。设置以后sbt就会读取~/.sbt/repositories文件中的[repositories]部分。

image-20211220214238281

设置方法(适用于Windows)就是将sbt安装目录下的conf/sbtconfig.txt中增加一行JVM启动参数 -Dsbt.override.build.repos=true

而对于Intellij Idea,则是在设置中sbt页面的VM Parameters中增加同样的一行启动配置 -Dsbt.override.build.repos=true

image-20211220214822472

这里给出我的配置文件,使用的是阿里云的maven仓库,保存的路径为~/.sbt/repositories

1
2
3
4
5
6
7
8
[repositories]
local
aliyun: https://maven.aliyun.com/repository/public
typesafe: https://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly
ivy-sbt-plugin:https://dl.bintray.com/sbt/sbt-plugin-releases/, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]
sonatype-oss-releases
maven-central
sonatype-oss-snapshots

5.IDEA创建项目

①新建项目

image-20211218140825829 image-20211218141016326

②选择File->project Structure

左边选择Modules 右边选择Sources,将src目录Mark as Sources后就可以在src下新建Scala类了

然后右边继续选择Dependencies,点击+号,添加Scala类库

image-20211218141703986

image-20211218144001915

前面的勾要勾选上

image-20211218144025191

③修改sbt构建设置

修改sbt构建设置,其中VM parameters配置为

1
2
3
4
5
6
7
8
-Xmx512M
-XX:MaxPermSize=256m
-XX:ReservedCodeCacheSize=128m
-Dsbt.log.format=true
-Dsbt.ivy.home=E:/dev_tools/sbt/.ivy2
-Dsbt.global.base=E:/dev_tools/sbt/.sbt

-Dsbt.repository.config=E:/dev_tools/sbt/conf/repository.properties

image-20211218142536080

④关于新建sbt task的步骤和设置

选择run->edit configuration,点击左上角+号,选择sbt task

tasks输入:~run

VM parameters输入:

1
2
3
4
5
6
7
8
9
-Xms512M
-Xmx1024M
-Xss1M
-XX:+CMSClassUnloadingEnabled
-Dsbt.log.format=true
-Dsbt.boot.directory=E:/dev_tools/sbt/.sbt/boot
-Dsbt.ivy.home=E:/dev_tools/sbt/.ivy2
-Dsbt.global.base=E:/dev_tools/sbt/.sbt
-Dsbt.repository.config=E:/dev_tools/sbt/conf/repository.properties

⑤创建文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package main.scala

/**
 * @Description
 * @Author bin
 * @Date 2021/12/18
 */
object Test extends App {
  val ages = Seq(42, 75, 29, 64)
  println(s"The oldest person is ${ages.max}")
}

object Test {
  def main(args: Array[String]) : Unit = {
    val msg = "hello world"
    println(msg)
  }
}

运行的时候出现如下错误:

image-20211218144456064

Build出现如下错误:

Extracting structure failed, reason: not ok build status:

==上面http换成https之后就没有报这个错误了==

GeoTrellis使用

1.入门

教程

拉官网给的代码运行

打开项目后先build一下,这个步骤要花费不少的时间

然后copy如下代码进行测试

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package demo

import geotrellis.raster._
import geotrellis.raster.mapalgebra.focal.Square
import geotrellis.spark._

object Main {
  def helloSentence = "Hello GeoTrellis"

  def helloRaster(): Unit = {
    val nd = NODATA    //-2147483648

    val input = Array[Int](
      nd, 7, 1, 1, 3, 5, 9, 8, 2,
      9, 1, 1, 2, 2, 2, 4, 3, 5,
      3, 8, 1, 3, 3, 3, 1, 2, 2,
      2, 4, 7, 1, nd, 1, 8, 4, 3)

    //将数组转化为4*9矩阵
    val iat = IntArrayTile(input, 9, 4)


    //用一个n*n的窗口对矩阵做卷积,设中心值为平均值
    //Square(i) => n = 2 * i + 1
    val focalNeighborhood = Square(1)
    println(focalNeighborhood)
    val meanTile = iat.focalMean(focalNeighborhood)

    for (i <- 0 to 3) {
      for (j <- 0 to 8) {
        print(meanTile.getDouble(j, i) + " ")
      }
      println()
    }
  }

  def main(args: Array[String]): Unit = {
    helloRaster()
  }
}

2.读本地Geotiff文件

一共四行代码

1
2
3
4
5
import geotrellis.raster.io.geotiff.reader.GeoTiffReader
import geotrellis.raster.io.geotiff._

val path: String = "filepath/filename.tif"
val geoTiff: SinglebandGeoTiff = GeoTiffReader.readSingleband(path)

这种方法用于读取但波段tif影像,要读取多波段影像,可以用

1
val geoTiff: MultibandGeoTiff = GeoTiffReader.readMultiband(path)

如果强行用GeoTiffReader.readSingleband(path)方法去读取一个多波段影像,则最后的返回结果是一个单波段影像,且其中的数据为原始影像中的第一个波段

此外,也可以用影像路径为参数直接构造一个Geotiff对象

1
2
3
import geotrellis.raster.io.geotiff.SinglebandGeoTiff

val geoTiff: SinglebandGeoTiff = SinglebandGeoTiff(path)

3.发布TMS服务

akka

scala的akka框架有一个极简的http service组件,是把原来spray框架集成到akka里面修改而成。

WebServer.scala

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package demo

import akka.actor.ActorSystem
import akka.http.javadsl.server.Route
import akka.http.scaladsl.Http//http().bindandhandle
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.stream.ActorMaterializer
import scala.io.StdIn
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._//path/get/complete
import akka.http.scaladsl.server.Directive0
import akka.http.scaladsl.server.Route
/**
 * @Description
 * @Author bin
 * @Date 2021/12/20
 */
object WebServer {

  def main(args: Array[String]): Unit = {
    implicit val system = ActorSystem("my-system")
    implicit val materilizer = ActorMaterializer()
    implicit val executionContext = system.dispatcher

    lazy val route =
      path("register"){
        get {
          complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Welcome to register my project</h1>"))
        }
      }
    val bindingFuture = Http().bindAndHandle(route,"localhost",8080)
    println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
    StdIn.readLine()
    bindingFuture
      //.flatMap(_.unbind())
      .onComplete(_ => system.terminate())
  }

}

配置文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Rename this as you see fit
name := "geotrellis-sbt-template"

version := "0.2.0"

scalaVersion := "2.11.12"

lazy val akkaHttpVersion = "10.0.11"
lazy val akkaVersion = "2.5.8"

lazy val root = (project in file("."))
  .settings(
    inThisBuild(List(
      organization :="com.example",
      scalaVersion :="2.12.4"
    )),
    name := "My-first-akka-http-project",
    libraryDependencies ++= Seq(
      "com.typesafe.akka" %% "akka-http"            % akkaHttpVersion,
      "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion,
      "com.typesafe.akka" %% "akka-http-xml"        % akkaHttpVersion,
      "com.typesafe.akka" %% "akka-stream"          % akkaVersion,
    )

  )

geotrellis-landsat-tutorial

以官网的例子为例,跑一个demo

做数据处理的时候报了如下错误,看来还是要先了解一下hadoop

image-20211221095521378