Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

NDVI Server A

ndvi_server_a.livemd

NDVI Server A

Mix.install(
  [
    {:nx, "~> 0.9"},
    {:evision, "~> 0.2"},
    {:exla, "~> 0.9"},
    {:kino, "~> 0.14"}
  ],
  config: [nx: [default_backend: EXLA.Backend]]
)

NDVI Service

defmodule NDVIService do
  import Nx.Defn

  defn calc(input) do
    red_tensor = input[0][[0..-1//1, 0..-1//1, 0]]
    nir_tensor = input[0][[0..-1//1, 0..-1//1, 1]]

    Nx.select(
      # 0 除算をしないため、 NIR と Red の両方が 0 でないところだけ演算する
      (red_tensor != 0) * (nir_tensor != 0),
      # NDVI の演算
      (nir_tensor - red_tensor) / (nir_tensor + red_tensor),
      0
    )
    |> then(fn tensor -> tensor * 128 + 128 end)
    |> Nx.as_type(:u8)
    |> Nx.new_axis(0)
  end
end
frame = Kino.Frame.new()
serving =
  Nx.Serving.new(fn opts -> Nx.Defn.jit(&NDVIService.calc/1, opts) end, compiler: EXLA)
  |> Nx.Serving.client_preprocessing(fn input ->
    batch = Nx.Batch.stack([input])
    {batch, :client_info}
  end)
  |> Nx.Serving.client_postprocessing(fn {output, _metadata}, _multi? ->
    res = output[0]

    res
    |> Evision.Mat.from_nx_2d()
    |> Evision.resize({320, 320})
    |> then(&[src: &1, colormap: Evision.Constant.cv_COLORMAP_WINTER()])
    |> Evision.applyColorMap()
    |> then(&Kino.Frame.render(frame, &1))

    res
  end)
  |> Nx.Serving.distributed_postprocessing(fn output ->
    Nx.backend_copy(output, Nx.BinaryBackend)
  end)
Kino.start_child({Nx.Serving, name: NDVIServer, serving: serving})
{node(), Node.get_cookie()}