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>
}