Image Processing in OpenCV-Emgu
Transcript of Image Processing in OpenCV-Emgu
1
Image Processing in OpenCV-Emgu (2)
Wen-Chang Cheng
CYUT-CSIE
2019/10/29
2
Contents
1. Morphological Transformations ........................................ 4
1-1. Goal ............................................................................................................ 4
1-2. Theory ........................................................................................................ 4
(1). Erosion ..................................................................................................... 4
(2). Dilation..................................................................................................... 7
(3). Opening ................................................................................................... 9
(4). Closing.................................................................................................... 11
(5). Morphological Gradient......................................................................... 12
(6). Top Hat ................................................................................................... 12
(7). Black Hat ................................................................................................ 12
1-3. Structuring Element ................................................................................. 13
1-4. Additional Resources ............................................................................... 15
1-5. Exercises ................................................................................................... 15
2. Image Gradients .............................................................. 16
2-1. Goal ............................................................................................................... 16
2-2. Theory ........................................................................................................... 16
(1). Sobel and Scharr Derivatives ................................................................. 16
(2). Laplacian Derivatives ............................................................................. 20
2-3. One Important Matter! ................................................................................. 22
2-4. Additional Resources .................................................................................... 23
2-5. Exercises ........................................................................................................ 23
3. Canny Edge Detection ..................................................... 24
3-1. Goal ............................................................................................................... 24
3-2. Theory ........................................................................................................... 24
3-3. Canny Edge Detection in OpenCV ................................................................. 26
3-4. Additional Resources .................................................................................... 28
3-5. Exercises ........................................................................................................ 28
4. Contours in OpenCV: Getting Started ............................... 29
4-1. Goal ............................................................................................................... 29
4-2. What are contours? ...................................................................................... 29
5-3. How to draw the contours? .......................................................................... 33
5-4. Contour Approximation Method .................................................................. 35
3
5-5. Additional Resources .................................................................................... 36
5-6. Exercises ........................................................................................................ 36
5. Contours in OpenCV: Contour Features ............................ 37
5-1. Goal ............................................................................................................... 37
5-2. Moments ....................................................................................................... 37
5-3. Contour Area ................................................................................................. 38
5-4. Contour Perimeter ........................................................................................ 39
5-5. Contour Approximation ................................................................................ 40
5-6. Bounding Rectangle ...................................................................................... 41
(1) Straight Bounding Rectangle .................................................................. 41
(2) Rotated Rectangle ................................................................................... 42
5-7. Minimum Enclosing Circle ............................................................................ 44
5-8. Fitting an Ellipse ............................................................................................ 44
5-9. Fitting a Line .................................................................................................. 46
5-10. Additional Resources .................................................................................. 47
5-11. Exercises ...................................................................................................... 47
4
1. Morphological Transformations
1-1. Goal
In this chapter,
We will learn different morphological operations like Erosion,
Dilation, Opening, Closing etc.
We will see different functions like : Cvinvoke.erode(),
Cvinvoke.dilate(), Cvinvoke.morphologyEx() etc.
1-2. Theory
Morphological transformations are some simple operations based on the image
shape. It is normally performed on binary images. It needs two inputs, one is
our original image, second one is called structuring element or kernel which
decides the nature of operation. Two basic morphological operators are Erosion
and Dilation. Then its variant forms like Opening, Closing, Gradient etc also
comes into play. We will see them one-by-one with help of following image:
(形態變換是基於圖像形狀的一些簡單操作。通常在二元圖像上執行。它需要兩
個輸入,一個是原始圖像,第二個是決定操作性質的結構元素或內核。兩種基本
的形態學算子是侵蝕和膨脹。然後它的變體形式(如“打開”、“關閉”、“漸
變”等)也開始起作用。在下圖的幫助下,我們將一一看到它們:)
(1). Erosion
The basic idea of erosion is just like soil erosion only, it erodes away the
boundaries of foreground object (Always try to keep foreground in white). So
5
what does it do? The kernel slides through the image (as in 2D convolution). A
pixel in the original image (either 1 or 0) will be considered 1 only if all the pixels
under the kernel is 1, otherwise it is eroded (made to zero).
(侵蝕的基本思想就像僅是土壤侵蝕一樣,它侵蝕了前景物體的邊界(使前景保持
白色)。那怎麼辦呢?內核在圖像中滑動(如 2D 卷積)。僅當內核下的所有像素
均為 1 時,原始圖像中的像素(1 或 0)才被視為 1,否則它將被侵蝕(設為零)。)
So what happends is that, all the pixels near boundary will be discarded
depending upon the size of kernel. So the thickness or size of the foreground
object decreases or simply white region decreases in the image. It is useful for
removing small white noises (as we have seen in colorspace chapter), detach
two connected objects etc.
(因此發生的是,將根據內核的大小丟棄邊界附近的所有像素。因此,前景對象的
厚度或大小會減小,或者圖像中的白色區域會減小。這對於消除小的白噪聲(如
我們在色彩空間一章中看到的),分離兩個連接的物體等非常有用。)
Here, as an example, I would use a 5x5 kernel with full of ones. Let’s see it how
it works:
Result:
1 1 1
1 1 1
1 1 1
0 0 0 0 0 0
0 1 1 1 1 0
0 1 1 1 1 0
0 1 1 1 1 0
0 1 1 1 1 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 1 0 0
0 0 1 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0
6
CvInvoke.Erode Method
http://www.emgu.com
Erodes the source image using the specified structuring element that determines
the shape of a pixel neighborhood over which the minimum is taken:
dst=erode(src,element): dst(x,y)=min((x', y') in element)) src(x+x', y+y') The
function supports the in-place mode. Erosion can be applied several (iterations)
times. In case of color image each channel is processed independently.
Namespace: Emgu.CV
Assembly: Emgu.CV (in Emgu.CV.dll) Version: 3.0.0.2161
public static void Erode(
IInputArray src,
IOutputArray dst,
IInputArray element,
Point anchor,
int iterations,
BorderType borderType,
MCvScalar borderValue
)
Parameters
src
Type: Emgu.CV.IInputArray
Source image.
dst
Type: Emgu.CV.IOutputArray
Destination image
element
Type: Emgu.CV.IInputArray
Structuring element used for erosion.
anchor
Type: System.Drawing.Point
Position of the anchor within the element; default value (-1, -1) means
that the anchor is at the element center.
7
iterations
Type: System.Int32
Number of times erosion is applied.
borderType
Type: Emgu.CV.CvEnum.BorderType
Pixel extrapolation method
borderValue
Type: Emgu.CV.Structure.MCvScalar
Border value in case of a constant border, use Constant for default
(2). Dilation
It is just opposite of erosion. Here, a pixel element is ‘1’ if at least one pixel
under the kernel is ‘1’. So it increases the white region in the image or size of
foreground object increases. Normally, in cases like noise removal, erosion is
followed by dilation. Because, erosion removes white noises, but it also shrinks
our object. So we dilate it. Since noise is gone, they won’t come back, but our
object area increases. It is also useful in joining broken parts of an object.
(它與侵蝕正好相反,如果內核下至少一個像素為“1”,則像素元素為“1”。
因此,它會增加圖像中的白色區域或增加前景對象的大小。通常,在消除噪音的
情況下,腐蝕後會膨脹。因為腐蝕會消除白噪聲,但也會縮小物體,因此,我們
對其進行了擴展,由於噪音消失了,它們不會回來,但我們的目標區域增加了。
在連接對象的損壞部分時也很有用。)
CvInvoke.Dilate Method
http://www.emgu.com
Dilates the source image using the specified structuring element that determines
the shape of a pixel neighborhood over which the maximum is taken The function
supports the in-place mode. Dilation can be applied several (iterations) times. In
case of color image each channel is processed independently
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.2.0.2682
8
public static void Dilate(
IInputArray src,
IOutputArray dst,
IInputArray element,
Point anchor,
int iterations,
BorderType borderType,
MCvScalar borderValue
)
Parameters
src
Type: Emgu.CV.IInputArray
Source image
dst
Type: Emgu.CV.IOutputArray
Destination image
element
Type: Emgu.CV.IInputArray
Structuring element used for erosion.
anchor
Type: System.Drawing.Point
Position of the anchor within the element; default value (-1, -1) means
that the anchor is at the element center.
iterations
Type: System.Int32
Number of times erosion is applied
borderType
Type: Emgu.CV.CvEnum.BorderType
Pixel extrapolation method
borderValue
Type: Emgu.CV.Structure.MCvScalar
Border value in case of a constant border
Result:
9
(3). Opening
Opening is just another name of erosion followed by dilation. It is useful in
removing noise, as we explained above. Here we use the function,
Cvinvoke.morphologyEx()
Result:
CvInvoke.MorphologyEx Method
http://www.emgu.com
Performs advanced morphological transformations.
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.3.0.2824
public static void MorphologyEx(
IInputArray src,
IOutputArray dst,
MorphOp operation,
IInputArray kernel,
Point anchor,
10
int iterations,
BorderType borderType,
MCvScalar borderValue
)
Parameters
src
Type: Emgu.CV.IInputArray
Source image.
dst
Type: Emgu.CV.IOutputArray
Destination image.
operation
Type: Emgu.CV.CvEnum.MorphOp
Type of morphological operation.
kernel
Type: Emgu.CV.IInputArray
Structuring element.
anchor
Type: System.Drawing.Point
Anchor position with the kernel. Negative values mean that the anchor is
at the kernel center.
iterations
Type: System.Int32
Number of times erosion and dilation are applied.
borderType
Type: Emgu.CV.CvEnum.BorderType
Pixel extrapolation method.
borderValue
Type: Emgu.CV.Structure.MCvScalar
Border value in case of a constant border.
MorphOp Enumeration
http://www.emgu.com
Morphology operation type
11
Namespace: Emgu.CV.CvEnum
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.3.0.2824
public enum MorphOp
Members
Member name Value Description
Erode 0 Erode
Dilate 1 Dilate
Open 2 Open
Close 3 Close
Gradient 4 Gradient
Tophat 5 Tophat
Blackhat 6 Blackhat
(4). Closing
Closing is reverse of Opening, Dilation followed by Erosion. It is useful in
closing small holes inside the foreground objects, or small black points on the
object.
Result:
12
(5). Morphological Gradient
It is the difference between dilation and erosion of an image. The result will look
like the outline of the object.
Result:
(6). Top Hat
It is the difference between input image and Opening of the image. Below
example is done for a 9x9 kernel.
Result:
(7). Black Hat
It is the difference between the Closing of the input image and input image.
Result:
13
1-3. Structuring Element
We manually created a structuring elements in the previous examples. It is
rectangular shape. But in some cases, you may need elliptical/circular shaped
kernels. So for this purpose, OpenCV has a function,
Cvinvoke.getStructuringElement(). You just pass the shape and size of the
kernel, you get the desired kernel.
CvInvoke.GetStructuringElement Method
http://www.emgu.com
Returns a structuring element of the specified size and shape for morphological
operations.
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.1.0.2282
public static Mat GetStructuringElement(
ElementShape shape,
Size ksize,
Point anchor
)
Parameters
shape
Type: Emgu.CV.CvEnum.ElementShape
Element shape
ksize
Type: System.Drawing.Size
14
Size of the structuring element.
anchor
Type: System.Drawing.Point
Anchor position within the element. The value (-1, -1) means that the
anchor is at the center. Note that only the shape of a cross-shaped
element depends on the anchor position. In other cases the anchor just
regulates how much the result of the morphological operation is shifted.
Return Value
Type: Mat
The structuring element
ElementShape Enumeration
http://www.emgu.com
Shape of the Structuring Element
Namespace: Emgu.CV.CvEnum
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.1.0.2282
public enum ElementShape
Members
Member name Value Description
Rectangle 0 A rectangular element.
Cross 1 A cross-shaped element.
Ellipse 2 An elliptic element.
Custom 100 A user-defined element.
15
1-4. Additional Resources
1. Morphological Operations at HIPR2
1-5. Exercises
16
2. Image Gradients
2-1. Goal
In this chapter, we will learn to:
Find Image gradients, edges etc
We will see following functions : Cvinvoke.Sobel(), Cvinvoke.Scharr(),
Cvinvoke.Laplacian() etc
2-2. Theory
OpenCV provides three types of gradient filters or High-pass filters, Sobel,
Scharr and Laplacian. We will see each one of them.
(1). Sobel and Scharr Derivatives
Sobel operators is a joint Gausssian smoothing plus differentiation operation,
so it is more resistant to noise. You can specify the direction of derivatives to
be taken, vertical or horizontal (by the arguments, yorder and xorder
respectively). You can also specify the size of kernel by the argument ksize . If
ksize = -1 (for python), a 3x3 Scharr filter is used which gives better results than
3x3 Sobel filter. Please see the docs for kernels used.
CvInvoke.Sobel Method
http://www.emgu.com
The Sobel operators combine Gaussian smoothing and differentiation so the
result is more or less robust to the noise. Most often, the function is called with
(xorder=1, yorder=0, aperture_size=3) or (xorder=0, yorder=1, aperture_size=3)
to calculate first x- or y- image derivative. The first case corresponds to
[−1 0 1−2 0 2−1 0 1
]
17
kernel and the second one corresponds to
[−1 −2 −10 0 01 2 1
]
Or
[1 2 10 0 0−1 −2 −1
]
kernel, depending on the image origin (origin field of IplImage structure). No
scaling is done, so the destination image usually has larger by absolute value
numbers than the source image. To avoid overflow, the function requires 16-bit
destination image if the source image is 8-bit. The result can be converted back
to 8-bit using cvConvertScale or cvConvertScaleAbs functions. Besides 8-bit
images the function can process 32-bit floating-point images. Both source and
destination must be single-channel images of equal size or ROI size
Namespace: Emgu.CV
Assembly: Emgu.CV (in Emgu.CV.dll) Version: 3.0.0.2161 (3.0.0.2161)
public static void Sobel(
IInputArray src,
IOutputArray dst,
DepthType ddepth,
int xorder,
int yorder,
int kSize = 3,
double scale = 1,
double delta = 0,
BorderType borderType = BorderType.Reflect101
)
Parameters
src
Type: Emgu.CV.IInputArray
Source image.
dst
Type: Emgu.CV.IOutputArray
18
Destination image
ddepth
Type: Emgu.CV.CvEnum.DepthType
output image depth; the following combinations of src.depth() and
ddepth are supported:
src.depth() = CV_8U, ddepth = -1/CV_16S/CV_32F/CV_64F
src.depth() = CV_16U/CV_16S, ddepth = -1/CV_32F/CV_64F
src.depth() = CV_32F, ddepth = -1/CV_32F/CV_64F
src.depth() = CV_64F, ddepth = -1/CV_64F
when ddepth=-1, the destination image will have the same depth as the
source; in the case of 8-bit input images it will result in truncated
derivatives.
xorder
Type: System.Int32
Order of the derivative x.
yorder
Type: System.Int32
Order of the derivative y.
kSize (Optional)
Type: System.Int32
Size of the extended Sobel kernel, must be 1, 3, 5 or 7.
scale (Optional)
Type: System.Double
Optional scale factor for the computed derivative values.
delta (Optional)
Type: System.Double
Optional delta value that is added to the results prior to storing them in
dst
borderType (Optional)
Type: Emgu.CV.CvEnum.BorderType
Pixel extrapolation method
CvInvoke.Scharr Method
http://www.emgu.com
19
Calculates the first x- or y- image derivative using Scharr operator.
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.4.1.2976
(3.4.1.2976)
public static void Scharr(
IInputArray src,
IOutputArray dst,
DepthType ddepth,
int dx,
int dy,
double scale = 1,
double delta = 0,
BorderType borderType = BorderType.Reflect101
)
Parameters
src
Type: Emgu.CV.IInputArray
input image.
dst
Type: Emgu.CV.IOutputArray
output image of the same size and the same number of channels as src.
ddepth
Type: Emgu.CV.CvEnum.DepthType
output image depth
dx
Type: System.Int32
order of the derivative x.
dy
Type: System.Int32
order of the derivative y.
scale (Optional)
Type: System.Double
optional scale factor for the computed derivative values; by default, no
scaling is applied
delta (Optional)
20
Type: System.Double
optional delta value that is added to the results prior to storing them in
dst.
borderType (Optional)
Type: Emgu.CV.CvEnum.BorderType
pixel extrapolation method
(2). Laplacian Derivatives
It calculates the Laplacian of the image given by the relation,
,
where each derivative is found using Sobel derivatives. If ksize = 1 , then
following kernel is used for filtering:
CvInvoke.Laplacian Method
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.4.1.2976
(3.4.1.2976)
public static void Laplacian(
IInputArray src,
IOutputArray dst,
DepthType ddepth,
int ksize = 1,
double scale = 1,
double delta = 0,
BorderType borderType = BorderType.Reflect101
)
21
Parameters
src
Type: Emgu.CV.IInputArray
Source image.
dst
Type: Emgu.CV.IOutputArray
Destination image. Should have type of float
ddepth
Type: Emgu.CV.CvEnum.DepthType
Desired depth of the destination image.
ksize (Optional)
Type: System.Int32
Aperture size used to compute the second-derivative filters.
scale (Optional)
Type: System.Double
Optional scale factor for the computed Laplacian values. By default, no
scaling is applied.
delta (Optional)
Type: System.Double
Optional delta value that is added to the results prior to storing them in
dst.
borderType (Optional)
Type: Emgu.CV.CvEnum.BorderType
Pixel extrapolation method.
Result:
22
2-3. One Important Matter!
In our last example, output datatype is CV_8U. But there is a slight problem
with that. Black-to-White transition is taken as Positive slope (it has a positive
value) while White-to-Black transition is taken as a Negative slope (It has
negative value). So when you convert data to CV_8U, all negative slopes are
made zero. In simple words, you miss that edge.
If you want to detect both edges, better option is to keep the output datatype to
some higher forms, like CV_16S, CV_64F etc, take its absolute value and then
convert back to CV_8U.
Check the result below:
23
2-4. Additional Resources
2-5. Exercises
24
3. Canny Edge Detection
3-1. Goal
In this chapter, we will learn about
Concept of Canny edge detection
OpenCV functions for that : Cvinvoke.Canny()
3-2. Theory
Canny Edge Detection is a popular edge detection algorithm. It was developed
by John F. Canny in 1986. It is a multi-stage algorithm and we will go through
each stages.
(1). Noise Reduction
Since edge detection is susceptible to noise in the image, first step is to remove
the noise in the image with a 5x5 Gaussian filter. We have already seen this in
previous chapters.
(2). Finding Intensity Gradient of the Image
Smoothened image is then filtered with a Sobel kernel in both horizontal and
vertical direction to get first derivative in horizontal direction ( ) and vertical
direction ( ). From these two images, we can find edge gradient and direction
for each pixel as follows:
Gradient direction is always perpendicular to edges. It is rounded to one of four
angles representing vertical, horizontal and two diagonal directions.
(3). Non-maximum Suppression
25
After getting gradient magnitude and direction, a full scan of image is done to
remove any unwanted pixels which may not constitute the edge. For this, at
every pixel, pixel is checked if it is a local maximum in its neighborhood in the
direction of gradient. Check the image below:
Point A is on the edge ( in vertical direction). Gradient direction is normal to the
edge. Point B and C are in gradient directions. So point A is checked with point
B and C to see if it forms a local maximum. If so, it is considered for next stage,
otherwise, it is suppressed ( put to zero).
In short, the result you get is a binary image with “thin edges”.
(4). Hysteresis Thresholding
This stage decides which are all edges are really edges and which are not. For
this, we need two threshold values, minVal and maxVal. Any edges with
intensity gradient more than maxVal are sure to be edges and those below
minVal are sure to be non-edges, so discarded. Those who lie between these
two thresholds are classified edges or non-edges based on their connectivity.
If they are connected to “sure-edge” pixels, they are considered to be part of
edges. Otherwise, they are also discarded. See the image below:
26
The edge A is above the maxVal, so considered as “sure-edge”. Although edge
C is below maxVal, it is connected to edge A, so that also considered as valid
edge and we get that full curve. But edge B, although it is above minVal and is
in same region as that of edge C, it is not connected to any “sure-edge”, so that
is discarded. So it is very important that we have to select minVal and maxVal
accordingly to get the correct result.
This stage also removes small pixels noises on the assumption that edges are
long lines.
So what we finally get is strong edges in the image.
3-3. Canny Edge Detection in OpenCV
OpenCV puts all the above in single function,Cvinvoke.Canny(). We will see
how to use it. First argument is our input image. Second and third arguments
are our minVal and maxVal respectively. Third argument is aperture_size. It is
the size of Sobel kernel used for find image gradients. By default it is 3. Last
argument is L2gradient which specifies the equation for finding gradient
magnitude. If it is True , it uses the equation mentioned above which is more
accurate, otherwise it uses this function: .
By default, it is False .
See the result below:
27
CvInvoke.Canny Method
http://www.emgu.com
Finds the edges on the input image and marks them in the output image edges
using the Canny algorithm. The smallest of threshold1 and threshold2 is used for
edge linking, the largest - to find initial segments of strong edges.
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.2.0.2682
(3.2.0.2682)
public static void Canny(
IInputArray image,
IOutputArray edges,
double threshold1,
double threshold2,
int apertureSize = 3,
bool l2Gradient = false
)
Parameters
image
Type: Emgu.CV.IInputArray
Input image
edges
Type: Emgu.CV.IOutputArray
Image to store the edges found by the function
threshold1
Type: System.Double
28
The first threshold
threshold2
Type: System.Double
The second threshold.
apertureSize (Optional)
Type: System.Int32
Aperture parameter for Sobel operator
l2Gradient (Optional)
Type: System.Boolean
a flag, indicating whether a more accurate norm should be used to
calculate the image gradient magnitude ( L2gradient=true ), or whether
the default norm is enough ( L2gradient=false ).
3-4. Additional Resources
1. Canny edge detector at Wikipedia
2. Canny Edge Detection Tutorial by Bill Green, 2002.
3-5. Exercises
1. Write a small application to find the Canny edge detection whose threshold
values can be varied using two trackbars. This way, you can understand the
effect of threshold values.
29
4. Contours in OpenCV: Getting Started
4-1. Goal
Understand what contours are.
Learn to find contours, draw contours etc
You will see these functions :CvInvoke.findContours(),
CvInvoke.drawContours().
4-2. What are contours?
Contours can be explained simply as a curve joining all the continuous
points (along the boundary), having same color or intensity. The contours are
a useful tool for shape analysis and object detection and recognition.
(輪廓可以簡單地解釋為連接具有相同顏色或強度的所有連續點(沿邊界)的曲
線。輪廓是用於形狀分析以及對象檢測和識別的有用工具。)
For better accuracy, use binary images. So before finding contours, apply
threshold or canny edge detection.
findContours function modifies the source image. So if you want source
image even after finding contours, already store it to some other variables.
In OpenCV, finding contours is like finding white object from black
background. So remember, object to be found should be white and
background should be black.
CvInvoke.FindContours Method
http://www.emgu.com
Retrieves contours from the binary image and returns the number of retrieved
contours. The pointer firstContour is filled by the function. It will contain pointer
to the first most outer contour or IntPtr.Zero if no contours is detected (if the
image is completely black). Other contours may be reached from firstContour
using h_next and v_next links.
Namespace: Emgu.CV
30
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.2.0.2682
public static void FindContours(
IInputOutputArray image,
IOutputArray contours,
IOutputArray hierarchy,
RetrType mode,
ChainApproxMethod method,
Point offset = null
)
Parameters
image
Type: Emgu.CV.IInputOutputArray
The source 8-bit single channel image. Non-zero pixels are treated as 1s,
zero pixels remain 0s - that is image treated as binary. To get such a binary
image from grayscale, one may use cvThreshold, cvAdaptiveThreshold or
cvCanny. The function modifies the source image content.
contours
Type: Emgu.CV.IOutputArray
Detected contours. Each contour is stored as a vector of points.
hierarchy
Type: Emgu.CV.IOutputArray
Optional output vector, containing information about the image
topology.
mode
Type: Emgu.CV.CvEnum.RetrType
Retrieval mode
method
Type: Emgu.CV.CvEnum.ChainApproxMethod
Approximation method (for all the modes, except CV_RETR_RUNS, which
uses built-in approximation).
offset (Optional)
Type: System.Drawing.Point
Offset, by which every contour point is shifted. This is useful if the
contours are extracted from the image ROI and then they should be
analyzed in the whole image context
31
Return Value
Type:
The number of countours
RetrType Enumeration
http://www.emgu.com
contour retrieval mode
Namespace: Emgu.CV.CvEnum
Assembly: Emgu.CV (in Emgu.CV.dll) Version: 3.0.0.2161
public enum RetrType
Members
Member
name Value Description
External 0 retrieve only the extreme outer contours.
List 1 retrieve all the contours and puts them in the list.
Ccomp 2 retrieve all the contours and organizes them into two-
level hierarchy: top level are external boundaries of
the components, second level are boundaries of the
holes.
Tree 3 retrieve all the contours and reconstructs the full
hierarchy of nested contours.
32
ChainApproxMethod Enumeration
http://www.emgu.com
contour approximation method
Namespace: Emgu.CV.CvEnum
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.1.0.2282
public enum ChainApproxMethod
Members
Member name Value Description
ChainCode 0 output contours in the Freeman chain
code. All other methods output polygons
(sequences of vertices).
ChainApproxNone 1 translate all the points from the chain
code into points;
ChainApproxSimple 2 compress horizontal, vertical, and
diagonal segments, that is, the function
leaves only their ending points;
ChainApproxTc89L1 3
ChainApproxTc89Kcos 4 apply one of the flavors of Teh-Chin chain
approximation algorithm
LinkRuns 5 use completely different contour retrieval
algorithm via linking of horizontal
segments of 1s. Only LIST retrieval mode
can be used with this method
33
Fig 1. An examples of the FreeMan Chain Code
5-3. How to draw the contours?
To draw the contours, CvInvoke.drawContours() function is used. It can
also be used to draw any shape provided you have its boundary points.
CvInvoke.DrawContours Method
http://www.emgu.com
Draws contours outlines or filled contours.
Namespace: Emgu.CV
Assembly: Emgu.CV (in Emgu.CV.dll) Version: 3.0.0.2161
public static void DrawContours(
IInputOutputArray image,
IInputArray contours,
int contourIdx,
MCvScalar color,
int thickness = 1,
LineType lineType = LineType.EightConnected,
IInputArray hierarchy = null,
int maxLevel = 2147483647,
Point offset = null
)
Parameters
image
34
Type: Emgu.CV.IInputOutputArray
Image where the contours are to be drawn. Like in any other drawing
function, the contours are clipped with the ROI.
contours
Type: Emgu.CV.IInputArray
All the input contours. Each contour is stored as a point vector.
contourIdx
Type: System.Int32
Parameter indicating a contour to draw. If it is negative, all the contours
are drawn.
color
Type: Emgu.CV.Structure.MCvScalar
Color of the contours
thickness(Optional)
Type: System.Int32
Thickness of lines the contours are drawn with. If it is negative the contour
interiors are drawn.
lineType(Optional)
Type: Emgu.CV.CvEnum.LineType
Type of the contour segments
hierarchy(Optional)
Type: Emgu.CV.IInputArray
Optional information about hierarchy. It is only needed if you want to
draw only some of the contours.
maxLevel (Optional)
Type: System.Int32
Maximal level for drawn contours. If 0, only contour is drawn. If 1, the
contour and all contours after it on the same level are drawn. If 2, all
contours after and all contours one level below the contours are drawn,
etc. If the value is negative, the function does not draw the contours
following after contour but draws child contours of contour up to
abs(maxLevel)-1 level.
offset(Optional)
Type: System.Drawing.Point
Shift all the point coordinates by the specified value. It is useful in case if
the contours retrieved in some image ROI and then the ROI offset needs
35
to be taken into account during the rendering.
5-4. Contour Approximation Method
This is the third argument in CvInvoke.findContours() function. What does
it denote actually?
Above, we told that contours store the (x, y) coordinates of the boundary
of a shape. But does it store all the coordinates? That is specified by this
contour approximation method.
If you pass ChainApproxNone, all the boundary points are stored. But
actually do we need all the points? For eg, you found the contour of a straight
line. Do you need all the points on the line to represent that line? No, we need
just two end points of that line. This is what ChainApproxSimple does. It
removes all redundant points and compresses the contour, thereby saving
memory.
Below image of a rectangle demonstrate this technique. Just draw a circle
on all the coordinates in the contour array (drawn in blue color). First image
shows points I got with ChainApproxNone (734 points) and second image
shows the one with ChainApproxSimple (only 4 points). See, how much
memory it saves!!!
36
5-5. Additional Resources
5-6. Exercises
37
5. Contours in OpenCV: Contour Features
5-1. Goal
In this article, we will learn
To find the different features of contours, like area, perimeter, centroid,
bounding box etc.
You will see plenty of functions related to contours.
5-2. Moments
Image moments help you to calculate some features like center of mass of
the object, area of the object etc. Check out the wikipedia page on Image
Moments
The function CvInvoke.Moments() gives a dictionary of all moment values
calculated. See below:
CvInvoke.Moments Method
http://www.emgu.com
Calculates spatial and central moments up to the third order and writes them to
moments. The moments may be used then to calculate gravity center of the
shape, its area, main axises and various shape characeteristics including 7 Hu
invariants.
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.2.0.2682
public static MCvMoments Moments(
IInputArray arr,
bool binaryImage = false
)
38
Parameters
arr
Type: Emgu.CV.IInputArray
Image (1-channel or 3-channel with COI set) or polygon (CvSeq of
points or a vector of points)
binaryImage (Optional)
Type: System.Boolean
(For images only) If the flag is true, all the zero pixel values are treated
as zeroes, all the others are treated as 1s.
Return Value
Type: MCvMoments
The moment
From this moments, you can extract useful data like area, centroid etc.
Centroid is given by the relations, and .
5-3. Contour Area
Contour area is given by the function CvInvoke.contourArea() or from
moments, M00.
CvInvoke.ContourArea Method
http://www.emgu.com
Calculates area of the whole contour or contour section.
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.2.0.2682
public static double ContourArea(
IInputArray contour,
39
bool oriented = false
)
Parameters
contour
Type: Emgu.CV.IInputArray
Input vector of 2D points (contour vertices), stored in std::vector or Mat.
Oriented (Optional)
Type: System.Boolean
Oriented area flag. If it is true, the function returns a signed area value,
depending on the contour orientation (clockwise or counter-clockwise).
Using this feature you can determine orientation of a contour by taking
the sign of an area. By default, the parameter is false, which means that
the absolute value is returned.
Return Value
Type: Double
The area of the whole contour or contour section
5-4. Contour Perimeter
It is also called arc length. It can be found out using CvInvoke.arcLength()
function. Second argument specify whether shape is a closed contour (if
passed True), or just a curve.
CvInvoke.ArcLength Method
http://www.emgu.com
Calculates a contour perimeter or a curve length.
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.1.0.2282
public static double ArcLength(
IInputArray curve,
40
bool isClosed
)
Parameters
curve
Type: Emgu.CV.IInputArray
Sequence or array of the curve points
isClosed
Type: System.Boolean
Indicates whether the curve is closed or not.
Return Value
Type: Double
Contour perimeter or a curve length
5-5. Contour Approximation
It approximates a contour shape to another shape with less number of
vertices depending upon the precision we specify. It is an implementation of
Douglas-Peucker algorithm. Check the wikipedia page for algorithm and
demonstration.
To understand this, suppose you are trying to find a square in an image,
but due to some problems in the image, you didn’t get a perfect square, but a
“bad shape” (As shown in first image below). Now you can use this function to
approximate the shape. In this, second argument is called epsilon, which is
maximum distance from contour to approximated contour. It is an accuracy
parameter. A wise selection of epsilon is needed to get the correct output.
Below, in second image, green line shows the approximated curve for
epsilon=0.1*srcLength. Third image shows the same for
epsilon=0.01*srcLength. Third argument specifies whether curve is closed or
not.
41
5-6. Bounding Rectangle
There are two types of bounding rectangles.
(1) Straight Bounding Rectangle
It is a straight rectangle, it doesn’t consider the rotation of the object. So
area of the bounding rectangle won’t be minimum. It is found by the function
CvInvoke.BoundingRectangle().
CvInvoke.BoundingRectangle Method
http://www.emgu.com
Returns the up-right bounding rectangle for 2d point set
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.2.0.2682
public static Rectangle BoundingRectangle(
IInputArray points
)
Parameters
points
Type: Emgu.CV.IInputArray
Input 2D point set, stored in std::vector or Mat.
42
Return Value
Type: Rectangle
The up-right bounding rectangle for 2d point set
(2) Rotated Rectangle
Here, bounding rectangle is drawn with minimum area, so it considers the
rotation also. The function used is CvInvoke.minAreaRect(). It returns a
Box2D structure which contains following detals-( top-left corner(x,y), (width,
height), angle of rotation). But to draw this rectangle, we need 4 corners of the
rectangle. It is obtained by the function CvInvoke.boxPoints()
Both the rectangles are shown in a single image. Green rectangle shows
the normal bounding rect. Red rectangle is the rotated rect.
CvInvoke.MinAreaRect Method (IInputArray)
http://www.emgu.com
Finds a rotated rectangle of the minimum area enclosing the input 2D point set.
Namespace: Emgu.CV
Assembly: Emgu.CV (in Emgu.CV.dll) Version: 3.0.0.2161
43
public static RotatedRect MinAreaRect(
IInputArray points
)
Parameters
points
Type: Emgu.CV.IInputArray
Input vector of 2D points
Return Value
Type: RotatedRect
a circumscribed rectangle of the minimal area for 2D point set
CvInvoke.BoxPoints Method (RotatedRect)
http://www.emgu.com
Calculates vertices of the input 2d box.
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.1.0.2282
public static PointF[] BoxPoints(
RotatedRect box
)
Parameters
box
Type: Emgu.CV.Structure.RotatedRect
The box
Return Value
Type:PointF[]
The four vertices of rectangles.
44
5-7. Minimum Enclosing Circle
Next we find the circumcircle(外接圓 ) of an object using the function
CvInvoke.minEnclosingCircle(). It is a circle which completely covers the
object with minimum area.
5-8. Fitting an Ellipse
Next one is to fit an ellipse to an object. It returns the rotated rectangle in
which the ellipse is inscribed.
45
CvInvoke.FitEllipse Method
http://www.emgu.com
Fits an ellipse around a set of 2D points.
Namespace: Emgu.CV
Assembly: Emgu.CV.World (in Emgu.CV.World.dll) Version: 3.2.0.2682
public static RotatedRect FitEllipse(
IInputArray points
)
Parameters
points
Type: Emgu.CV.IInputArray
Input 2D point set
Return Value
Type: RotatedRect
The ellipse that fits best (in least-squares sense) to a set of 2D points
46
5-9. Fitting a Line
Similarly we can fit a line to a set of points. Below image contains a set of
white points. We can approximate a straight line to it.
CvInvoke.FitLine Method
http://www.emgu.com
Fits line to 2D or 3D point set
Namespace: Emgu.CV
Assembly: Emgu.CV (in Emgu.CV.dll) Version: 3.0.0.2161 (3.0.0.2161)
public static void FitLine(
IInputArray points,
IOutputArray line,
DistType distType,
double param,
double reps,
double aeps
)
47
Parameters
points
Type: Emgu.CV.IInputArray
Input vector of 2D or 3D points, stored in std::vector or Mat.
line
Type: Emgu.CV.IOutputArray
Output line parameters. In case of 2D fitting, it should be a vector of 4
elements (like Vec4f) - (vx, vy, x0, y0), where (vx, vy) is a normalized vector
collinear to the line and (x0, y0) is a point on the line. In case of 3D fitting,
it should be a vector of 6 elements (like Vec6f) - (vx, vy, vz, x0, y0, z0),
where (vx, vy, vz) is a normalized vector collinear to the line and (x0, y0,
z0) is a point on the line.
distType
Type: Emgu.CV.CvEnum.DistType
The distance used for fitting.
param
Type: System.Double
Numerical parameter (C) for some types of distances, if 0 then some
optimal value is chosen
reps
Type: System.Double
Sufficient accuracy for radius (distance between the coordinate origin
and the line), 0.01 would be a good default
aeps
Type: System.Double
Sufficient accuracy for angle, 0.01 would be a good default
5-10. Additional Resources
5-11. Exercises