View Source Evision.DNN Example - Benchmark using Densenet121

# set `EVISION_PREFER_PRECOMPILED` to `false` 
# if you prefer `:evision` to be compiled from source
# note that to compile from source, you may need at least 1GB RAM
# System.put_env("EVISION_PREFER_PRECOMPILED", "false")

Mix.install([
  {:evision, "~> 0.1.21"},
  {:kino, "~> 0.7"},
  {:req, "~> 0.3"}
])

define-some-helper-functions

Define Some Helper Functions

defmodule Helper do
  def download!(url, save_as, overwrite? \\ false) do
    unless File.exists?(save_as) do
      Req.get!(url, http_errors: :raise, output: save_as, cache: not overwrite?)
    end

    :ok
  end
end

write-the-benchmark-module

Write the Benchmark Module

alias Evision, as: Cv

defmodule DetectionModel do
  def benchmark(times, mat, model, out_names, opts \\ []) do
    mean = opts[:mean] || [0, 0, 0]
    scalefactor = opts[:scalefactor] || 1.0

    for _ <- 1..times, reduce: {[], []} do
      {forward_only, all} ->
        start_time_1 = :os.system_time(:millisecond)
        blob = Cv.DNN.blobFromImage(mat, opts)
        model = Cv.DNN.Net.setInput(model, blob, name: "", scalefactor: scalefactor, mean: mean)

        start_time_2 = :os.system_time(:millisecond)
        _detections = Cv.DNN.Net.forward(model, outBlobNames: out_names)
        end_time = :os.system_time(:millisecond)

        inference_time_1 = end_time - start_time_1
        inference_time_2 = end_time - start_time_2
        IO.puts("Inference time=>#{inference_time_2} ms")
        {[inference_time_2 | forward_only], [inference_time_1 | all]}
    end
  end

  def get_model(filename) do
    net = Cv.DNN.readNetFromONNX(filename)
    out_names = Cv.DNN.Net.getUnconnectedOutLayersNames(net)
    {:ok, net, out_names}
  end
end

write-the-densenet121-module

Write the DenseNet121 Module

defmodule DenseNet121 do
  defp download_model(opset_version) when opset_version in [3, 6, 7, 8, 9, 12] do
    onnx_filename = "densenet-#{opset_version}.onnx"
    test_filename = "CyprusShorthair.jpg"

    Helper.download!(
      "https://github.com/onnx/models/raw/main/vision/classification/densenet-121/model/densenet-#{opset_version}.onnx",
      onnx_filename
    )

    Helper.download!(
      "https://upload.wikimedia.org/wikipedia/commons/b/b9/CyprusShorthair.jpg",
      "CyprusShorthair.jpg"
    )

    {onnx_filename, test_filename}
  end

  def get_detection_model(opset_version \\ 12) do
    {onnx_filename, test_filename} = download_model(opset_version)
    {:ok, net, out_names} = DetectionModel.get_model(onnx_filename)
    test_mat = Cv.imread(test_filename)
    {net, out_names, test_mat}
  end

  def benchmark(times, opset_version \\ 12) do
    {net, out_names, test_mat} = get_detection_model(opset_version)

    DetectionModel.benchmark(times, test_mat, net, out_names,
      scalefactor: 1,
      swapRB: true,
      mean: {128, 128, 128},
      size: {224, 224}
    )
  end
end

load-and-run

Load and Run

{forward_only, all} = DenseNet121.benchmark(50)
avg_forward_only = Enum.sum(forward_only) / Enum.count(forward_only)
avg_all = Enum.sum(all) / Enum.count(all)
{avg_forward_only, avg_all}