Face Alignment: 2D106det
File.cd!(__DIR__)
# for windows JP
System.shell("chcp 65001")
Mix.install([
{:onnx_interp, path: ".."},
{:cimg, "~> 0.1.17"},
{:nx, "~> 0.4.1"},
{:kino, "~> 0.8.0"}
])
0.Original work
-
InsightFace: Face Alignment
https://github.com/deepinsight/insightface/tree/master/alignment/coordinate_reg
1.Implementation with OnnxInterp in Elixir
defmodule FaceAlign do
@width 192
@height 192
alias OnnxInterp, as: NNInterp
use NNInterp,
model: "model/2d106det.onnx",
inputs: [f32: {1, 3, @height, @width}],
outputs: [f32: {1, 212}]
def apply(img) do
# preprocess
input0 =
img
|> CImg.resize({@width, @height})
|> CImg.to_binary([{:range, {0.0, 255.0}}, :nchw])
# prediction
output0 =
session()
|> NNInterp.set_input_tensor(0, input0)
|> NNInterp.invoke()
|> NNInterp.get_output_tensor(0)
|> Nx.from_binary(:f32)
|> Nx.reshape({:auto, 2})
# postprocess
landmark =
output0
|> Nx.add(Nx.tensor([1.0, 1.0]))
|> Nx.divide(2.0)
|> Nx.to_flat_list()
|> Enum.chunk_every(2)
{:ok, landmark}
end
end
Launch FaceAlign
.
FaceAlign.start_link([])
2.Let’s try it
defmodule DemoFaceAlign do
def run(path) do
img = CImg.load(path)
[
img,
with {:ok, res} = FaceAlign.apply(img) do
draw_item(res, CImg.builder(img), :red)
end
]
end
defp draw_item(landmark, canvas, color) do
Enum.reduce(landmark, canvas, fn [x, y], canvas ->
CImg.draw_marker(canvas, x, y, color, size: 2)
end)
end
end
DemoFaceAlign.run("face.jpg")
|> Enum.map(&CImg.display_kino(&1, :jpeg))
|> Kino.Layout.grid(columns: 2)
3.TIL ;-)
Appendix
□