Object Detection: YOLOv4
File.cd!(__DIR__)
# for windows JP
# System.shell("chcp 65001")
Mix.install(
[
{:axon_interp, "~> 0.1.0"},
{:cimg, "~> 0.1.14"},
{:postdnn, "~> 0.1.5"},
{:kino, "~> 0.7.0"}
],
config: [
nx: [default_defn_options: [compiler: EXLA]]
]
# system_env: [{"NNINTERP", "Axon"}]
)
0.Original work
Pytorch-YOLOv4
This note usee the pretraind model converted from above project ;-)
Thanks a lot!!!
Implementation with AxonInterp in Elixir
1.Defining the inference module: YOLOv4
-
Model
yolov4_1_3_608_608_static.onnx -
Pre-processing
Resize the input image to the size {608,608}, normalize to {0.0,1.0} and transpose NCHW. -
Post-processing
Filtering Boxes(output[0]) and Scores(output[1]) with Multi-class Non Maximum Suppression.
defmodule YOLOv4 do
@moduledoc """
Original work:
Pytorch-YOLOv4 - https://github.com/Tianxiaomo/pytorch-YOLOv4
"""
use AxonInterp,
model: "./model/yolov4_1_3_608_608_static.onnx",
url:
"https://github.com/shoz-f/axon_interp/releases/download/0.0.1/yolov4_1_3_608_608_static.onnx",
inputs: [f32: {1, 3, 608, 608}],
outputs: [f32: {1, 22743, 1, 4}, f32: {1, 22743, 80}]
@prepro CImg.builder()
|> CImg.resize({608, 608})
|> CImg.to_binary([{:range, {0.0, 1.0}}, :nchw])
def apply(img) do
# preprocess
input0 = CImg.run(@prepro, img)
# prediction
outputs =
session()
|> AxonInterp.set_input_tensor(0, input0, [:binary])
|> AxonInterp.invoke()
# postprocess
boxes = AxonInterp.get_output_tensor(outputs, 0, [:binary])
scores = AxonInterp.get_output_tensor(outputs, 1, [:binary])
PostDNN.non_max_suppression_multi_class(
{22743, 80},
boxes,
scores,
boxrepr: :corner,
label: "./model/coco.label"
)
end
end
Launch YOLOv4
.
# AxonInterp.stop(Resnet18)
YOLOv4.start_link([])
Display the properties of the YOLOv4
model.
AxonInterp.info(YOLOv4)
2.Defining execution module LiveYOLOv4
defmodule LiveYOLOv4 do
@palette CImg.Util.rand_palette("./model/coco.label")
def run(path) do
img = CImg.load(path)
with {:ok, res} <- YOLOv4.apply(img) do
IO.inspect(res)
Enum.reduce(res, CImg.builder(img), &draw_item(&1, &2))
|> CImg.display_kino(:jpeg)
end
end
defp draw_item({name, boxes}, canvas) do
color = @palette[name]
Enum.reduce(boxes, canvas, fn [_score, x1, y1, x2, y2, _index], canvas ->
[x1, y1, x2, y2] = PostDNN.clamp([x1, y1, x2, y2], {0.0, 1.0})
CImg.fill_rect(canvas, x1, y1, x2, y2, color, 0.35)
end)
end
end
3.Let’s try it
LiveYOLOv4.run("dog.jpg")
Appendix
□