View Source Evision Quick Start

This document is a cheatsheet on how to use evision.

Read & Write An Image

Read An Image

Evision.imread

# Read an image
iex> img = Evision.imread("image.png")
%Evision.Mat{
  channels: 3,
  dims: 2,
  type: {:u, 8},
  raw_type: 16,
  shape: {1080, 1920, 3},
  ref: #Reference<0.664400266.3733323795.187022>
}

# Read and get the number of channels
iex> %Evision.Mat{channels: c} = img = Evision.imread("image.png")
iex> c
3

Read a color image as a grayscale one

Evision.imread with flags

iex> img = Evision.imread("image.png", flags: Evision.Constant.cv_IMREAD_GRAYSCALE())
%Evision.Mat{
  channels: 1,
  dims: 2,
  type: {:u, 8},
  raw_type: 0,
  shape: {1080, 1920},
  ref: #Reference<0.664400266.3733323795.187022>
}

Read a PNG image that has an alpha channel

Evision.imread with flags

iex> img = Evision.imread("image.png", flags: Evision.Constant.cv_IMREAD_UNCHANGED())
%Evision.Mat{
  channels: 4,
  dims: 2,
  type: {:u, 8},
  raw_type: 24,
  shape: {1080, 1920, 4},
  ref: #Reference<0.664400266.3733323795.187022>
}

Write An Image

Evision.imwrite

The file extension decides the image encoder of the output image.

# as PNG
Evision.imwrite("filename.png", image)

# as JPEG
Evision.imwrite("filename.jpeg", image)

Access A Sub-region/matrix

Get A Sub-area of An Image

iex> img = Evision.imread("image.png")
%Evision.Mat{
  channels: 3,
  dims: 2,
  type: {:u, 8},
  raw_type: 16,
  shape: {1080, 1920, 3},
  ref: #Reference<0.664400266.3733323795.187022>
}

# Note that Elixir Range is inclusive, 0..1 gives [0, 1]
iex> img[[0..100, 0..100]]
%Evision.Mat{
  channels: 3,
  dims: 2,
  type: {:u, 8},
  raw_type: 16,
  shape: {101, 101, 3},
  ref: #Reference<0.664400266.3733323795.187023>
}

Extract One Channel of An Image

iex> img = Evision.imread("image.png")
%Evision.Mat{
  channels: 3,
  dims: 2,
  type: {:u, 8},
  raw_type: 16,
  shape: {1080, 1920, 3},
  ref: #Reference<0.664400266.3733323795.187022>
}

# by default OpenCV uses BGR format, therefore
# the following code will extract the red-channel
iex> img[[:all, :all, 2]]
%Evision.Mat{
  channels: 1,
  dims: 2,
  type: {:u, 8},
  raw_type: 0,
  shape: {1080, 1920},
  ref: #Reference<0.664400266.3733323795.187023>
}

Extract An Abritray Continuous Sub-matrix

iex> img = Evision.imread("image.png")
%Evision.Mat{
  channels: 3,
  dims: 2,
  type: {:u, 8},
  raw_type: 16,
  shape: {1080, 1920, 3},
  ref: #Reference<0.664400266.3733323795.187022>
}

# as of now, the step size has to be 1
iex> img[[100..200, 10..50, 0..1]]
%Evision.Mat{
  channels: 2,
  dims: 2,
  type: {:u, 8},
  raw_type: 8,
  shape: {101, 41, 2},
  ref: #Reference<0.664400266.3733323795.187024>
}

Interact with Nx.Tensor

Convert to Nx.Tensor

iex> img = Evision.imread("image.png")
%Evision.Mat{
  channels: 3,
  dims: 2,
  type: {:u, 8},
  raw_type: 16,
  shape: {1080, 1920, 3},
  ref: #Reference<0.664400266.3733323795.187022>
}

iex> t = Evision.Mat.to_nx(img)
#Nx.Tensor<
  u8[1080][1920][3]
  Evision.Backend
  [
    [
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, 0],
      [128, 128, ...],
      ...
    ],
    ...
  ]
>

It works the same for any Evision.Mat.

iex> mat = Evision.Mat.ones({2, 3, 4, 5}, :u8)
%Evision.Mat{
  channels: 1,
  dims: 4,
  type: {:u, 8},
  raw_type: 0,
  shape: {2, 3, 4, 5},
  ref: #Reference<0.2233780127.1059454995.175627>
}
iex> t = Evision.Mat.to_nx(mat)
#Nx.Tensor<
  u8[2][3][4][5]
  Evision.Backend
  [
    [
      [
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1]
      ],
      [
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1]
      ],
      [
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        ...
      ]
    ],
    ...
  ]
>

Convert From Nx.Tensor

From abritray Nx.Tensor.

iex> t = Nx.iota({3, 5, 7}, type: :u8)
iex> Evision.Mat.from_nx(t)
%Evision.Mat{
  channels: 1,
  dims: 4,
  type: {:u, 8},
  raw_type: 0,
  shape: {2, 3, 4, 5},
  ref: #Reference<0.2233780127.1059454995.175631>
}

However, please note that type :s64, :u32 and :u64 are not supported by OpenCV.

Another thing to note is that, some OpenCV functions expect the input to be a "valid 2D image", in such cases, Evision.Mat.from_nx_2d/1 should be used instead. Please see the cheat below.

iex> image_tensor = Nx.broadcast(Nx.tensor(0, type: :u8), {720, 1280, 3})
iex> Evision.Mat.from_nx_2d(image_tensor)
%Evision.Mat{
  channels: 3,
  dims: 2,
  type: {:u, 8},
  raw_type: 16,
  shape: {720, 1280, 3},
  ref: #Reference<0.2233780127.1059454995.175632>
}

# compare the results
# note the differences in `channels`, `dims` and `raw_type`
iex> Evision.Mat.from_nx(image_tensor)
%Evision.Mat{
  channels: 1,
  dims: 3,
  type: {:u, 8},
  raw_type: 0,
  shape: {720, 1280, 3},
  ref: #Reference<0.2233780127.1059454995.175633>
}