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()}