Professional Documents
Culture Documents
BTL số 1 Nhóm 1
BTL số 1 Nhóm 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1
1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1
1
Câu a) Tìm các blob bằng tay (tọa độ, góc, chu vi, diện tích) và lập trình tìm blob sử dụng hu-moment
❖ Tính tay
𝑚𝑘𝑙 = ∑ ∑ 𝑖 𝑘 𝑗 𝑙 𝐴𝑖,𝑗
𝑖 𝑗
Hình 1:
𝑚00 = ∑ ∑ 𝑖 0 𝑗 0 𝐴𝑖,𝑗 = 32
𝑖 𝑗
Suy ra:
𝑚11 392
𝑚′11 = −𝑥1 𝑦1 = − 3,5 × 3,5 = 0
𝑚00 32
𝑚20 496
𝑚′20 = − 𝑦12 = − 3,5 × 3,5 = 3,25
𝑚00 32
𝑚02 496
𝑚′02 = − 𝑥12 = − 3,5 × 3,5 = 3,25
𝑚00 32
1 2𝑚′11 1 0
θ= arctan( ) = arctan( ) = 0°
2 𝑚′20 − 𝑚′02 2 0
Chu vi và diện tích hình 1:
Perimeter = 4 × 1 + 16 × 1 = 20
3
Area = 5 × 5 − (8 × + 4) = 18
8
Hình 2:
𝑚00 = ∑ ∑ 𝑖 0 𝑗 0 𝐴𝑖,𝑗 = 39
𝑖 𝑗
Suy ra:
𝑚11 1948
𝑚′11 = −𝑥1 𝑦2 = − 12,49 × 4 = 0
𝑚00 39
𝑚20 748
𝑚′20 = − 𝑦22 = − 4 × 4 = 3,18
𝑚00 39
𝑚02 6287
𝑚′02 = − 𝑥12 = − 12,49 × 12,49 = 5,28
𝑚00 39
1 2𝑚′11 1 0
θ= arctan( )= arctan( ) = 0°
2 𝑚′20 − 𝑚′02 2 3,18 − 5,28
Chu vi và diện tích hình 2:
Perimeter = 9 × 1 + 6 × (1 + √2)/2 + 5 ×× √2 = 23.31
1 1 5 3 1 5 3 1
Area = 25 + 3 × + 11 × + 2 × + 4 × − (6 + 4 × + 2 × + 2 × + 2 × ) = 24
4 2 8 8 4 8 8 2
Hình 3:
𝑚00 = ∑ ∑ 𝑖 0 𝑗 0 𝐴𝑖,𝑗 = 36
𝑖 𝑗
Suy ra:
𝑚11 1449
𝑚′11 = −𝑥1 𝑦1 = − 3,5 × 11,5 = 0
𝑚00 36
𝑚20 4954
𝑚′20 = − 𝑦32 = − 11,52 = 5,36
𝑚00 36
𝑚02 634
𝑚′02 = − 𝑥32 = − 3,52 = 5,36
𝑚00 36
1 2𝑚′11 1 0
θ= arctan( )= arctan( ) = 0°
2 𝑚′20 − 𝑚′02 2 5,36 − 5,36
Chu vi và diện tích hình 3:
Perimeter = 8 × 1 + 8 × (1 + √2)/2 + 4 × √2 = 23.31
1 3 3 1
Area = 32 + 12 × +8× − (16 + 8 × + 8 × ) = 18
2 8 8 2
Hình 4:
𝑚00 = ∑ ∑ 𝑖 0 𝑗 0 𝐴𝑖,𝑗 = 21
𝑖 𝑗
Suy ra:
𝑚11 2820
𝑚′11 = −𝑥4 𝑦4 = − 11,19 × 12 = 0
𝑚00 21
𝑚20 3122
𝑚′20 = − 𝑦42 = − 122 = 4,67
𝑚00 21
𝑚02 2663
𝑚′02 = − 𝑥42 = − 11,192 = 1,58
𝑚00 21
1 2𝑚′11 1 0
θ= arctan( )= arctan( ) = 0°
2 𝑚′20 − 𝑚′02 2 4,67 − 1,58
Chu vi và diện tích hình 3:
❖ Lập trình
Ta tiến hành lập trình theo trình tự như giải thuật tính tay, khai báo ma trận đầu vào, sử dụng hàm conectedComponents
gán nhãn cho từng vùng trong ảnh.
float scr_array[18 * 17] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,0,0,0,0,0,1,1,1,0,0,0,
0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,
0,1,1,0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,
0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,1,1,1,
0,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,0,
0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,
0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,
1,1,0,0,0,0,1,1,0,0,1,1,1,0,0,0,0,0,
1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,0,0,0,
1,1,0,0,0,0,1,1,0,0,1,0,0,1,1,0,0,0,
1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,0,0,0,
0,1,1,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,
0,0,1,1,1,1,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
};
scr.convertTo(scr, CV_8U);
label.convertTo(label, CV_8U);
Tiếp theo, ta tiến hành tìm các đường bao của hình bằng hàm findContours, sử dụng tham số mode là RETR_TREE
để lấy tất cả các đường biên và tạo phân cấp của các đường lồng nhau, sau đó trích xuất các đường biên trong và ngoài
out_contours.push_back(contours[i]);
in_contours.push_back(contours[i]);
Tiến hành tìm các moment để tính toán trọng tâm bao gồm m0,0 , m0,1 , m1,0 để tính toán trọng tâm, vì các hình ảnh
đều có tính đối xứng, tức là tâm của các đường biên trong cùng 1 ảnh trùng nhau, do đó, ta chỉ cần moment của đường biên
ngoài cùng để tìm trọng tâm.
vector<Moments> mu_out(out_contours.size());
vector<Moments> mu_in(in_contours.size());
if (label.at<uchar>(Point(i, j)) == 1)
area[0]++;
area[1]++;
area[2]++;
{
area[3]++;
Sau khi tính được các moment, tìm trọng tâm và hướng của vật
Có thể sử dụng hàm arcLength để tìm chu vi thông qua các contour biên ngoài cùng
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <math.h>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
float scr_array[18 * 17] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,0,0,0,0,0,1,1,1,0,0,0,
0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,
0,1,1,0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,
0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,1,1,1,
0,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,0,
0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,
0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,
1,1,0,0,0,0,1,1,0,0,1,1,1,0,0,0,0,0,
1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,0,0,0,
1,1,0,0,0,0,1,1,0,0,1,0,0,1,1,0,0,0,
1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,0,0,0,
0,1,1,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,
0,0,1,1,1,1,0,0,0,0,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
};
Mat scr = Mat(17, 18, CV_32F, scr_array);
scr.convertTo(scr, CV_8U);
threshold(scr, scr, 0, 255, THRESH_BINARY);
Mat label = Mat::zeros(17, 18,CV_8U);
//cout << scr;
//label các blob
connectedComponents(scr, label, 4, 4); // chọn connective = 4
label.convertTo(label, CV_8U);
cout << "Ket qua sau khi label" << endl << label<<endl;
// tìm contours của ảnh
vector <vector<Point>> contours;
vector <vector<Point>> out_contours;
vector <vector<Point>> in_contours;
vector <Vec4i> hierarchy;
Mat drawing = Mat::zeros(scr.size(),CV_8U);
findContours(scr, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0,
0));
// Hàm contours trả về kết quả contour từ cuối mảng lên đầu mảng, reverse lại cho đúng thứ
tự
reverse(contours.begin(), contours.end()); //Các contours ngoài cùng là contour số lẻ 1,3,5,7
// Trích xuất các contour nằm ngoài cùng
for (int i = 1; i < contours.size(); i+=2)
{
out_contours.push_back(contours[i]);
}
// Trích xuất các contour bên trong
for (int i = 0; i < contours.size(); i += 2)
{
in_contours.push_back(contours[i]);
}
for (int i = 0; i < out_contours.size(); i++)
{
cout << out_contours[i] << endl;
}
// Tìm momen các contour ngoài cùng
vector<Moments> mu_out(out_contours.size());
vector<Moments> mu_in(in_contours.size());
for (int i = 0; i < out_contours.size(); i++)
{
mu_out[i] = moments(out_contours[i], false);
}
// Tìm momen các contour bên trong
for (int i = 0; i < in_contours.size(); i++)
{
mu_in[i] = moments(in_contours[i], false);
}
//Tọa độ tâm và góc
double theta[4]; // mảng chứa 4 giá trị theta
double perimeter[4]; // mảng chứa chu vi
double area[4] = { 0, 0, 0, 0 }; //mảng chứa giá trị diện tích tìm theo cách đếm label
double area_func[4] = { 0,0,0,0 }; // mảng chứa giá trị diện tích tìm theo m00
double u11, u20, u02;
vector<Point2f>mc(mu_out.size());
// Diện tích tìm bằng cách đếm ô
for (int i = 0; i < label.cols; i++)
{
for (int j = 0; j < label.rows; j++)
{
if (label.at<uchar>(Point(i, j)) == 1)
{
area[0]++;
}
else if (label.at<uchar>(Point(i, j)) == 2)
{
area[1]++;
}
else if (label.at<uchar>(Point(i, j)) == 3)
{
area[2]++;
}
else if (label.at<uchar>(Point(i, j)) == 4)
{
area[3]++;
}
}
}
// Diện tích tính theo tọa độ
for (int i = 0; i < in_contours.size(); i++)
{
area_func[i] = mu_out[i].m00 - mu_in[i].m00;
}
for (int i = 0; i < out_contours.size(); i++)
{
// tính trọng tâm
mc[i] = Point2f(mu_out[i].m10 / mu_out[i].m00, mu_out[i].m01 / mu_out[i].m00);
cout << endl << "toa do tam hinh " << i + 1 << " " << mc[i] << endl;
// tính góc
u11 = (mu_out[i].m11 / mu_out[i].m00) - (mu_out[i].m10 / mu_out[i].m00) *
(mu_out[i].m01 / mu_out[i].m00);
u20 = (mu_out[i].m20 / mu_out[i].m00) - (mu_out[i].m10 / mu_out[i].m00) *
(mu_out[i].m10 / mu_out[i].m00);
u02 = (mu_out[i].m02 / mu_out[i].m00) - (mu_out[i].m01 / mu_out[i].m00) *
(mu_out[i].m01 / mu_out[i].m00);
if (u20 == u02) // xử lí trường hợp 0/0
{
u20 += 1e-8;
}
theta[i] = 0.5 * atan(2 * u11 / (u20 - u02));
theta[i] = theta[i] * 180 / CV_PI;
cout << "goc hinh " << i + 1 << ": " << theta[i] << " do" << endl;
perimeter[i] = arcLength(out_contours[i], true);
cout << "chu vi hinh " << i + 1 << ": " << perimeter[i] << endl;
cout << "dien tich tinh theo cach dem pixel hinh " << i + 1 << ": " << area[i] << endl;
cout << "dien tich tinh theo toa do hinh " << i + 1 << ": " << area_func[i] << endl;
}
}
Câu b) Thining bằng tay và lập trình, output kết quả từng bước
❖ Tính tay
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1
1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1
1
-1 -1 -1 -1 -1 1 -1 1 1 1 1 1 1 1 -1 1
1 1 1 -1 1 1 -1 1 1 -1 1 -1 1 1 -1 1 1
1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1
𝐵1 𝐵2 𝐵3 𝐵4 𝐵5 𝐵6 𝐵7
𝐴 ⊛ 𝐵1
-1 -1 -1
1
1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1
1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1
1
Ta có kết quả trả về ở lần trượt thứ nhất là 0. Do đó ma trận result là:
0
Ở lượt trượt thứ hai, tương tự như lần đầu.
Ta có kết quả trả về giống như ở lần trượt thứ nhất là 0. Do đó ma trận result là:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Trượt ở các vị trí đặc biệt:
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1
1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1
1
Ta có kết quả trả về là 1, do đó ma trận result là:
1
Làm tương tự cho đến hết ma trận
Ta được kết quả 𝐴 ⊛ 𝐵1
1 1 1 1 1 1 1
1
1 1 1 1
1 1
𝐴1 = 𝐴 ⊗ 𝐵1 = 𝐴 − (𝐴 ⊛ 𝐵1 ):
1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1
1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1
1
𝐴1 ⊛ 𝐵2
-1 -1
1 1 -1
1 1
1
1
1
1
𝐴2 = 𝐴1 ⊗ 𝐵2 = 𝐴1 − ( 𝐴1 ⊛ 𝐵2 ) :
1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1
1
1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1
1
𝐴2 ⊛ 𝐵3
1 -1
1 1 -1
1 -1
1
1
1
1 1
1 1
1
𝐴3 = 𝐴2 ⊗ 𝐵3 = 𝐴2 − (𝐴2 ⊛ 𝐵3 ) :
1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1
1
1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1
1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1
1
𝐴3 ⊛ 𝐵4
1 1
1 1 -1
-1 -1
1
1
1
1
𝐴4 = 𝐴3 ⊗ 𝐵4 = 𝐴3 − (𝐴3 ⊛ 𝐵4 ) :
1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1
1
1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1
1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1
1
𝐴4 ⊛ 𝐵5
1 1 1
1
-1 -1 -1
Cho kernel 𝐵5 trượt trên 𝐴4 , ta được kết quả 𝐴4 ⊛ 𝐵5
1 1 1
1 1
𝐴5 = 𝐴4 ⊗ 𝐵5 = 𝐴4 − (𝐴4 ⊛ 𝐵5 ) :
1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1
1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1
1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1
1
𝐴5 ⊛ 𝐵6
1 1
-1 1 1
-1 -1
1
𝐴6 = 𝐴5 ⊗ 𝐵6 = 𝐴5 − (𝐴5 ⊛ 𝐵6 ) :
1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1
1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1
1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1
1
𝐴6 ⊛ 𝐵7
-1 1
-1 1 1
-1 1
1
1 1
1
𝐴7 = 𝐴6 ⊗ 𝐵7 = 𝐴6 − (𝐴6 ⊛ 𝐵7 ) , ta được kết quả cuối cùng:
1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1
1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1
1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1
1
❖ Lâp trình
src.convertTo(src, CV_8U);
threshold(src, src, 0, 255, THRESH_BINARY);
cout << "input image: " << endl << src << endl;
namedWindow("src", WINDOW_NORMAL);
imshow("src", src*255);
Kết quả được xuất ra:
Ma trận ban đầu sau khi phân ngưỡng Binary image before thining
Sau đó lấy SRC- DST để thu được ma trận Ai, tiếp tục thực hiện thao tác dùng hàm và trừ hai ma trận để thu được
kết quả Thining:
Image after thining with kernel B1 Image after thining with kernel B2
Image after thining with kernel B3 Image after thining with kernel B4
Source code:
#include<opencv2/opencv.hpp>
#include<iostream>
int main() {
Mat dst;
src.convertTo(src, CV_8U);
threshold(src, src, 0, 255, THRESH_BINARY);
cout << "input image: " << endl << src << endl;
namedWindow("src", WINDOW_NORMAL);
imshow("src", src*255);
namedWindow("dst", WINDOW_NORMAL);
imshow("dst", src * 255);
cout << "Image after thinning in final: " << endl << src << endl;
waitKey(0);
}
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1
1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1
1
Tiến hành thêm padding 0 cho ma trận ban đầu để tính toán:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0
0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 0
0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 1 0 0
0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 1 1 1 0
0 0 1 1 1 1 1 1 0 0 1 1 1 1 0 1 1 1 0 0
0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 1 1 0 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Trong đó:
A: ma trận điểm ảnh của ảnh nhị phân
B: phần tử cấu trúc (structuring element)
Ta sẽ sử dụng kernel B sau để tiến hành skeleton:
x 1 x
1 1 1
x 1 x
Erode: Lần lượt so sánh tại các vị trí có giá trị bằng 1 của kernel B. Nếu giống nhau hoàn toàn thì giá trị trả về là 1. Ngược
lại là 0\
Nhận xét: Các vị trí có giá trị 1 tại vị trí đang xét trong ma trận A không trùng khớp với kernel B.
Ta có kết quả trả về ở lần trượt thứ nhất là 0. Do đó ma trận result là:
0
Tại vị trí (0,1) ta có:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0
0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 0
0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 1 0 0
0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 1 1 1 0
0 0 1 1 1 1 1 1 0 0 1 1 1 1 0 1 1 1 0 0
0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 1 1 0 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Ta có kết quả trả về ở lần trượt thứ hai là 0. Do đó ma trận result là:
0 0
Ta trượt ở các vị trí đặc biệt:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0
0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 0
0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 1 0 0
0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 1 1 1 0
0 0 1 1 1 1 1 1 0 0 1 1 1 1 0 1 1 1 0 0
0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 1 1 0 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 0 0 0 0
0 1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Nhận xét: Các vị trí có giá trị 1 tại vị trí kernel B hoàn toàn trùng khớp với vị trí đang xét trong ma trận A.
Suy ra kết quả trả về là 1. Do đó ma trận result là:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1
Trượt lần lượt kernel B đến hết ma trận A ta thu được ma trận result là:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Nhận xét: Các vị trí có giá trị 1 tại vị trí kernel B không trùng khớp với bất kì vị trí nào đang xét trong ma trận đã eroded.
Ta có kết quả trả về ở lần trượt thứ nhất là 0. Do đó ma trận result là:
0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Nhận xét: Ở lượt trượt thứ hai, tương tự như lần đầu.
Ta có kết quả trả về ở lần trượt thứ nhất là 0. Do đó ma trận result là:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Tiếp tục trượt lần lượt đến hết ma trận eroded ta được:
Trượt lần lượt đến hết ma trận eroded, ta thu được ma trận Result cuối cùng là:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0
0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0
0 0 1 0 0 1 0 0 0 1 1 1 1 0 1 1 1 0
0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 0 1 1 1 0
0 0 1 0 0 1 0 0 0 0 1 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Bước 3: Lấy ma trận ban đầu trừ đi ma trận dilated:
Kết quả sau khi subtract:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 1 1 0 1 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 1 1 0 1 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0
1 1 0 0 0 0 1 1 0 1 1 1 0 0 0 0 0 0
1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 0 0
1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 0 0 0
1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 0 0
0 1 1 1 1 1 1 0 0 1 1 1 0 0 0 0 0 0
0 0 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
Vì đây là lần thực hiện đầu tiên nên ma trận subtract cũng là ma trận skeleton.
Gán giá trị thu được ở ma trận subtract ngược lại cho ma trận src để thực hiện tiếp lần 2.
2) Thực hiện lần 2:
Erode ma trận đã src (ma trận eroded ở lần thực hiện thứ nhất) :
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Nhận xét: Có thể dễ dàng nhận ra được răng không có vị trí nào thỏa để erode xuất hiện giá trị 1. Do đó ma trận
eroded2 như sau:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Vì không hề có giá trị 1 nào xuất hiện trong ma trận vì thể ma trận dilated cũng là ma trận 0.
Tiến hành lấy ma trận eroded trừ cho ma trận dilated ta ra được ma trận subtract2:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Cuối cùng ta sẽ tổng hợp ma trận skeleton ở lần thực hiện đầu và ma trận subtract2 sẽ thu được ma trận skeleton2:
Kết quả thu được cho ma trận skeleton2:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 1 1 0 1 0 0 0 0 0 0 1 0 0 0 0
0 0 1 0 0 1 0 0 0 1 0 0 1 0 1 0 0 0
0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0
0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0
0 1 0 1 1 0 1 0 0 1 0 0 1 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0
1 1 0 0 0 0 1 1 0 1 1 1 0 0 0 0 0 0
1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 0 0
1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 0 0 0
1 1 0 0 0 0 1 1 0 1 0 1 1 0 0 0 0 0
0 1 1 1 1 1 1 0 0 1 1 1 0 0 0 0 0 0
0 0 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
Nhận xét: ở hình 1 và 2 cơ bản đã thu được ảnh đẹp và hợp lí sau khi skeleton nhưng hình 3 và 4 vẫn giữ nguyên vì
thế tiến hành dùng những kernel khác để skeleton.
Vì về cơ bản 2 hình đầu tiên đã cho ra hình ảnh hợp lí rồi nên bây giờ chỉ tập trung detect 2 hình còn lại.
Ta dùng các kernel sau cho hình thứ 3 :
Kernel B1:
0 1 0
1 1 0
0 1 0
Kernel B2
0 1 0
0 1 1
0 1 0
Kernel B3
0 1 0
1 1 1
0 0 0
Kernel B4
0 0 0
1 1 1
0 1 0
Thực hiện skeleton bằng lần lượt từng kernel trên với ma trận ban đầu ta thu được các kết quả skeleton như sau:
Skeleton Kernel B1:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 1 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 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 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 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 1 1 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 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 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 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 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 1 1 0 0 0 0 1 1 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 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 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 1 1 0 0 0 0 1 1 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 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 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 0 0 0 0 0 0 0 0
Ý tưởng : ta sẽ lọc lấy những vị trí điểm nào không hề trùng khớp nhau giữa từng cặp ma trận ( 1,2 và 3,4) , thực
hiện tương tự như lệnh bitwise_xor . Sau đó ta sẽ dùng ma trận hình 3 ban đầu để trừ đi những vị trí điểm lọc được
này.
Bitwise_or cặp ma trận đầu , ta thu được ma trận sau:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Sau khi lấy hình ban đầu trừ đi:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 1 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 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 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 0 0 0 0 0 0 0 0
Làm tương tự cho cặp ma trận còn lại, ta được:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 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 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 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 1 1 0 0 0 0 1 1 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 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Cuối cùng , giao 2 ma trận lại ta được ma trận Result cuối cùng:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 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 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 1 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 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0
1 1 1
0 0 0
Kernel B42
0 0 0
1 1 1
0 1 0
Ta thu được ma trận Result là:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
❖ Lập trình
Ma trận hình ban đầu sau khi phân ngưỡng:
Structuring element:
Hình 1:
Hình 2:
Hình 3:
Hình 4:
Sau khi skeleton hình 3 bẳng các kernel kể trên phần tính tay ta sẽ dùng các lệnh sau để tiến hành tổng hợp hình lại :
bitwise_xor(skelB1, skelB2, skelB5);
subtract(edge34, skelB5, skelB5);
bitwise_xor(skelB3, skelB4, skelB6);
subtract(edge34, skelB6, skelB6);
bitwise_and(skelB5, skelB6, skel1);
Hình 4 làm tương tự nhưng chỉ với 2 kernel:
bitwise_xor(skelB41, skelB42, skelB43);
subtract(edge43, skelB43, skelB43);
bitwise_or(skelB43, skel1, skel);
Code Hình 3 và 4:
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>