Image Processing in OpenCV-Emgu

47
1 Image Processing in OpenCV-Emgu (2) Wen-Chang Cheng CYUT-CSIE 2019/10/29

Transcript of Image Processing in OpenCV-Emgu

Page 1: Image Processing in OpenCV-Emgu

1

Image Processing in OpenCV-Emgu (2)

Wen-Chang Cheng

CYUT-CSIE

2019/10/29

Page 2: Image Processing in OpenCV-Emgu

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

Page 3: Image Processing in OpenCV-Emgu

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

Page 4: Image Processing in OpenCV-Emgu

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

Page 5: Image Processing in OpenCV-Emgu

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

Page 6: Image Processing in OpenCV-Emgu

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.

Page 7: Image Processing in OpenCV-Emgu

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

Page 8: Image Processing in OpenCV-Emgu

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:

Page 9: Image Processing in OpenCV-Emgu

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,

Page 10: Image Processing in OpenCV-Emgu

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

Page 11: Image Processing in OpenCV-Emgu

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:

Page 12: Image Processing in OpenCV-Emgu

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:

Page 13: Image Processing in OpenCV-Emgu

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

Page 14: Image Processing in OpenCV-Emgu

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.

Page 15: Image Processing in OpenCV-Emgu

15

1-4. Additional Resources

1. Morphological Operations at HIPR2

1-5. Exercises

Page 16: Image Processing in OpenCV-Emgu

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

]

Page 17: Image Processing in OpenCV-Emgu

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

Page 18: Image Processing in OpenCV-Emgu

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

Page 19: Image Processing in OpenCV-Emgu

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)

Page 20: Image Processing in OpenCV-Emgu

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

)

Page 21: Image Processing in OpenCV-Emgu

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:

Page 22: Image Processing in OpenCV-Emgu

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:

Page 23: Image Processing in OpenCV-Emgu

23

2-4. Additional Resources

2-5. Exercises

Page 24: Image Processing in OpenCV-Emgu

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

Page 25: Image Processing in OpenCV-Emgu

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:

Page 26: Image Processing in OpenCV-Emgu

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:

Page 27: Image Processing in OpenCV-Emgu

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

Page 28: Image Processing in OpenCV-Emgu

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.

Page 29: Image Processing in OpenCV-Emgu

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

Page 30: Image Processing in OpenCV-Emgu

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

Page 31: Image Processing in OpenCV-Emgu

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.

Page 32: Image Processing in OpenCV-Emgu

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

Page 33: Image Processing in OpenCV-Emgu

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

Page 34: Image Processing in OpenCV-Emgu

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

Page 35: Image Processing in OpenCV-Emgu

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

Page 36: Image Processing in OpenCV-Emgu

36

5-5. Additional Resources

5-6. Exercises

Page 37: Image Processing in OpenCV-Emgu

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

)

Page 38: Image Processing in OpenCV-Emgu

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,

Page 39: Image Processing in OpenCV-Emgu

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,

Page 40: Image Processing in OpenCV-Emgu

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.

Page 41: Image Processing in OpenCV-Emgu

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.

Page 42: Image Processing in OpenCV-Emgu

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

Page 43: Image Processing in OpenCV-Emgu

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.

Page 44: Image Processing in OpenCV-Emgu

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.

Page 45: Image Processing in OpenCV-Emgu

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

Page 46: Image Processing in OpenCV-Emgu

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

)

Page 47: Image Processing in OpenCV-Emgu

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