View Source Find and Draw Contours in an Image
# 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.22"},
{:kino, "~> 0.7"},
{:req, "~> 0.3"}
])
:ok
helper-function
Helper Function
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
{:module, Helper, <<70, 79, 82, 49, 0, 0, 10, ...>>, {:download!, 3}}
Helper.download!("https://docs.opencv.org/4.x/pca_test1.jpg", "pca_test.jpg")
:ok
load-image-as-gray-scale
Load Image As Gray Scale
gray = Evision.imread("pca_test.jpg", flags: Evision.cv_IMREAD_GRAYSCALE())
%Evision.Mat{
channels: 1,
dims: 2,
type: {:u, 8},
raw_type: 0,
shape: {600, 800},
ref: #Reference<0.2172638371.2268463131.71223>
}
get-a-binary-image
Get A Binary Image
# import Bitwise so that we can use `|||` (bitwise or)
import Bitwise
# binarization
{_, bw} =
Evision.threshold(gray, 50, 255, Evision.cv_THRESH_BINARY() ||| Evision.cv_THRESH_OTSU())
bw
%Evision.Mat{
channels: 1,
dims: 2,
type: {:u, 8},
raw_type: 0,
shape: {600, 800},
ref: #Reference<0.2172638371.2268463122.70922>
}
find-all-contours-in-the-binary-image
Find All Contours in the Binary Image
# Find all the contours in the thresholded image
{contours, _} = Evision.findContours(bw, Evision.cv_RETR_LIST(), Evision.cv_CHAIN_APPROX_NONE())
IO.puts("Find #{Enum.count(contours)} contour(s)")
Find 7 contour(s)
:ok
ignore-contours-that-are-too-small-or-too-large
Ignore Contours That Are Too Small or Too Large
minimal_area = 100
maximal_area = 100_000
contours =
Enum.reject(contours, fn c ->
# Calculate the area of each contour
area = Evision.contourArea(c)
# Ignore contours that are too small or too large
# (return true to reject)
area < minimal_area or area > maximal_area
end)
IO.puts("#{Enum.count(contours)} contour(s) remains")
6 contour(s) remains
:ok
draw-all-contours
Draw All Contours
# color in {Blue, Green, Red}, range from 0-255
edge_color = {0, 0, 255}
# draw all contours by setting `index` to `-1`
index = -1
# Load image in color
src = Evision.imread("pca_test.jpg")
# draw all contours on the color image
Evision.drawContours(src, contours, index, edge_color, thickness: 2)
%Evision.Mat{
channels: 3,
dims: 2,
type: {:u, 8},
raw_type: 16,
shape: {600, 800, 3},
ref: #Reference<0.2172638371.2268463122.70944>
}