宙畑 Sorabatake

Notebooks

We created a Puzzle app using data on Tellus

This app was created to make people more familiar with SAR data and optical data on Tellus.

(1) Definition of Requirements

1.1 We wanted this kind of app!

Tellus has the feature of more loaded SAR data compared to other satellite data platforms.  While optical satellites use the reflection of the sun for its camera, an SAR satellite observes by actually emitting radio waves itself. Therefore, in contrast to optical satellites, SAR data is said to be more helpful as it can penetrate clouds and can observe even during the night.

However, SAR data is not well known to the public.

So, we came up with an idea to create an APP that teaches us and make us familiar about SAR and optical data.

The competed APP looks like this

 

1.2 Selection of implemented technology

Basic image analysis apps use Python as a programming language most of the time.  Python has a library that divides images, so we selected Python as our programming language as it seems to be the most efficient in the development of this app.

As for the framework for the front-end, we implemented PWA as we thought it much more useful than iOS or Android for most people.  In view of the ease in implementing PWA, we decided to use “Nuxt.js” and “@nuxjs/pwa”.

 

Puzzle image processing Python:  Pllow(image processing), flask(API)
Framework for front-end Nuxt.js, @nuxtjs/pwa

(2) Preparation

2.1 Environment Construction

We used Docker to manage the development environment.

2.2 Screen Design

As we have decided the implementation method, we will now think about the designing of the puzzle app.  While inputting game features, we stuck to detailed space motifs. For the start screen, we used an illustration of the Land Observing Satellite Daichi 2 (ALOS-2).

Start Screen
Screen to chose level of difficulty
Puzzle screen

(3) Implementation

3.1 Selecting the library

We used the following library during development.

We used flask as a simple API. We implemented a library called pillow in order to divide images.

Reference:
https://qiita.com/zaburo/items/5091041a5afb2a7dffc8

Library Description
flask

flask-api

To make API simpler
pillow To divide images
requests To create http request

Since it is not so efficient to convert images every time and directly connect with the API, we decided to obtain SAR images from API, and convert them to “png” for storing.

# SAR画像(.tif)をAPIから取得してきて、それを画像クロップして、pngに変換してストレージに保持している
_img = Image.open(BytesIO(_res.content))
_img.point(lambda i:i*(1./256)).convert('L').crop(_box).resize((op_size, op_size)).save(save_sar_png_img_path, 'PNG', quality=True)

In order to keep API in a state in which dividing images is easy, we created API using “flask”.  With “flask”, it provides puzzle division information at the “get query” to divide images.

cd image_processing
make devrun

With just SAR images, it is impossible to complete the puzzle so as a reference, and to confirm on the optical images, we obtained such images as well.

# _req_url='https://gisapi.opf-dev.jp/true/9/449/202.png'
_req_url = '%s/%s/%d/%d/%d.png' % (img_url, map_kinds[map_kind], z, x, y)
_res = requests.get(_req_url, stream=True)
_img = Image.open(BytesIO(_res.content))

*As of February 21, 2019, this API is yet unpublished.  Please wait for the official announcement.

For the viewpoint of being easy to look at and fun, I retrieved images of Biwako, Tokyo and Sadogashima.  Each parameter are as follows.

kind Image format
z Zoom value (the bigger the value, it zooms in)
x Value of X axis on the map
y Value of Y axis on the map
split_n Split number (it is the split number of the puzzle; if the number is 3, it means 3 x 3 and splits in 9 pieces)

 

Biwako

curl http://localhost:5000?z=9&x=449&y=202&kind=true&split_n=3
curl http://localhost:5000?z=9&x=449&y=202&kind=true&split_n=4
curl http://localhost:5000?z=9&x=449&y=202&kind=true&split_n=5

Tokyo

curl http://localhost:5000?z=10&x=909&y=403&kind=true&split_n=3
curl http://localhost:5000?z=10&x=909&y=403&kind=true&split_n=4
curl http://localhost:5000?z=10&x=909&y=403&kind=true&split_n=5

Sadogashima

curl http://localhost:5000?z=8&x=226&y=98&kind=true&split_n=3
curl http://localhost:5000?z=8&x=226&y=98&kind=true&split_n=4
curl http://localhost:5000?z=8&x=226&y=98&kind=true&split_n=5

As we needed a tether with the ”front” we used API which you can call from “nuxt”, instead of doing as a batch in the first place.  We also made it configurable that manage image position information which are obtained by “json” and send their parameter to API.

3.2 Image Coding

We wrote up the construction of the entire screen like this.

src
├ components(components constructing the screen)
│ ├ puzzle
│ │ └ Puzzle.vue(puzzle screen)
│ └ Result.vue(result modal to show on completed puzzle screen )

├ layouts
│ ├ default.vue(common templates? )
│ └ error.vue(error page)

├ pages(folder that has a screen implementation file)
│ ├ difficulty
│ │ ├ _difficulty
│ │ │ └ map
│ │ │ ├ _map
│ │ │ │ ├ complete.vue(complete view of the puzzle)
│ │ │ │ └ index.vue(puzzle screen)
│ │ │ └ index.vue(screen to choose the map)
│ │ └ index.vue(screen to choose the level of difficulty)
│ └ index.vue(top screen)

├ static
│ └ tile.json(define puzzle tiles)
├ store
│ └ index.js(entry point)
└ puzzle.json(discription on puzzle of each level of difficulty)

We used “@nuxtjs/pwa” to make it PWA.  You can install the library and use it easily by importing “nuxt.config.js”.  “@nuxtjs/pwa” is a single file component (Vue file) and dividing files by component is possible.

As the program will relate closely to the front design, we allowed the operator (or caller) to adjust after confirming the design by implementing all necessary tools after converting them into single component.

We made the mobility of the puzzle images to be easily able to change.

The method would be; write setting file on “json”, and then made the mobility of the image change, by calling python’s API as a request parameter of “get”.

By doing so, it makes it possible to obtain images from Tellus and easily change puzzle images by reverting only to ”json” files.

{
  "puzzles": [
    {
      "id": "lake-biwako",
      "name": "Biwa lake",
      "description": "Japan's largest Lake",
      "sar": [1000, 7800, 23000, 33000],
      "parameters": [
        {
          "kind": "true",
          "z": 9,
          "x": 449,
          "y": 202,
          "split_n": 3
        },
        {
          "kind": "true",
          "z": 9,
          "x": 449,
          "y": 202,
          "split_n": 4
        },
        {
          "kind": "true",
          "z": 9,
          "x": 449,
          "y": 202,
          "split_n": 5
        }
      ]
    },
    {
      "id": "city-tokyo",
      "name": "Tokyo",
      "description": "World-top class Metropolis",
      "parameters": [
        {
          "kind": "true",
          "z": 10,
          "x": 909,
          "y": 403,
          "split_n": 3
        },
        {
          "kind": "true",
          "z": 10,
          "x": 909,
          "y": 403,
          "split_n": 4
        },
        {
          "kind": "true",
          "z": 10,
          "x": 909,
          "y": 403,
          "split_n": 5
        }
      ]
    },
    {
      "id": "island-sado",
      "name": "Sadoga-shima",
      "description": "Island of Gold and Silver",
      "parameters": [
        {
          "kind": "true",
          "z": 8,
          "x": 226,
          "y": 98,
          "split_n": 3
        },
        {
          "kind": "true",
          "z": 8,
          "x": 226,
          "y": 98,
          "split_n": 4
        },
        {
          "kind": "true",
          "z": 8,
          "x": 226,
          "y": 98,
          "split_n": 5
        }
      ]
    }
  ]
}

We tried to compose SAR images similar to this but as there were several changes in specification, it is now in the state of hard-coding.

Also unlike optical images, SAR images are distributed with an extension of “tif”, so it needs to be converted into PNG and resized as big as an optical image, and this process has been implemented.

_img.point(lambda i:i*(1./256)).convert('L').crop(_box).resize((op_size, op_size)).save(save_sar_png_img_path, 'PNG', quality=True)

3.3 The puzzle logic

If it is too difficult to solve, no one would enjoy it, so we prepared three types of puzzles; 3×3, 4×4, and 5×5. If we make it too difficult, it will take forever to solve, so we embedded some clues to shed light for players. If they click the button saying “show complete image”, they can see the goal, the completed shape of the puzzle.

(4) The result

So, this is what we completed.  We made it quite difficult to solve so good luck and enjoy!
https://satellite-puzzle.app.tellusxdp.com