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

YOLO benchmark

livebooks/ortex/yolo_benchmark.livemd

YOLO benchmark

Mix.install([
  {:yolo, ">= 0.0.0"},
  {:yolo_fast_nms, "~> 0.1"},
  {:exla, "~> 0.9"},
  {:emlx, github: "elixir-nx/emlx"},
  {:evision, "~> 0.2"},
  {:kino_benchee, "~> 0.1"}
])

Use YOLOv8x

v8x_onnx_input = Kino.Input.file("YOLOv8x ONNX")
v8x_classes_json_input = Kino.Input.file("YOLOv8x CLASSES JSON")

Kino.Layout.grid([v8x_onnx_input, v8x_classes_json_input], columns: 2)
v8x_model = YOLO.load([
  model_path: v8x_onnx_input |> Kino.Input.read() |> Map.get(:file_ref) |> Kino.Input.file_path(), 
  classes_path: v8x_classes_json_input |> Kino.Input.read() |> Map.get(:file_ref) |> Kino.Input.file_path()
])
image_input = Kino.Input.image("IMAGE", format: :png)
mat =
  image_input
  |> Kino.Input.read()
  |> Map.get(:file_ref)
  |> Kino.Input.file_path()
  |> File.read!()
  |> Evision.imdecode(Evision.Constant.cv_IMREAD_COLOR())
objects =
  v8x_model
  |> YOLO.detect(mat, nms_fun: &YoloFastNMS.run/3)
  |> YOLO.to_detected_objects(v8x_model.classes)
draw_objects = fn mat, objects ->
  objects
  |> Enum.reduce(mat, fn %{class: class, prob: prob, bbox: bbox, class_idx: class_idx}, drawed_mat ->
    %{w: w, h: h, cx: cx, cy: cy} = bbox
    left = cx - div(w, 2)
    top = cy - div(h, 2)
    right = left + w
    bottom = top + h
  
    score = round(prob * 100) |> Integer.to_string()
  
    color = {
      case rem(class_idx, 3) do
        0 -> 0
        1 -> 128
        2 -> 255
      end,
      case rem(80 - class_idx, 4) do
        0 -> 0
        1 -> 30
        2 -> 60
        3 -> 90
      end,
      case rem(40 + class_idx, 5) do
        0 -> 255
        1 -> 196
        2 -> 128
        3 -> 64
        4 -> 0
      end
    }
  
    text = class <> ":" <> score
    font = Evision.Constant.cv_FONT_HERSHEY_SIMPLEX()
    font_scale = 1
    font_thickness = 2
    {{tw, th}, _} = Evision.getTextSize(text, font, font_scale, font_thickness)
  
    drawed_mat
    |> Evision.rectangle(
      {left, top},
      {right, bottom},
      color,
      thickness: 10
    )
    |> Evision.rectangle(
      {left - 5, top - th - 10},
      {left + tw + 5, top},
      color,
      thickness: -1
    )
    |> Evision.putText(
      text,
      {left, top - 5},
      font,
      font_scale,
      {255, 255, 255},
      thickness: font_thickness
    )
  end)
end
draw_objects.(mat, objects)
defmodule MyBenchmark do
  def detect(model, mat) do
    model
    |> YOLO.detect(mat, nms_fun: &amp;YoloFastNMS.run/3)
    |> YOLO.to_detected_objects(model.classes)
  end

  def run(model, mat) do
    Benchee.run(
      %{
        "binary" => fn ->
          Nx.default_backend(Nx.BinaryBackend)
          detect(model, mat)
        end,
        "exla" => fn ->
          Nx.default_backend(EXLA.Backend)
          detect(model, mat)
        end,
        "emlx" => fn ->
          Nx.default_backend(EMLX.Backend)
          detect(model, mat)
        end
      },
      memory_time: 2,
      reduction_time: 2
    )
  end
end
MyBenchmark.run(v8x_model, mat)