You are on page 1of 186

TÁCH BIÊN VÀ PHÂN VÙNG

ẢNH
EDGE DETECTION AND
SEGMENTATION

TS NGUYỄN ĐỨC THÀNH 1


PHÂN NGƯỠNG THRESHOLDING
• Phân ngưỡng dùng để tách một vật ra khỏi ảnh
nền, đổi ảnh xám ra ảnh nhị phân
• Xét histogram ảnh xám bên dưới

Ta có thể kết luận ảnh nhị phân trắng của vật


ứng với f(x,y) >T và nền đen ứng với f(x,y) <T

TS NGUYỄN ĐỨC THÀNH 2


PHÂN NGƯỠNG THRESHOLDING
• Ngưỡng T chung cho toàn bộ ảnh gọi là ngưỡng toàn
cục
1. Chọn T bằng phương pháp thử sai dựa vào quan sát hoặc
dùng phương pháp lặp sau:
2. Chọn giá trị ban đầu cho T , thường là trung bình cường
độ cực đại và cực tiểu
3. Phân đoạn ảnh dùng ngưỡng T được hai nhóm G1, G2
4. Tính cường độ trung bình cho mỗi nhóm
5. Tính lại T là trung bình của hai cường độ này
6. Lặp lại bước 3

TS NGUYỄN ĐỨC THÀNH 3


PHÂN NGƯỠNG THRESHOLDING

TS NGUYỄN ĐỨC THÀNH 4


TẠO ẢNH NHỊ PHÂN DÙNG
PHƯƠNG PHÁP OTSU
• Otsu neâu ra phöông phaùp ñeå ñaùnh giaù phöông sai giöõa hai
lôùp. Nhöõng pixel cuûa aûnh coù giaù trò cöôøng ñoä trong daõy L
giaù trò möùc xaùm [0,1,2, … ,L], soá löôïng pixel ôû möùc i laø ni vaø
toång soá pixel cuûa aûnh laø

• Ñeå ñôn giaûn vaán ñeà, bieåu ñoà Histogram ñöôïc bieán ñoåi vaø
xem nhö laø moät phaân boá xaùc xuaát:

TS NGUYỄN ĐỨC THÀNH 5


TẠO ẢNH NHỊ PHÂN DÙNG
PHƯƠNG PHÁP OTSU
• Các điểm ảnh chia làm hai lớp C0 và C1 bởi giá trị k,
C0 ñaïi dieän cho nhöõng pixel coù cöôøng ñoä trong
khoaûng [0 ;k-1], vaø C1 ñaïi dieän cho nhöõng pixel coù
cöôøng ñoä trong khoaûng [k ; L-1].
• K chọn để cực đại phương sai giữa lớp

TS NGUYỄN ĐỨC THÀNH 6


TẠO ẢNH NHỊ PHÂN DÙNG
PHƯƠNG PHÁP OTSU

Matlab có hàm graythres


cho giá trị ngưỡng theo
pp này

Gía trị T này dùng trong hàm


ìmbw để đổi ảnh xám ra ảnh nhị
phân

TS NGUYỄN ĐỨC THÀNH 7


PHÂN NGƯỠNG CỤC BỘ (PHÂN NGƯỠNG
THÍCH NGHI)
• Nếu độ chiếu sáng thay đổi việc phân ngưỡng
có thể sai

Dùng ngưỡng thích nghi thay đổi theo điểm


ảnh để khắc phục
f0 là opening của f và T0 là
ngưỡng do hàm graythresh tác
động lên f0

TS NGUYỄN ĐỨC THÀNH 8


SO SÁNH PHÂN NGƯỠNG VÀ PHÂN NGƯỠNG
THÍCH NGHI

TS NGUYỄN ĐỨC THÀNH 9


MATLAB IM2BW
BW = im2bw(I,level) converts the grayscale image I to
binary image BW, by replacing all pixels in the input image
with luminance greater than level with the value 1 (white)
and replacing all other pixels with the value 0 (black).
This range is relative to the signal levels possible for the
image's class. Therefore, a level value of 0.5 corresponds to
an intensity value halfway between the minimum and
maximum value of the class.
BW = im2bw(X,cmap,level) converts the indexed image X
with colormap cmap to a binary image.
BW = im2bw(RGB,level) converts the truecolor image RGB
to a binary image.
TS NGUYỄN ĐỨC THÀNH 10
MATLAB IMBINARIZE
• T = graythresh(I) computes a global threshold T from
grayscale image I, using Otsu's method
• BW = imbinarize(I) creates a binary image from 2-D or 3-
D grayscale image I by replacing all values above a
globally determined threshold with 1s and setting all other
values to 0s.
• BW = imbinarize(I,method) creates a binary image from
image I using the thresholding method specified by
method: 'global' or 'adaptive'.
• BW = imbinarize(I,T) creates a binary image from image
I using the threshold value T.
TS NGUYỄN ĐỨC THÀNH 11
TẠO ẢNH NHỊ PHÂN DÙNG
PHƯƠNG PHÁP OTSU

I = imread('coins.png');
imshow(I)
level = graythresh(I);
BW = im2bw(I,level);
figure, imshow(BW)

TS NGUYỄN ĐỨC THÀNH 12


MATLAB ADAPTIVE THRESHOLD

I = imread('rice.png');
BW = imbinarize(I,
'adaptive');
figure
imshowpair(I,BW,'mo
ntage')

TS NGUYỄN ĐỨC THÀNH 13


MATLAB ADAPTIVE THRESHOLD
BW = imbinarize(I,'adaptive',Name,Value) creates a
binary image from image I using name-value pairs to
control aspects of adaptive thresholding.
I = imread('printedtext.png');
figure;imshow(I)
BW =
imbinarize(I,'adaptive','ForegroundPolarity','dark','Sensiti
vity',0.4);
Figure;imshow(BW)
title('Binary Version of Image')

TS NGUYỄN ĐỨC THÀNH 14


MATLAB ADAPTIVE THRESHOLD

TS NGUYỄN ĐỨC THÀNH 15


MATLAB ADAPTIVE THRESHOLD

TS NGUYỄN ĐỨC THÀNH 16


OPENCV THRESHOLD
Applies a fixed-level threshold to each array element.
C++: double threshold(InputArray src, OutputArray dst,
double thresh, double maxval, int type)
Python: cv2.threshold(src, thresh, maxval, type[, dst]) →
retval, dst
C: double cvThreshold(const CvArr* src, CvArr* dst,
double threshold, double max_value, int threshold_type)
Python: cv.Threshold(src, dst, threshold, maxValue,
thresholdType) → None

TS NGUYỄN ĐỨC THÀNH 17


OPENCV THRESHOLD
Parameters:
src – input array (single-channel, 8-bit or 32-bit
floating point).
dst – output array of the same size and type as src.
thresh – threshold value.
maxval – maximum value to use with the
THRESH_BINARY and
THRESH_BINARY_INV thresholding types.
type – thresholding type (see the details below).

TS NGUYỄN ĐỨC THÀNH 18


TYPE

TS NGUYỄN ĐỨC THÀNH 19


TYPE

TS NGUYỄN ĐỨC THÀNH 20


ẢNH VỚI CÁC SỐ CÓ MỨC XÁM
KHÁC NHAU

TS NGUYỄN ĐỨC THÀNH 21


C++
using namespace cv;
Mat src = imread("threshold.png",
IMREAD_GRAYSCALE);
Mat dst;
// Set threshold and maxValue
double thresh = 0;
double maxValue = 255;
threshold(src,dst, thresh, maxValue,
THRESH_BINARY);
TS NGUYỄN ĐỨC THÀNH 22
PYTHON
import cv2
src = cv2.imread("threshold.png",
cv2.IMREAD_GRAYSCALE)
# Set threshold and maxValue
thresh = 0
maxValue = 255
th, dst = cv2.threshold(src, thresh, maxValue,
cv2.THRESH_BINARY)

TS NGUYỄN ĐỨC THÀNH 23


OPENCV adaptiveThreshold
Applies an adaptive threshold to an array.
C++: void adaptiveThreshold(InputArray src,
OutputArray dst, double maxValue, int adaptiveMethod,
int thresholdType, int blockSize, double C)
Python: cv2.adaptiveThreshold(src, maxValue,
adaptiveMethod, thresholdType, blockSize, C[, dst]) →
dst
C: void cvAdaptiveThreshold(const CvArr* src, CvArr*
dst, double max_value, int
adaptive_method=CV_ADAPTIVE_THRESH_MEAN_
C, int threshold_type=CV_THRESH_BINARY, int
block_size=3, double param1=5 )
TS NGUYỄN ĐỨC THÀNH 24
OPENCV adaptiveThreshold
Python: cv.AdaptiveThreshold(src, dst, maxValue,
adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C
, thresholdType=CV_THRESH_BINARY, blockSize=3,
param1=5) → None
src – Source 8-bit single-channel image.
dst – Destination image of the same size and the same
type as src .
maxValue – Non-zero value assigned to the pixels for
which the condition is satisfied. See the details below.
adaptiveMethod – Adaptive thresholding algorithm to use,
ADAPTIVE_THRESH_MEAN_C or
ADAPTIVE_THRESH_GAUSSIAN_C .
TS NGUYỄN ĐỨC THÀNH 25
OPENCV adaptiveThreshold
thresholdType – Thresholding type that must be either
THRESH_BINARY or THRESH_BINARY_INV .
blockSize – Size of a pixel neighborhood that is used to
calculate a threshold value for the pixel: 3, 5, 7, and so on.
C – Constant subtracted from the mean or weighted mean
Normally, it is positive but may be zero or negative as well.
For the method ADAPTIVE_THRESH_MEAN_C , the
threshold value T(x,y) is a mean of the \texttt{blockSize}
\times \texttt{blockSize} neighborhood of (x, y) minus C .
ckSize . See getGaussianKernel()

TS NGUYỄN ĐỨC THÀNH 26


For the method
ADAPTIVE_THRESH_GAUSSIAN_C , the
threshold value T(x, y) is a weighted sum (cross-
correlation with a Gaussian window) of the
\texttt{blockSize} \times \texttt{blockSize}
neighborhood of (x, y) minus C . The default
sigma (standard deviation) is used for the
specified blo

TS NGUYỄN ĐỨC THÀNH 27


PYTHON ADAPTIVE THRESHOLD
import cv2
import numpy as np
img = cv2.imread("book_page.jpg")
_, threshold = cv2.threshold(img, 155, 255,
cv2.THRESH_BINARY)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
mean_c = cv2.adaptiveThreshold(img_gray, 255,
cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY, 15, 12)

TS NGUYỄN ĐỨC THÀNH 28


PYTHON ADAPTIVE THRESHOLD
gaus = cv2.adaptiveThreshold(img_gray, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 91, 12)
cv2.imshow("Img", img)
cv2.imshow("Binary threshold", threshold)
cv2.imshow("Mean C", mean_c)
cv2.imshow("Gaussian", gaus)
cv2.waitKey(0)
cv2.destroyAllWindows()
TS NGUYỄN ĐỨC THÀNH 29
PYTHON ADAPTIVE THRESHOLD

TS NGUYỄN ĐỨC THÀNH 30


TÁCH ĐiỂM CÔ LẬP
• Tách điểm cô lập: một điểm cô lập có thể tách bằng cách di chuyển
mặt nạ 3x3 trên ảnh, cường độ điểm ảnh ở tâm mặt nạ là tổng các
tích cường độ điểm ảnh bao bởi mặt nạ với các trọng số mặt nạ, nếu
quá mức ngưỡng nào đó thì kết luận là điểm cô lập
• Trong công thức dưới z là cường độ sáng, w là trọng số mặt nạ, R là
cường độ sáng mới, T là ngưỡng không âm

• Dùng dạng tích chập

TS NGUYỄN ĐỨC THÀNH 31


TS NGUYỄN ĐỨC THÀNH 32
TÁCH ĐƯỜNG
• Với các đường thẳng dầy một pixel theo chiều
ngang dọc hay góc 45o ta có thể dùng các mặt
nạ sau

TS NGUYỄN ĐỨC THÀNH 33


TÁCH CẠNH EDGE
• Thường tim sự thay đổi đột ngột của độ sáng bằng
phương pháp gradient, đạo hàm bậc một và bậc hai
(Laplacian) của độ sáng

TS NGUYỄN ĐỨC THÀNH 34


• Tìm cạnh ở chỗ đạo hàm bậc nhất lớn hơn gia trị ngưỡng
hay đạo hàm bậc hai bằng không
• Matlab có hàm edge tìm các điểm cạnh tùy theo method
và parameters, kết quả là ma trận g có giá trị 1 chỗ ó cạnh
và 0 ngược lại, và ngưỡng t tương ứng, parameters gồm
ngưỡng T và hướng direction

Các phép tính đạo hàm được thay bằng các tích chập
với các mặt nạ phù hợp
TS NGUYỄN ĐỨC THÀNH 35
TS NGUYỄN ĐỨC THÀNH 36
• Tách cạnh gồm ba giai đoạn: lọc, vi phân và so
ngưỡng
• Vi phân thường dùng lọc trung bình hay lọc
Gauss

• Lọc Gauss được tính khi cho trước sigma và tính g


theo x,y rồi chuẩn hóa thành trị nguyên

TS NGUYỄN ĐỨC THÀNH 37


TS NGUYỄN ĐỨC THÀNH 38
LỌC SOBEL

TS NGUYỄN ĐỨC THÀNH 39


LỌC PREWITT

Lọc Prewitt tính toán đơn giản hơn lọc Sobel nhưng kết
quả không trơn bằng

TS NGUYỄN ĐỨC THÀNH 40


LỌC ROBERTS

TS NGUYỄN ĐỨC THÀNH 41


LỌC LAPLACE
• Thay toán tử đạo hàm bậc hai bằng một trong
các mặt nạ

TS NGUYỄN ĐỨC THÀNH 42


LAPLACIAN OF GAUSSIAN
LoG
• Nhân chập ảnh với đạo hàm bậc hai của hàm
Gauss

TS NGUYỄN ĐỨC THÀNH 43


LỌC CANNY
• Phương pháp lọc tốt nhất, gồm các bước:
• Lọc Gauss
• Tính gradient và hướng, điểm cạnh ứng với gradient
tối đa theo hướng gradient
• So sánh với hai ngưỡng T1 < T2

TS NGUYỄN ĐỨC THÀNH 44


TS NGUYỄN ĐỨC THÀNH 45
TS NGUYỄN ĐỨC THÀNH 46
TS NGUYỄN ĐỨC THÀNH 47
CANNY C++
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
Mat src, src_gray; Mat dst, detected_edges;
int lowThreshold = 0; const int max_lowThreshold = 100;
const int ratio = 3; const int kernel_size = 3;
const char* window_name = "Edge Map";
static void CannyThreshold(int, void*)
{ blur( src_gray, detected_edges, Size(3,3) );
Canny( detected_edges, detected_edges, lowThreshold,
lowThreshold*ratio, kernel_size );
dst = Scalar::all(0); src.copyTo( dst, detected_edges);
imshow( window_name, dst );}
TS NGUYỄN ĐỨC THÀNH 48
CANNY C++

int main( int argc, char** argv )


{
src = imread( path,IMREAD_COLOR );
dst.create( src.size(), src.type() );
cvtColor( src, src_gray, COLOR_BGR2GRAY );
createTrackbar( "Min Threshold:", window_name,
&lowThreshold, max_lowThreshold, CannyThreshold );
CannyThreshold(0, 0);
waitKey(0);
return 0;
}

TS NGUYỄN ĐỨC THÀNH 49


TS NGUYỄN ĐỨC THÀNH 50
BiẾN ĐỔI HOUGH
• Sau khi tìm các điểm cạnh ta nối chúng lại để
tạo biên dùng biến đổi Hough
• Cho hai điểm cạnh (xi,yi) và (xj,yj) ta tìm
phương trình đường thẳng nối hai điểm này

• Tìm θ và ρ

TS NGUYỄN ĐỨC THÀNH 51


TS NGUYỄN ĐỨC THÀNH 52
BiẾN ĐỔI HOUGH
• Cho θ và ρ thay đổi trong phạm vi giới hạn và có giá
trị rời rạc, ta tạo ma trận tích lũy A(θ,ρ) có giá trị ban
đầu 0
• Với mỗi θ và điểm cạnh (xi,yi) ta tính ρ, A(θ,ρ) tương
ứng sẽ tăng thêm 1
• Tìm cặp (θ,ρ) ứng với A cực đại, có nghĩa là có nhiều
đường đi qua điểm cạnh có cùng (θ,ρ), có nghĩa là các
đường này trùng nhau, vậy ta tạo được đường thẳng
nối các điểm cạnh vì (θ,ρ) xác định một đường thẳng
duy nhất

TS NGUYỄN ĐỨC THÀNH 53
TS NGUYỄN ĐỨC THÀNH 54
TS NGUYỄN ĐỨC THÀNH 55
VÍ DỤ MATLAB BiẾN ĐỔI HOUGH
• Hàm hough tạo ma trận H(θ,ρ) dùng biến đổi Hough tiêu
chuẩn SHT
[H, theta, rho] = hough(BW)
[H, theta, rho] = hough(BW, ParameterName,
ParameterValue)
RGB = imread('gantrycrane.png');
% Convert to intensity.
I = rgb2gray(RGB);
% Extract edges.
BW = edge(I,'canny');
[H,T,R] = hough(BW,'RhoResolution',0.5,'Theta',-90:0.5:89.5);
% Display the original image.
subplot(2,1,1); imshow(RGB);
title('Gantrycrane Image');
TS NGUYỄN ĐỨC THÀNH 56
VÍ DỤ MATLAB BiẾN ĐỔI HOUGH
% Display the Hough matrix.
subplot(2,1,2); imshow(imadjust(mat2gray(H)),'XData',T,'YData',R,...
'InitialMagnification','fit');
title('Hough Transform of Gantrycrane Image');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on; colormap(hot);

TS NGUYỄN ĐỨC THÀNH 57


VÍ DỤ MATLAB BiẾN ĐỔI HOUGH
• Hàm houghpeaks tìm giá trị cực đại trong ma trận Hough, trả
về tọa độ hàng cột của điểm cực đại, numpeaks là số điểm cực
đại muốn tìm
peaks = houghpeaks(H, numpeaks)
peaks = houghpeaks(..., param1, val1, param2, val2)
%Read an image into the MATLAB workspace.
I = imread('circuit.tif');
%For this example, rotate and crop the image using the imrotate function.
rotI = imrotate(I,33,'crop'); fig1 = imshow(rotI);
%Find the edges in the image using the edge function.
BW = edge(rotI,'canny'); figure, imshow(BW);
%Compute the Hough transform of the image using the hough function.
[H,theta,rho] = hough(BW);
%Display the transform using the imshow function.
TS NGUYỄN ĐỨC THÀNH 58
VÍ DỤ MATLAB BiẾN ĐỔI HOUGH
figure,
imshow(imadjust(mat2gray(H)),[],'XData',theta,'YData',rho,...
'InitialMagnification','fit');
xlabel('\theta (degrees)'), ylabel('\rho');
axis on, axis normal, hold on; colormap(hot)
%Find the peaks in the Hough transform matrix, H, using the
houghpeaks function.
P = houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));
%Superimpose a plot on the image of the transform that identifies
the peaks.
x = theta(P(:,2)); y = rho(P(:,1)); plot(x,y,'s','color','black');

TS NGUYỄN ĐỨC THÀNH 59


VÍ DỤ MATLAB BiẾN ĐỔI HOUGH

TS NGUYỄN ĐỨC THÀNH 60


VÍ DỤ MATLAB BiẾN ĐỔI HOUGH
• Hàm houghlines tách đường thẳng dựa trên theta rho
do hàm hough cung cấp và peaks do hàm houghpeaks
Lines cung cấp tọa độ điểm mút của đoạn thẳng và giá trị
theta rho
lines = houghlines(BW, theta, rho, peaks)
lines = houghlines(..., param1, val1, param2, val2)
%Find lines in the image using the houghlines function.
lines = houghlines(BW,theta,rho,P,'FillGap',5,'MinLength',7);
%Create a plot that superimposes the lines on the original image.
figure, imshow(rotI), hold on
max_len = 0;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];

TS NGUYỄN ĐỨC THÀNH 61


VÍ DỤ MATLAB BiẾN ĐỔI HOUGH
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
% Plot beginnings and ends of lines
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
% Determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if ( len > max_len)
max_len = len;
xy_long = xy;
end
end
% highlight the longest line segment
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','red');

TS NGUYỄN ĐỨC THÀNH 62


VÍ DỤ MATLAB BiẾN ĐỔI HOUGH

TS NGUYỄN ĐỨC THÀNH 63


MATLAB TÌM ĐƯỜNG TRÒN
Find circles using circular Hough transform
centers = imfindcircles(A,radius)
[centers,radii] = imfindcircles(A,radiusRange)
[centers,radii,metric] = imfindcircles(A,radiusRange)
[centers,radii,metric] = imfindcircles(___,Name,Value)
centers = imfindcircles(A,radius) finds the circles in image A
whose radii are approximately equal to radius. The output, centers,
is a two-column matrix containing the x,y coordinates of the circles
centers in the image.
[centers,radii] = imfindcircles(A,radiusRange) finds circles with
radii in the range specified by radiusRange. The additional output
argument, radii, contains the estimated radii corresponding to each
circle center in centers.
TS NGUYỄN ĐỨC THÀNH 64
MATLAB TÌM ĐƯỜNG TRÒN
[centers,radii,metric] = imfindcircles(A,radiusRange) also returns
a column vector, metric, containing the magnitudes of the
accumulator array peaks for each circle (in descending order). The
rows of centers and radii correspond to the rows of metric.
[centers,radii,metric] = imfindcircles(___,Name,Value) specifies
additional options with one or more Name,Value pair arguments,
using any of the previous syntaxes.
centers — Coordinates of circle centers, two-column matrix
Coordinates of the circle centers, returned as a P-by-2 matrix
containing the x-coordinates of the circle centers in the first
column and the y-coordinates in the second column. The number
of rows, P, is the number of circles detected. centers is sorted
based on the strength of the circles.

TS NGUYỄN ĐỨC THÀNH 65


MATLAB TÌM ĐƯỜNG TRÒN
radii — Estimated radii, column vector
The estimated radii for the circle centers, returned as a column
vector. The radius value at radii(j) corresponds to the circle
centered at centers(j,:).
metric — Circle strengths, column vector
Circle strengths is the relative strengths for the circle centers,
returned as a vector. The value at metric(j) corresponds to the
circle with radius radii(j) centered at centers(j,:).
A — Input image grayscale image | truecolor image | binary image
Input image is the image in which to detect circular objects,
specified as a grayscale, truecolor, or binary image.

TS NGUYỄN ĐỨC THÀNH 66


MATLAB TÌM ĐƯỜNG TRÒN
radius — Circle radius, scalar numeric
Circle radius is the approximate radius of the circular objects
you want to detect, specified as a scalar of any numeric type.
radiusRange — Range of radii, two-element vector of integers
Range of radii for the circular objects you want to detect,
specified as a two-element vector, [rmin rmax], of integers of any
numeric type.
Name-Value Pair Arguments
Specify optional comma-separated pairs of Name,Value
arguments. Name is the argument name and Value is the
corresponding value. Name must appear inside single quotes (' ').
You can specify several name and value pair arguments in any
order as Name1,Value1,...,NameN,ValueN.
TS NGUYỄN ĐỨC THÀNH 67
MATLAB TÌM ĐƯỜNG TRÒN
'ObjectPolarity' — Object polarity, 'bright' (default) | 'dark'
Object polarity indicates whether the circular objects are brighter or
darker than the background, specified as the comma-separated pair
consisting of 'ObjectPolarity' and either of the values in the following
table.
'bright' The circular objects are brighter than the background.
'dark' The circular objects are darker than the background.
'Sensitivity' — Sensitivity factor
0.85 (default) | nonnegative scalar between 0 and 1
Sensitivity factor is the sensitivity for the circular Hough transform
accumulator array, specified as the comma-separated pair consisting
of 'Sensitivity' and a nonnegative scalar value in the range [0,1]. As
you increase the sensitivity factor, imfindcircles detects more circular
objects, including weak and partially
TS NGUYỄN ĐỨC THÀNH 68
MATLAB TÌM ĐƯỜNG TRÒN
obscured circles. Higher sensitivity values also increase the risk of
false detection.
'EdgeThreshold' — Edge gradient threshold ,nonnegative scalar
between 0 and 1
Edge gradient threshold sets the gradient threshold for determining
edge pixels in the image, specified as the comma-separated pair
consisting of 'EdgeThreshold' and a nonnegative scalar value in the
range [0,1]. Specify 0 to set the threshold to zero-gradient
magnitude. Specify 1 to set the threshold to the maximum gradient
magnitude. imfindcircles detects more circular objects (with both
weak and strong edges) when you set the threshold to a lower value.
It detects fewer circles with weak edges as you increase the value of
the threshold. By default, imfindcircles chooses the edge gradient
threshold automatically using the function graythresh.
Example: 'EdgeThreshold',0.5 sets the edge gradient threshold to 0.5.
TS NGUYỄN ĐỨC THÀNH 69
Detect Five Strongest Circles in an Image
This example shows how to find all circles in an image, and how to
retain and display the strongest circles.
Read a grayscale image into the workspace and display it.
A = imread('coins.png'); imshow(A)
Find all the circles with radius r pixels in the range [15, 30].
[centers, radii, metric] = imfindcircles(A,[15 30]);
NumCircles=length(radii)
Retain the five strongest circles according to the metric values.
centersStrong5 = centers(1:5,:);
radiiStrong5 = radii(1:5);
metricStrong5 = metric(1:5);
Draw the five strongest circle perimeters over the original image.
viscircles(centersStrong5, radiiStrong5,'EdgeColor','b');
TS NGUYỄN ĐỨC THÀNH 70
Detect Five Strongest Circles in an Image

TS NGUYỄN ĐỨC THÀNH 71


OPEN CV BiẾN ĐỔI HOUGH
CvSeq* cvHoughLines2(
CvArr* image,
void* line_storage,
int method,
double rho,
double theta,
int threshold,
double param1 = 0,
double param2 = 0
);
Image là ảnh nhị phân, method là các phương pháp biến đổi
CV_HOUGH_STANDARD, CV_HOUGH_PROBABILISTIC,
CV_HOUGH_MULTI_SCALE

TS NGUYỄN ĐỨC THÀNH 72


OPEN CV BiẾN ĐỔI HOUGH
rho và theta là độ phân giải theo pixel và radian, threshold là
ngưỡng để xác định đường
Giá trị trả về là rho và theta của đường hay tọa độ điểm đầu và
cuối của đường, tham số line_storage trỏ đến địa chỉ này

TS NGUYỄN ĐỨC THÀNH 73


THUẬT TÓAN HOUGH TÌM ĐƯỜNG TRÒN
• Vòng tròn có ba tham số là tâm và bán kính,
thuật toán tìm như sau

TS NGUYỄN ĐỨC THÀNH 74


THUẬT TÓAN HOUGH TÌM ĐƯỜNG TRÒN
• Phương trình đường tròn có thể viết là

TS NGUYỄN ĐỨC THÀNH 75


THUẬT TÓAN HOUGH TÌM ĐƯỜNG TRÒN
CvSeq* cvHoughCircles(
CvArr* image,
void* circle_storage,
int method,
double dp,
double min_dist,
double param1 = 100,
double param2 = 300,
int min_radius = 0,
int max_radius = 0
);

TS NGUYỄN ĐỨC THÀNH 76


THUẬT TÓAN HOUGH TÌM ĐƯỜNG TRÒN
• Using cvHoughCircles to return a sequence of circles found in a grayscale
image
#include <cv.h>
#include <highgui.h>
#include <math.h>
int main(int argc, char** argv) {
IplImage* image = cvLoadImage( argv[1],
CV_LOAD_IMAGE_GRAYSCALE
);
CvMemStorage* storage = cvCreateMemStorage(0);
cvSmooth(image, image, CV_GAUSSIAN, 5, 5 );
CvSeq* results = cvHoughCircles( image, storage,
CV_HOUGH_GRADIENT, 2, image->width/10
); TS NGUYỄN ĐỨC THÀNH 77
THUẬT TÓAN HOUGH TÌM ĐƯỜNG TRÒN
for( int i = 0; i < results->total; i++ ) {
float* p = (float*) cvGetSeqElem( results, i );
CvPoint pt = cvPoint( cvRound( p[0] ), cvRound( p[1] ) );
cvCircle( image, pt, cvRound( p[2] ),
CV_RGB(0xff,0xff,0xff) );
}
cvNamedWindow( “cvHoughCircles”, 1 );
cvShowImage( “cvHoughCircles”, image);
cvWaitKey(0);
}

TS NGUYỄN ĐỨC THÀNH 78


THUẬT TÓAN HOUGH TÌM ĐƯỜNG TRÒN

TS NGUYỄN ĐỨC THÀNH 79


THUẬT TOÁN HOUGH SUY RỘNG
• Áp dụng cho một hình bất kỳ
• Đầu tiên tìm trọng tâm hình (centroid)

Với mỗi điểm cạnh (x,y) tìm vectơ r(x’,y’)

TS NGUYỄN ĐỨC THÀNH 80


THUẬT TOÁN HOUGH SUY RỘNG

TS NGUYỄN ĐỨC THÀNH 81


FLOODFILL

• Dùng để tô màu, đánh dấu một vùng ảnh


void cvFloodFill(
IplImage* img,
CvPoint seedPoint,
CvScalar newVal,
CvScalar loDiff = cvScalarAll(0),
CvScalar upDiff = cvScalarAll(0),
CvConnectedComp* comp = NULL,
int flags = 4,
CvArr* mask = NULL
);

TS NGUYỄN ĐỨC THÀNH 82


FLOODFILL
• Img là ảnh xám hay màu
• Floodfill bắt đầu từ seedpoint, thay các pixel lân cận
bằng giá trị mới newVal nếu cường độ sáng điểm đó
trong khoảng loDiff và upDiff so với seedpoint hay
so với pixel lân cận đã tô màu tùy theo giá trị của
flags

TS NGUYỄN ĐỨC THÀNH 83


GÁN NHÃN CHO CÁC PIXEL LIÊN KẾT
• Một ảnh vật gồm các pixel liên kết với nhau

• Người có thể thấy ảnh trên gồm mười vật


nhưng làm sao chương trình máy tính có thể
hiểu TS NGUYỄN ĐỨC THÀNH 84
LÁNG GiỀNG NEIGHBOR
• Pixel p(x,y) có bốn cận ngang và dọc gọi là N4(p) có tọa độ (x-
1,y),(x+1,y), (x,y-1) và (x,y+1),
• Bốn cận chéo là ND(p)
• Cận 8 N8(p) là kết hợp N4 và ND
• Pixel p và q là kề 4 nếu q thuộc N4(p), kề 8 nếu q thuộc N8(p)

• Path là một loạt pixel kề nhau


• Hai pixel là kết nối 4 nếu có
path kết nối 4 giữa chúng, kết
TS NGUYỄN ĐỨC THÀNH
nối 8 nếu có path kết nối 8
85
• Tập hợp các pixel kết nối với nhau gọi là thành phần component
• Các pixel trong cùng một thành phần được gán một số gọi là nhãn đặt trong
ma trận nhãn Label Matrix

TS NGUYỄN ĐỨC THÀNH 86


cc = bwconncomp(BW)
cc =
Connectivity: 8
ImageSize: [8 9]
NumObjects: 3
PixelIdxList: {[6x1 double] [6x1 double] [5x1
double]}

TS NGUYỄN ĐỨC THÀNH 87


• For visualizing connected components, it is useful
to construct a label matrix. Use the labelmatrix
function. To inspect the results, display the label
matrix as a pseudo-color image using label2rgb.
• Construct a label matrix:
– labeled = labelmatrix(cc); Create a pseudo-color
image, where the label identifying each object in the
label matrix maps to a different color in the associated
colormap matrix. Use label2rgb to choose the
colormap, the background color, and how objects in
the label matrix map to colors in the colormap:
– RGB_label = label2rgb(labeled, @copper, 'c',
'shuffle');
imshow(RGB_label,'InitialMagnification','fit')
TS NGUYỄN ĐỨC THÀNH 88
TS NGUYỄN ĐỨC THÀNH 89
TÍNH TRỌNG TÂM COMPONENTS

TS NGUYỄN ĐỨC THÀNH 90


TÍNH DiỆN TÍCH
• Hàm bwarea tính diện tích ảnh nhị phân, là số
pixel cường độ sáng 1
• Ví dụ tính phần trăm tăng diện tích khi dùng
Dilation
W = imread('circbw.tif');
SE = ones(5);
BW2 = imdilate(BW,SE);
increase = (bwarea(BW2) -bwarea(BW))/bwarea(BW)
increase = 0.3456

TS NGUYỄN ĐỨC THÀNH 91


PHÂN ẢNH DỰA THEO VÙNG
• Phân ảnh dựa theo vùng là chia ảnh thảnh nhiều vùng không
giao nhau, các điểm trong một vùng có tính chất P chung

TS NGUYỄN ĐỨC THÀNH 92


PHÂN ẢNH DỰA VÀO ĐƯỜNG PHÂN THỦY
(WATERSHED)

• Ảnh xám có thể xem như một bề mặt có chỗ cao chỗ thấp, chỗ
thấp là lưu vực (catchment basin) nơi các con sông chảy
xuống, đường phân thủy phân chia ranh giơi lưu vực, các con
sông phát xuất từ đường phân thủy chảy ra hai bên. Các lưu
vực chính là các vùng ảnh và đường phân thủy là ranh giới các
vùng, để tìm đường phân thủy ta cho nước dâng lên cho đến
khi các hồ giao nhau , đường phân thủy vẽ đường ranh giới
giữa các vùng chạm nhau
• Để biểu thị độ cao các vùng trũng ta dùng biến đổi khoảng
cách, giả sử nền ảnh đen trắng là đen (0) các vùng có gía trị
trắng (1), ta lấy đảo ảnh, sau đó dùng biến đổi khoảng cách,
các pixel giá trị 1 được thay bằng 0.0, các pixel giá trị 0 được
thay bằng khoảng cách đến pixel giá trị 1 gần nhất
TS NGUYỄN ĐỨC THÀNH 93
PHÂN ẢNH DỰA VÀO ĐƯỜNG PHÂN THỦY
(WATERSHED)

TS NGUYỄN ĐỨC THÀNH 94


TS NGUYỄN ĐỨC THÀNH 95
TS NGUYỄN ĐỨC THÀNH 96
• Cho ảnh f
• Hàm D=bwdist(-f) biến đổi ảnh ra ảnh biến đổi
khoảng cách
• Hàm L=watershed (-D) vẽ đường phân thủy,
giá trị 0 là đường phân thủy
• w=L==0 có giá trị 1 ở đường phân thủy
• G=f and (-w) vẽ đường phân thủy trên ảnh gốc

TS NGUYỄN ĐỨC THÀNH 97


TS NGUYỄN ĐỨC THÀNH 98
• Trước khi dùng watershed transform thường
biến đổi ảnh bằng các bộ lọc như
morphological gradient, closing opening

TS NGUYỄN ĐỨC THÀNH 99


TS NGUYỄN ĐỨC THÀNH 100
Marker-Controlled Watershed Segmentation
This example shows how to use watershed segmentation to
separate touching objects in an image. The watershed transform is
often applied to this problem. The watershed transform finds
"catchment basins" and "watershed ridge lines" in an image by
treating it as a surface where light pixels are high and dark pixels
are low.
Segmentation using the watershed transform works better if you
can identify, or "mark," foreground objects and background
locations. Marker-controlled watershed segmentation follows this
basic procedure:
1. Compute a segmentation function. This is an image whose dark
regions are the objects you are trying to segment.

TS NGUYỄN ĐỨC THÀNH 101


Marker-Controlled Watershed Segmentation

2. Compute foreground markers. These are connected blobs of


pixels within each of the objects.
3. Compute background markers. These are pixels that are not
part of any object.
4. Modify the segmentation function so that it only has minima at
the foreground and background marker locations.
5. Compute the watershed transform of the modified
segmentation function.
This example highlights many different Image Processing
Toolbox™ functions, including imgradient, watershed, label2rgb,
labeloverlay, imopen, imclose, imreconstruct, imcomplement,
imregionalmax, bwareaopen, graythresh, and imimposemin.
TS NGUYỄN ĐỨC THÀNH 102
Marker-Controlled Watershed Segmentation
rgb = imread('pears.png');
I = rgb2gray(rgb); imshow(I)
text(732,501,'Image courtesy of Corel(R)',...
'FontSize',7,'HorizontalAlignment','right')

TS NGUYỄN ĐỨC THÀNH 103


Marker-Controlled Watershed Segmentation

gmag =
imgradient(I);
imshow(gmag,[]
)
title('Gradient
Magnitude')

TS NGUYỄN ĐỨC THÀNH 104


Marker-Controlled Watershed Segmentation
%Cannot segment the
image by using the
watershed transform
directly on the gradient
magnitude
L = watershed(gmag);
Lrgb = label2rgb(L);
imshow(Lrgb)
title('Watershed
Transform of Gradient
Magnitude')

TS NGUYỄN ĐỨC THÀNH 105


Marker-Controlled Watershed Segmentation

Without additional preprocessing such as the marker


computations below, using the watershed transform directly often
results in "oversegmentation."
A variety of procedures could be applied here to find the
foreground markers, which must be connected blobs of pixels
inside each of the foreground objects. In this example you'll use
morphological techniques called "opening-by-reconstruction" and
"closing-by-reconstruction" to "clean" up the image. These
operations will create flat maxima inside each object that can be
located using imregionalmax.

TS NGUYỄN ĐỨC THÀNH 106


Marker-Controlled Watershed Segmentation

se = strel('disk',20);
Io = imopen(I,se);
imshow(Io)
title('Opening')

TS NGUYỄN ĐỨC THÀNH 107


Ie = imerode(I,se);
Iobr =
imreconstruct(Ie,I);
imshow(Iobr)
title('Opening-by-
Reconstruction')

TS NGUYỄN ĐỨC THÀNH 108


%Following the opening with a closing can remove the dark
spots and stem marks. Compare a regular morphological
closing with a closing-by-reconstruction. First try imclose:

Ioc =
imclose(Io,se);
imshow(Ioc)
title('Opening-
Closing')

TS NGUYỄN ĐỨC THÀNH 109


%Now use imdilate followed by imreconstruct. Notice you must
complement the image inputs and output of imreconstruct.
Iobrd = imdilate(Iobr,se);
Iobrcbr =
imreconstruct(imcomple
ment(Iobrd),imcomplem
ent(Iobr));
Iobrcbr =
imcomplement(Iobrcbr);
imshow(Iobrcbr)
title('Opening-Closing by
Reconstruction') TS NGUYỄN ĐỨC THÀNH 110
As you can see by comparing Iobrcbr with Ioc, reconstruction-
based opening and closing are more effective than standard
opening and closing at removing small blemishes without
affecting the overall shapes of the objects. Calculate the regional
maxima of Iobrcbr to obtain good foreground markers.

fgm =
imregionalmax(Iobrc
br);
imshow(fgm)
title('Regional
Maxima of Opening-
Closing by
Reconstruction')
TS NGUYỄN ĐỨC THÀNH 111
To help interpret the result, superimpose the
foreground marker image on the original image
I2 =
labeloverlay(I,fgm);
imshow(I2)
title('Regional
Maxima
Superimposed on
Original Image')

TS NGUYỄN ĐỨC THÀNH 112


Notice that some of the mostly-occluded and shadowed objects
are not marked, which means that these objects will not be
segmented properly in the end result. Also, the foreground
markers in some objects go right up to the objects' edge. That
means you should clean the edges of the marker blobs and then
shrink them a bit. You can do this by a closing followed by an
erosion.
se2 = strel(ones(5,5));
fgm2 = imclose(fgm,se2);
fgm3 = imerode(fgm2,se2);

TS NGUYỄN ĐỨC THÀNH 113


This procedure tends to leave some stray isolated pixels that must
be removed. You can do this using bwareaopen, which removes
all blobs that have fewer than a certain number of pixels.

fgm4 =
bwareaopen(fgm3,2
0);
I3 =
labeloverlay(I,fgm4);
imshow(I3)
title('Modified
Regional Maxima
Superimposed on
Original Image') TS NGUYỄN ĐỨC THÀNH 114
Now you need to mark the background. In the cleaned-up image,
Iobrcbr, the dark pixels belong to the background, so you could
start with a thresholding operation.

bw =
imbinarize(Iob
rcbr);
imshow(bw)
title('Threshol
ded Opening-
Closing by
Reconstructio
n')

TS NGUYỄN ĐỨC THÀNH 115


The background pixels are in black, but ideally we don't want the
background markers to be too close to the edges of the objects we
are trying to segment. We'll "thin" the background by computing
the "skeleton by influence zones", or SKIZ, of the foreground of
bw. This can be done by computing the watershed transform of
the distance transform of bw, and then looking for the watershed
ridge lines (DL == 0) of the result.
D = bwdist(bw);
DL =
watershed(D);
bgm = DL == 0;
imshow(bgm)
title('Watershed
Ridge Lines)')
TS NGUYỄN ĐỨC THÀNH 116
5/The function imimposemin can be used to modify an image so
that it has regional minima only in certain desired locations. Here
you can use imimposemin to modify the gradient magnitude
image so that its only regional minima occur at foreground and
background marker pixels.
gmag2 =
imimposemin(g
mag, bgm |
fgm4);

L=
watershed(gm
ag2);

TS NGUYỄN ĐỨC THÀNH 117


6/One visualization technique is to superimpose the foreground
markers, background markers, and segmented object boundaries
on the original image. You can use dilation as needed to make
certain aspects, such as the object boundaries, more visible.
Object boundaries are located where L == 0. The binary
foreground and background markers are scaled to different
integer values so that they are assigned different labels.
labels =
imdilate(L==0,ones(3,3)) +
2*bgm + 3*fgm4;
I4 = labeloverlay(I,labels);
imshow(I4)
title('Markers and Object
Boundaries Superimposed
on Original Image')

TS NGUYỄN ĐỨC THÀNH 118


This visualization illustrates how the locations of the foreground
and background markers affect the result. In a couple of
locations, partially occluded darker objects were merged with
their brighter neighbor objects because the occluded objects did
not have foreground markers.
Another useful visualization technique is to display the label
matrix as a color image. Label matrices, such as those produced
by watershed and bwlabel, can be converted to truecolor images
for visualization purposes by using label2rgb.

Lrgb =
label2rgb(L,'jet','w','shuffle
');
imshow(Lrgb)
title('Colored Watershed
Label Matrix')
TS NGUYỄN ĐỨC THÀNH 119
You can use transparency to superimpose this pseudo-color label
matrix on top of the original intensity image.

figure
imshow(I)
hold on
himage =
imshow(Lrgb);
himage.AlphaData =
0.3;
title('Colored Labels
Superimposed
Transparently on
Original Image') TS NGUYỄN ĐỨC THÀNH 120
CONTOUR ĐƯỜNG BAO
• A contour is a list of points that represent, in one way or
another, a curve in an image.
• The function cv::findContours() computes contours from
binary images. It can take images created by cv::Canny(),
which have edge pixels in them, or images created by
functions like cv::threshold() or cv::adaptiveThreshold(), in
which the edges are implicit as boundaries between positive
and negative regions.

TS NGUYỄN ĐỨC THÀNH 121


CONTOUR

Hierarchy is the output that describes the tree structure of the contours. The
output hierarchy will be an array with one entry for each contour in contours.
Each such entry will contain an array of four elements, each indicating the node
to which a particular link from the current node is connected

TS NGUYỄN ĐỨC THÀNH 122


CONTOUR

A test image (left


side) passed to
cv::findContours().
cx: contour, hx: hole

TS NGUYỄN ĐỨC THÀNH 123


CONTOUR

TS NGUYỄN ĐỨC THÀNH 124


TRACKBAR

TS NGUYỄN ĐỨC THÀNH 125


CONTOUR FIND AND DRAW
// Finding contours based on a trackbar’s location; the contours
//are updated whenever the trackbar is moved
#include "stdafx.h"
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
using namespace std;
Mat src; Mat src_gray;
int thresh = 100;
RNG rng(12345);

TS NGUYỄN ĐỨC THÀNH 126


CONTOUR FIND AND DRAW
/// Function header
void thresh_callback(int, void*);
int main(int argc, char** argv)
{//src = imread(argv[1], 1);
src = imread("d:/fish.png", 1);
cvtColor(src, src_gray, CV_BGR2GRAY);
blur(src_gray, src_gray, Size(3, 3));
imshow(“Source”, src);
createTrackbar(" Canny thresh:", "Source", &thresh, 255,
thresh_callback);
thresh_callback(0, 0); waitKey(0); return(0);}

TS NGUYỄN ĐỨC THÀNH 127


CONTOUR FIND AND DRAW
void thresh_callback(int, void*)
{Mat canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
Canny(src_gray, canny_output, thresh, thresh * 2, 3);
findContours(canny_output, contours, hierarchy,
CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);
for (int i = 0; i< contours.size(); i++)
{Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255),
rng.uniform(0, 255));
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0,
Point()); }
imshow("Contours", drawing);} TS NGUYỄN ĐỨC THÀNH 128
CONTOUR FIND AND DRAW

TS NGUYỄN ĐỨC THÀNH 129


MOMENTS
• Moment bậc p, q của ảnh nhị phân là

m00 là diện tích các phần ảnh khác 0, với contour m00 là
chiều dài contour,
m10/m00 và m01/m00 là tọa độ trọng tâm (x,y) của phần
diện tích đường bao

Central moments

TS NGUYỄN ĐỨC THÀNH 130


MOMENTS

TS NGUYỄN ĐỨC THÀNH 131


DRAW CONTOUR AND CENTER
void thresh_callback(int, void*)
{Mat canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
Canny(src_gray, canny_output, thresh, thresh * 2, 3);
findContours(canny_output, contours, hierarchy,
CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,
0));
/// Get the moments
vector<Moments> mu(contours.size());
for (int i = 0; i < contours.size(); i++)
{mu[i] = moments(contours[i], false);}
TS NGUYỄN ĐỨC THÀNH 132
DRAW CONTOUR AND CENTER
/// Get the mass centers:
vector<Point2f> mc(contours.size());
for (int i = 0; i < contours.size(); i++)
{mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);}
/// Draw contours
Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);
for (int i = 0; i< contours.size(); i++)
{Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255),
rng.uniform(0, 255));
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0,
Point());
circle(drawing, mc[i], 4, color, -1, 8, 0);}
TS NGUYỄN ĐỨC THÀNH 133
DRAW CONTOUR AND CENTER
imshow("Contours", drawing);
/// Calculate the area with the moments 00 and compare with the
result of the OpenCV function
printf("\t Info: Area and Contour Length \n");
for (int i = 0; i< contours.size(); i++)
{printf(" * Contour[%d] - Area (M_00) = %.2f - Area OpenCV:
%.2f - Length: %.2f \n", i, mu[i].m00, contourArea(contours[i]),
arcLength(contours[i], true));
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255),
rng.uniform(0, 255));
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0,
Point());
circle(drawing, mc[i], 4, color, -1, 8, 0);}}
TS NGUYỄN ĐỨC THÀNH 134
DRAW CONTOUR AND CENTER

TS NGUYỄN ĐỨC THÀNH 135


PYTHON CENTROID
# read image through command line
img = cv2.imread(args["ipimage"])
gray_image = cv2.cvtColor(img,
cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray_image,127,255,0)
# find contours in the binary image
im2, contours, hierarchy =
cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_
APPROX_SIMPLE)
for c in contours:
# calculate moments for each contour
TS NGUYỄN ĐỨC THÀNH 136
M = cv2.moments(c)
PYTHON CENTROID
# calculate x,y coordinate of center
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
cv2.circle(img, (cX, cY), 5, (255, 255, 255), -1)
cv2.putText(img, "centroid", (cX - 25, cY -
25),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,
255, 255), 2)
cv2.imshow("Image", img)
cv2.waitKey(0)
TS NGUYỄN ĐỨC THÀNH 137
CONVEX HULL
• The convex hull of a polygon or contour is the polygon that
completely contains the original, is made only of points from the
original, and is everywhere convex (i.e., the internal angle between
any three sequential points is less than 180 degrees). There are
many reasons to compute convex hulls. One particularly common
reason is that testing whether a point is inside a convex polygon can
be very fast, and it is often worthwhile to test first whether a point
is inside the convex hull of a complicated polygon before even
bothering to test whether it is in the true polygon.

TS NGUYỄN ĐỨC THÀNH 138


CONVEX HULL HAND DETECT

TS NGUYỄN ĐỨC THÀNH 139


CONVEX HULL HAND DETECT

TS NGUYỄN ĐỨC THÀNH 140


CONVEX HULL HAND DETECT

TS NGUYỄN ĐỨC THÀNH 141


CONVEX HULL HAND DETECT

TS NGUYỄN ĐỨC THÀNH 142


CONVEX HULL HAND DETECT
import numpy as np
import cv2
hand = cv2.imread("hand.jpg", 0)
ret, threshold = cv2.threshold(hand, 10, 255,
cv2.THRESH_BINARY)
contours, hiearchy = cv2.findContours(threshold, cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
basic_contours = cv2.drawContours(hand, contours, -1, (0,255,0))
hull = [cv2.convexHull(c) for c in contours]
final = cv2.drawContours(hand, hull, -1, (255,255,255))
cv2.imshow('Original', hand)
cv2.imshow('Thresh', threshold)
cv2.imshow('Convel Hull', hand)
TS NGUYỄN ĐỨC THÀNH 143
cv2.waitKey(0)
CONVEX HULL HAND DETECT

• https://drive.google.com/file/d/0B7lDtwez94H
3MWZlMGQwOTUtODk2Ni00NmNmLWI3
NTUtNjA4MTY2NTc5NDk0/view
• https://dev.to/amarlearning/finger-detection-
and-tracking-using-opencv-and-python-586m

TS NGUYỄN ĐỨC THÀNH 144


BLOB COUNTING MATLAB
BW2 = imfill(BW,locations) performs a flood-fill operation on
background pixels of the input binary image BW, starting from
the points specified in locations.
BW2 = imfill(BW,locations,conn) fills the area defined by
locations, where conn specifies the connectivity.
BW2 = imfill(BW,'holes') fills holes in the input binary image
BW. In this syntax, a hole is a set of background pixels that
cannot be reached by filling in the background from the edge of
the image.
BW2 = imfill(BW,conn,'holes') fills holes in the binary image
BW, where conn specifies the connectivity.
I2 = imfill(I) fills holes in the grayscale image I. In this syntax, a
hole is defined as an area of dark pixels surrounded by lighter
pixels.
TS NGUYỄN ĐỨC THÀNH 145
I2 = imfill(I,conn) fills holes in the grayscale image I, where conn
specifies the connectivity.
BW2 = imfill(BW) displays the binary image BW on the screen
and lets you define the region to fill by selecting points
interactively with the mouse. To use this syntax, BW must be a 2-
D image.
BW2 = imfill(BW,0,conn) lets you override the default
connectivity as you interactively specify locations.
[BW2, locations_out] = imfill(BW) returns the locations of points
selected interactively in locations_out. To use this syntax, BW
must be a 2-D image.

TS NGUYỄN ĐỨC THÀNH 146


conn — Pixel connectivity
4 | 8 | 6 | 18 | 26 | 3-by-3-by- ... -by-3 matrix of 0s and 1s

TS NGUYỄN ĐỨC THÀNH 147


TS NGUYỄN ĐỨC THÀNH 148
I = imread('coins.png');
figure;imshow(I);title('Origin
al Image')
BW = imbinarize(I);
figure;imshow(BW),title('Bin
ary Image')
BW2 =
imfill(BW,'holes');figure;
imshow(BW2);title('Filled
Image')

TS NGUYỄN ĐỨC THÀNH 149


bwlabel GÁN NHÃN

L = bwlabel(BW) returns the label matrix L that contains labels


for the 8-connected objects found in BW.
L = bwlabel(BW,conn) returns a label matrix, where conn
specifies the connectivity.
[L,n] = bwlabel(___) also returns n, the number of connected
objects found in BW.

TS NGUYỄN ĐỨC THÀNH 150


GÁN NHÃN
A connected component in a binary image is a set of pixels
that form a connected group. For example, the binary image
below has three connected components. Connected
component labeling is the process of identifying the connected
components in an image and assigning each one a unique
label, like this:

The matrix above is called a label matrix


TS NGUYỄN ĐỨC THÀNH 151
GÁN NHÃN
bwconncomp computes connected components, as shown in the
example:
cc = bwconncomp(BW)
cc =
Connectivity: 8
ImageSize: [8 9]
NumObjects: 3
PixelIdxList: {[6x1 double] [6x1 double] [5x1 double]}
The PixelIdxList identifies the list of pixels belonging to each
connected component. For visualizing connected components, it
is useful to construct a label matrix. Use the labelmatrix function.
To inspect the results, display the label matrix as a pseudo-color
image using label2rgb.
TS NGUYỄN ĐỨC THÀNH 152
GÁN NHÃN

Construct a label matrix:


labeled = labelmatrix(cc);
Create a pseudo-color image, where the
label identifying each object in the label
matrix maps to a different color in the
associated colormap matrix. Use label2rgb
to choose the colormap, the background
color, and how objects in the label matrix
map to colors in the colormap:
RGB_label = label2rgb(labeled, @copper,
'c', 'shuffle');
imshow(RGB_label,'InitialMagnification','fi
t') TS NGUYỄN ĐỨC THÀNH 153
regionprops
Measure properties of image regions
stats = regionprops(BW,properties) returns measurements for the set
of properties specified by properties for each 8-connected component
(object) in the binary image, BW. stats is struct array containing a
struct for each object in the image. You can use regionprops on
contiguous regions and discontiguous regions
For all syntaxes, if you do not specify the properties argument, then
regionprops returns the 'Area', 'Centroid', and 'BoundingBox'
measurements.
stats = regionprops(CC,properties) measures a set of properties for
each connected component (object) in CC, which is a structure
returned by bwconncomp.

TS NGUYỄN ĐỨC THÀNH 154


regionprops
Measure properties of image regions

stats = regionprops(L,properties) measures a set of properties for


each labeled region in label matrix L.
stats = regionprops(___,I,properties) returns measurements for
the set of properties specified by properties for each labeled
region in the image I. The first input to regionprops (BW, CC, or
L) identifies the regions in I.
stats = regionprops(output,___) returns measurements for a set of
properties, where output specifies the type of return value.
regionprops can return measurements in a struct array or a table.

TS NGUYỄN ĐỨC THÀNH 155


regionprops
Measure properties of image regions
a = imread('circlesBrightDark.png');
bw = a < 100;
imshow(bw);title('Image with Circles');
[L,n]=bwlabel(bw)
stats = regionprops('table',bw,'Centroid',...
'MajorAxisLength','MinorAxisLength')
centers = stats.Centroid;
diameters = mean([stats.MajorAxisLength
stats.MinorAxisLength],2);
radii = diameters/2;
hold on
viscircles(centers,radii);
hold off TS NGUYỄN ĐỨC THÀNH 156
regionprops
Measure properties of image regions

TS NGUYỄN ĐỨC THÀNH 157


BLOB COUNTING MATLAB
% Adapted from code of ImageAnalyst, mage Segmentation Tutorial
clc; close all;
originalImage = imread('coins.png');
subplot(3, 3, 1);
imshow(originalImage); drawnow;
caption = sprintf('Original image'); title(caption, 'FontSize', 10);
axis image;
% Threshold the image to get a binary image (only 0's and 1's) of
%class "logical."
% Method #1: using im2bw()
% normalizedThresholdValue = 0.4; % In range 0 to 1.
% thresholdValue = normalizedThresholdValue
*max(max(originalImage)); % Gray Levels.
TS NGUYỄN ĐỨC THÀNH 158
BLOB COUNTING MATLAB
% binaryImage = im2bw(originalImage,
normalizedThresholdValue); % One way to threshold to binary
% Method #2: using a logical operation.
%thresholdValue = 100;
binaryImage = originalImage > 100; % Bright objects will be chosen
%if you use >, Use < if you want to find dark objects instead of
%bright objects.
% binaryImage = originalImage < thresholdValue; % Dark objects
will be chosen if you use <.
% Do a "hole fill" to get rid of any background pixels or "holes"
inside the blobs.
binaryImage = imfill(binaryImage, 'holes');
subplot(3, 3, 2);
TS NGUYỄN ĐỨC THÀNH 159
BLOB COUNTING MATLAB
imshow(binaryImage); title('Binary Image', 'FontSize', 10);
% Identify individual blobs by seeing which pixels are connected
%to each other. Each group of connected pixels will be given a
%label, a number, to identify it and distinguish it from the other
%blobs. % Do connected components labeling with either
%bwlabel() or bwconncomp().
labeledImage = bwlabel(binaryImage, 8);
% Label each blob so we can make measurements of it
% labeledImage is an integer-valued image where all pixels in the
%blobs have values of 1, or 2, or 3, or ... etc.
subplot(3, 3, 3);
imshow(labeledImage, []); % Show the gray scale image.

TS NGUYỄN ĐỨC THÀNH 160


BLOB COUNTING MATLAB
title('Labeled Image', 'FontSize', 10);
% Let's assign each blob a different color to visually show the %user
the distinct blobs.
coloredLabels = label2rgb (labeledImage, 'hsv', 'k', 'shuffle');
% pseudo random color labels, coloredLabels is an RGB image.
%We could have applied a colormap instead
subplot(3, 3, 4);
imshow(coloredLabels);
axis image;
caption = sprintf('Pseudo colored labels'); title(caption, 'FontSize', 10);
% Get all the blob properties. Can only pass in originalImage in
%version R2008a and later.

TS NGUYỄN ĐỨC THÀNH 161


BLOB COUNTING MATLAB

blobMeasurements = regionprops(labeledImage, originalImage, 'all');


numberOfBlobs = size(blobMeasurements, 1)
% bwboundaries() returns a cell array, where each cell contains the
%row/column coordinates for an object in the image.
% Plot the borders of all the coins on the original grayscale image
%using the coordinates returned by bwboundaries.
subplot(3, 3, 5);
imshow(originalImage); title('Outlines', 'FontSize', 10);
axis image; hold on;
boundaries = bwboundaries(binaryImage);
numberOfBoundaries = size(boundaries, 1);

TS NGUYỄN ĐỨC THÀNH 162


BLOB COUNTING MATLAB
for k = 1 : numberOfBoundaries
thisBoundary = boundaries{k};
plot(thisBoundary(:,2), thisBoundary(:,1), 'g', 'LineWidth', 1);
end
hold off;
labelShiftX = -12;
% Used to align the labels in the centers of the coins.
blobECD = zeros(1, numberOfBlobs);
% Print header line in the command window.
fprintf(1,'Blob # Mean Intensity Area Perimeter Centroid
Diameter\n');
% Loop over all blobs printing their measurements to the command
%window.
TS NGUYỄN ĐỨC THÀNH 163
BLOB COUNTING MATLAB
for k = 1 : numberOfBlobs % Loop through all blobs.
% Find the mean of each blob. (R2008a has a better way where
% you can pass the original image
% directly into regionprops. The way below works for all
%versions including earlier versions.)
thisBlobsPixels = blobMeasurements(k).PixelIdxList;
% Get list of pixels in current blob.
meanGL = mean(originalImage(thisBlobsPixels));
% Find mean intensity (in original image!)
meanGL2008a = blobMeasurements(k).MeanIntensity;
% Mean again, but only for version >= R2008a
blobArea = blobMeasurements(k).Area; % Get area.
TS NGUYỄN ĐỨC THÀNH 164
BLOB COUNTING MATLAB
blobPerimeter = blobMeasurements(k).Perimeter; % Get perimeter.
% Get centroid one at a time
blobCentroid = blobMeasurements(k).Centroid;
% Compute ECD - Equivalent Circular Diameter.
blobECD(k) = sqrt(4 * blobArea / pi);
fprintf(1,'#%2d %17.1f %11.1f %8.1f %8.1f %8.1f % 8.1f\n', k,
meanGL, blobArea, blobPerimeter, blobCentroid, blobECD(k));
% Put the "blob number" labels on the "boundaries" grayscale image.
text(blobCentroid(1) + labelShiftX, blobCentroid(2), num2str(k),
'FontSize', 8, 'FontWeight', 'Normal');
end

TS NGUYỄN ĐỨC THÀNH 165


BLOB COUNTING MATLAB
% We can get the centroids of all the blobs into 2 arrays,
% one for the centroid x values and one for the centroid y values.
allBlobCentroids = [blobMeasurements.Centroid];
centroidsX = allBlobCentroids(1:2:end-1);
centroidsY = allBlobCentroids(2:2:end);
% Put the labels on the rgb labeled image and the original image
subplot(3, 3, 4);
for k = 1 : numberOfBlobs % Loop through all blobs.
text(centroidsX(k) + labelShiftX, centroidsY(k), num2str(k),
'FontSize', 8, 'FontWeight', 'Normal'); end
subplot(3, 3, 1);
for k = 1 : numberOfBlobs text(centroidsX(k) + labelShiftX,
centroidsY(k), num2str(k), 'FontSize', 8, 'FontWeight', 'Normal');end
TS NGUYỄN ĐỨC THÀNH 166
BLOB COUNTING MATLAB

TS NGUYỄN ĐỨC THÀNH 167


GRAIN COUNTING
close all; clc;
subplot(2,3,1);
img = imread('rice.png');
imshow(img);
bg = imopen(img, ones(30, 30));
subplot(2,3,6);imshow(bg);
img2 = img - bg;
subplot(2,3,2);
imshow(img2);
subplot(2,3,3);
histogram(img2);
% image binarisation, and remove particles touching border
bin = img2 > 50;
TS NGUYỄN ĐỨC THÀNH 168
GRAIN COUNTING
bin = imclearborder(bin, 4);
subplot(2,3,4);
imshow(bin);
% compute image labels, using minimal connectivity
lbl = bwlabel(bin, 4);
NumberofRice = max(lbl(:))
% display label image
rgb = label2rgb(lbl, jet(nLabels), 'w', 'shuffle');
subplot(2,3,5);
str=['Quantity of grain: ' num2str(NumberofRice)];
rgb=insertText(rgb,[20 50],str);
imshow(rgb);
TS NGUYỄN ĐỨC THÀNH 169
OPENCV TÌM CÁC ĐỐM
connectedComponentsWithStats

TS NGUYỄN ĐỨC THÀNH 170


TS NGUYỄN ĐỨC THÀNH 171
GRAIN COUNTING

TS NGUYỄN ĐỨC THÀNH 172


Segmentation Using K-Means Clustering
Clustering is a way to separate
groups of objects. K-means
clustering treats each object as
having a location in space. It finds
partitions such that objects within
each cluster are as close to each
other as possible, and as far from
objects in other clusters as possible.
K-means clustering requires that
you specify the number of clusters
to be partitioned and a distance
metric to quantify how close two
objects are to each other.
TS NGUYỄN ĐỨC THÀNH 173
Segmentation Using K-Means Clustering

k-means clustering is an iterative, data-partitioning algorithm that


assigns n observations to exactly one of k clusters defined by
centroids, where k is chosen before the algorithm starts.
The algorithm proceeds as follows:
1/Choose k initial cluster centers (centroid). For example,
choose k observations at random (by using 'Start','sample') or use
the k-means ++ algorithm for cluster center initialization (the
default).
2/Compute point-to-cluster-centroid distances of all
observations to each centroid.
3/There are two ways to proceed (specified by OnlinePhase):

TS NGUYỄN ĐỨC THÀNH 174


Segmentation Using K-Means Clustering

Batch update — Assign each observation to the cluster


with the closest centroid.
Online update — Individually assign observations to a
different centroid if the reassignment decreases the sum of the
within-cluster, sum-of-squares point-to-cluster-centroid distances.
4/Compute the average of the observations in each cluster to
obtain k new centroid locations.
5/Repeat steps 2 through 4 until cluster assignments do not
change, or the maximum number of iterations is reached.

TS NGUYỄN ĐỨC THÀNH 175


Segmentation Using K-Means Clustering

TS NGUYỄN ĐỨC THÀNH 176


Segmentation Using K-Means Clustering
Matlab
idx = kmeans(X,k) performs k-means clustering to partition the
observations of the n-by-p data matrix X into k clusters, and
returns an n-by-1 vector (idx) containing cluster indices of each
observation. Rows of X correspond to points and columns
correspond to variables.

TS NGUYỄN ĐỨC THÀNH 177


Segmentation Using K-Means Clustering
Matlab
• idx — Cluster indices, returned as a numeric column vector. idx
has as many rows as X, and each row indicates the cluster
assignment of the corresponding observation.
• C — Cluster centroid locations, returned as a numeric matrix. C
is a k-by-p matrix, where row j is the centroid of cluster j.
• X — Data, specified as a numeric matrix. The rows of X
correspond to observations, and the columns correspond to
variables. If X is a numeric vector, then kmeans treats it as an n-
by-1 data matrix, regardless of its orientation.
• k — Number of clusters in the data, specified as a positive
integer.
• Name-Value Pair Arguments Specify optional comma-separated
pairs of Name,Value arguments. Name is the argument name and
Value is the corresponding value. Name must appear inside
quotes. TS NGUYỄN ĐỨC THÀNH 178
Segmentation Using K-Means Clustering
Matlab
• Example: Distance', 'cosine', 'Replicates', 10, 'Options',
statset('UseParallel',1) specifies the cosine distance, 10
replicate clusters at different starting values, and to use parallel
computing.
• 'Replicates' — Number of times to repeat clustering using new
initial cluster centroid positions
• 'Start' — Method for choosing initial cluster centroid positions
specified as the comma-separated pair consisting of 'Start' and
'cluster', 'plus', 'sample', 'uniform', a numeric matrix, or a
numeric array.

TS NGUYỄN ĐỨC THÀNH 179


K means Example Matlab
%Partition Data into Two Clusters, Randomly generate 200 sample 2D
data. X: 200*2 data matrix
rng default; % For reproducibility
X = [randn(100,2)*0.75+ones(100,2); randn(100,2)*0.5-ones(100,2)];
figure;
plot(X(:,1),X(:,2),'.');
title 'Randomly Generated Data';
%Partition the data into two clusters, and choose the best arrangement
%out of five initializations. Display the final output.
opts = statset('Display','final');
[idx,C] = kmeans(X,2,'Distance','cityblock',…
'Replicates',5,'Options',opts)

TS NGUYỄN ĐỨC THÀNH 180


K means Example Matlab
figure;
plot(X(idx==1,1),X(idx==1,2),'r.','MarkerSize',12)
hold on
plot(X(idx==2,1),X(idx==2,2),'b.','MarkerSize',12)
plot(C(:,1),C(:,2),'kx', 'MarkerSize',15,'LineWidth',3)
legend('Cluster 1','Cluster 2','Centroids', 'Location','NW')
title 'Cluster Assignments and Centroids'
hold off

TS NGUYỄN ĐỨC THÀNH 181


K means Example Matlab

TS NGUYỄN ĐỨC THÀNH 182


Segmentation Using K-Means Clustering
C

TS NGUYỄN ĐỨC THÀNH 183


Segmentation Using K-Means Clustering
C

TS NGUYỄN ĐỨC THÀNH 184


Segmentation Using K-Means Clustering
C

TS NGUYỄN ĐỨC THÀNH 185


Segmentation Using K-Means Clustering
C

TS NGUYỄN ĐỨC THÀNH 186

You might also like