Professional Documents
Culture Documents
0 0 0 0 0 0 0
0 2 4 5 0 0 0
0 6 0 7 8 0 0
3 5 9 0 10 12 0
4 6 0 0 0 8 0
5 7 0 0 3 8 0
0 9 2 14 3 0 0
Matrix (b)
a) Reconstruct lại hình sử dụng 3 và 5 eigen value lớn nhất bằng tay , so sánh sự khác
biệt (2đ)
b) Lập trình Reconstruct lại hình sử dụng 3 và 5 eigen value lớn nhất sử dụng hàm
opencv (1.5đ)
Bài làm
a. Reconstruct lại hình sử dụng 3 và 5 eigen value lớn nhất bằng tay
Bước 1: Tính kỳ vọng của dữ liệu theo hàng
N
1
x= ∑x
N n=1 n
Tại hàng 1
1
x 1= ( 0 ×7 )=0
7
Tại hàng 2
1
x 2= ( 2+ 4+5+ 4 × 0 )=1,5714
7
Tại hàng 3
1
x 3= ( 6+ 7+8+0 × 4 )=3
7
Tại hàng 4
1
x 4 = ( 3+5+9+10+ 12+ 0× 2 )=5,5714
7
1
Tại hàng 5
1
x 5= ( 4+6+ 8+0 × 4 ) =2,5714
7
Tại hàng 6
1
x 6= ( 5+7 +3+8+0 × 3 )=3,2857
7
Tại hàng 7
1
x 7= ( 9+ 2+ 14+3+ 0× 3 )=4
7
x
0 0 0 0 0 0 0 0
0 2 4 5 0 0 0 1,5714
0 6 0 7 8 0 0 3
3 5 9 0 10 12 0 5,5714
4 6 0 0 0 8 0 2,5714
5 7 0 0 3 8 0 3,2857
0 9 2 14 3 0 0 4
Bước 2: Trừ mỗi điểm của dữ liệu với vector kỳ vọng x , ta được A
x n=x n−x
^
2
0 0 0 0 0 0 0
-1,5714 0,4286 2,4286 3,4286 -1,5714 -1,5714 -1,5714
-3 3 -3 4 5 -3 -3
-2,5714 -0.5714 3,4286 -5,5714 4,4286 6,4286 -5,5714
1,4286 3,4286 -2,5714 -2,5714 -2,5714 5,4286 -2,5714
1,7143 3,7143 -3,2857 -3,2857 -0,2857 4,7143 -3,2857
-4 5 -2 10 -1 -4 -4
3
0 0 0 0 0 0 0
0 27.7142 14 -15.2857 -16.2857 -22.1428 52
0 14 86 -7 -18 -3 92
0 -15.2857 -7 141.714 37.7142 47.8571 -63
2
0 -16.2857 -18 37.7142 69.7142 66.8571 -18
0 -22.1428 -3 47.8571 66.8571 71.4285 -20
0 52 92 -63 -18 -20 178
Eigen Value
297.108
6
156,213
4
84,6468
35,673
4
5
0,9128
0,016
5
0
Uk 3 Uk 5
0 0 0 0 0 0 0 0
0,2154 0,0284 -0,1218 0,2154 0,0284 -0,1218 -0,5840 -0,6381
0,3577 0,4057 -0,2843 0,3577 0,4057 -0,2843 0,6575 -0.1189
-0,4601 0,5001 -0,6659 -0,4601 0,5001 -0,6659 -0,2477 0,1443
-0,2514 0,4058 0,5319 -0,2514 0,4058 0,5319 -0,1778 0,3774
-0,2596 0,4771 0,4123 -0,2596 0,4771 0,4123 0,1792 -0,5838
0,6953 0,4383 0,0896 0,6953 0,4383 0,0896 -0,3186 0,2729
Bước 5:
Với 3 vector lớn nhất: Z3 =U Tk 3 × A
5
-3,1835 3,0785 -2,0186 13,1847 -0,5626 -9,7389 -0,1297
-2,9034 6,2988 -2,9214 0,7060 2,5804 4,6523 -8,4127
3,8651 3,2781 -4,6275 0,3282 -5,7541 1,2364 1,6738
0,9099 0,3271 -3,7349 -1,3098 3,8326 -1,4929 1,4679
-0,5646 -0,2224 -0,2964 0,2096 -0,0301 0,4922 0,4118
0 0 0 0 0 0 0
0,1964 2,0143 1,6173 4,3919 2,2246 -0,5449 1,1003
-0,6408 5,7245 2,4008 7,9087 5,4817 1,0527 -0,9354
3,0034 5,1221 8,1207 -0,3607 10,9524 11,5558 0,3093
4,4075 6,0973 -0,5679 -0,2821 0,6999 7,5654 0,0804
4,4839 6,8436 0,5078 0,3557 2,2904 8,5430 -0,0044
0,4222 9,1949 0,9016 13,5056 4,2245 -0,6211 0,3722
0 0 0 0 0 0 0
0,0253 1,9652 3,9877 5,0231 0,0054 0,0129 -0,0197
0,0246
7 5,9661 -0,0120 7,0256 8,0053 0,0126 -0,0192
2,9935 5,0089 9,0031 -0,0059 9,9985 11,996 0,0051
6
7
4,0326 5,9552 -0,0159 0,0298 0,0070 8,0167 -0,0254
4,9766 7,0321 0,0114 -0,0214 2,9949 7,9881 0,0182
-0,0218 9,0299 2,0106 13,9800 2,9953 -0,0111 0,0169
Threshold với T = 2
Với 3 vector lớn nhất
0 0 0 0 0 0 0
0 255 0 255 255 0 0
0 255 255 255 255 0 0
255 255 255 0 255 255 0
255 255 0 0 0 255 0
255 255 0 0 255 255 0
0 255 0 255 255 0 0
b. Lập trình Reconstruct lại hình sử dụng 3 và 5 eigen value lớn nhất sử dụng hàm
opencv
7
Code:
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
//khai báo ma trận đầu vào
Mat src = (Mat_<float>(7, 7) <<
0, 0, 0, 0, 0, 0, 0,
0, 2, 4, 5, 0, 0, 0,
0, 6, 0, 7, 8, 0, 0,
3, 5, 9, 0, 10, 12, 0,
4, 6, 0, 0, 0, 8, 0,
5, 7, 0, 0, 3, 8, 0,
0, 9, 2, 14, 3, 0, 0);
cout << "Ma tran dau vao\n" << src << endl;
//B1: Tính kỳ vọng của dữ liệu theo hàng
Mat mean = Mat::zeros(src.rows, 1, CV_32F);
for (int i = 0; i < src.rows; i++)
{
float x = 0;
for (int j = 0; j < src.cols; j++)
{
x += src.at<float>(i, j);
}
mean.at<float>(i, 0) = x / src.cols;
}
cout << "Vector ky vong x\n" << mean << endl;
//B2: Trừ mỗi điểm của dữ liệu với vector kỳ vọng, ta được A
Mat A = Mat::zeros(src.rows, src.cols, CV_32F);
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
A.at<float>(i, j) = src.at<float>(i, j) - mean.at<float>(i, 0);
}
}
cout << "Ma tran A\n" << A << endl;
//Tìm ma trận chuyển vị của ma trận A
Mat AT = Mat::zeros(A.cols, A.rows, CV_32F);
for (int i = 0; i < A.rows; i++)
{
for (int j = 0; j < A.cols; j++)
{
AT.at<float>(i, j) = A.at<float>(j, i);
}
}
//B3: Tính ma trận Covariance S
Mat S = Mat::zeros(A.rows, AT.cols, CV_32F);
S = A * AT;
cout << "Ma tran Covarience S\n" << S << endl;
//B4: Tìm eigen vector và eigen value
Mat eigenvalue, eigenvector;
eigen(S, eigenvalue, eigenvector);
cout << "eigenvalue\n"<< eigenvalue << endl;
cout << "eigenvetor\n" << eigenvector << endl;
8
//Chọn eigen vector (3 vector lớn nhất)
Mat Uk3 = Mat::zeros(eigenvector.rows, 3, CV_32F);
float max3_eigenvalue[] = { eigenvalue.at<float>(0, 0) , eigenvalue.at<float>(1, 0) , eigenvalue.at<float>(2,
0) };
int max3_ident[] = { 0, 1, 2 }; //Lưu ident của 3 eigenvalue lớn nhất
for (int i = 3; i < eigenvalue.rows; i++)
{
if (eigenvalue.at<float>(i, 0) > max3_eigenvalue[0])
{
max3_eigenvalue[0] = eigenvalue.at<float>(i, 0);
max3_ident[0] = i;
}
else if (eigenvalue.at<float>(i, 0) > max3_eigenvalue[1])
{
max3_eigenvalue[1] = eigenvalue.at<float>(i, 0);
max3_ident[1] = i;
}
else if (eigenvalue.at<float>(i, 0) > max3_eigenvalue[2])
{
max3_eigenvalue[2] = eigenvalue.at<float>(i, 0);
max3_ident[2] = i;
}
}
//Lưu Uk3
for (int i = 0; i < eigenvector.rows; i++)
{
for (int j = 0; j < eigenvector.cols; j++)
{
if (i == max3_ident[0])
Uk3.at<float>(j, 0) = eigenvector.at<float>(i, j);
else if (i == max3_ident[1])
Uk3.at<float>(j, 1) = eigenvector.at<float>(i, j);
else if (i == max3_ident[2])
Uk3.at<float>(j, 2) = eigenvector.at<float>(i, j);
}
}
cout << "Uk3\n" << Uk3 << endl;
//Chọn eigen vector (5 vector lớn nhất)
Mat Uk5 = Mat::zeros(eigenvector.rows, 5, CV_32F);
float max5_eigenvalue[] = { eigenvalue.at<float>(0, 0) , eigenvalue.at<float>(1, 0) , eigenvalue.at<float>(2,
0),eigenvalue.at<float>(3, 0), eigenvalue.at<float>(4, 0) };
int max5_ident[] = { 0, 1, 2, 3, 4 }; //Lưu ident của 5 eigenvalue lớn nhất
for (int i = 5; i < eigenvalue.rows; i++)
{
if (eigenvalue.at<float>(i, 0) > max5_eigenvalue[0])
{
max5_eigenvalue[0] = eigenvalue.at<float>(i, 0);
max5_ident[0] = i;
}
else if (eigenvalue.at<float>(i, 0) > max5_eigenvalue[1])
{
max5_eigenvalue[1] = eigenvalue.at<float>(i, 0);
max5_ident[1] = i;
}
else if (eigenvalue.at<float>(i, 0) > max5_eigenvalue[2])
{
max5_eigenvalue[2] = eigenvalue.at<float>(i, 0);
max5_ident[2] = i;
}
9
else if (eigenvalue.at<float>(i, 0) > max5_eigenvalue[3])
{
max5_eigenvalue[3] = eigenvalue.at<float>(i, 0);
max5_ident[3] = i;
}
else if (eigenvalue.at<float>(i, 0) > max5_eigenvalue[4])
{
max5_eigenvalue[4] = eigenvalue.at<float>(i, 0);
max5_ident[4] = i;
}
}
//Lưu Uk5
for (int i = 0; i < eigenvector.rows; i++)
{
for (int j = 0; j < eigenvector.cols; j++)
{
if (i == max5_ident[0])
Uk5.at<float>(j, 0) = eigenvector.at<float>(i, j);
else if (i == max5_ident[1])
Uk5.at<float>(j, 1) = eigenvector.at<float>(i, j);
else if (i == max5_ident[2])
Uk5.at<float>(j, 2) = eigenvector.at<float>(i, j);
else if (i == max5_ident[3])
Uk5.at<float>(j, 3) = eigenvector.at<float>(i, j);
else if (i == max5_ident[4])
Uk5.at<float>(j, 4) = eigenvector.at<float>(i, j);
}
}
cout << "Uk5\n" << Uk5 << endl;
//B5: Tính Z3, Z5
//Tính Uk3T, Uk5T
10
Mat UA5 = Mat::zeros(A.rows, A.cols, CV_32F);
UA5 = Uk5 * Z5;
Mat X3 = Mat::zeros(A.rows, A.cols, CV_32F);
Mat X5 = Mat::zeros(A.rows, A.cols, CV_32F);
for (int i = 0; i < A.rows; i++)
{
for (int j = 0; j < A.cols; j++)
{
X3.at<float>(i, j) = UA3.at<float>(i, j) + mean.at<float>(i, 0);
X5.at<float>(i, j) = UA5.at<float>(i, j) + mean.at<float>(i, 0);
}
}
cout << "Ma tran sau khi xap xi (voi 3 vector lon nhat)\n" << X3 << endl;
cout << "Ma tran sau khi xap xi (voi 5 vector lon nhat)\n" << X5 << endl;
Mat X5final, X3final;
//Chọn ngưỡng T = 2 cho cả 2 trường hợp
threshold(X5, X5final, 2, 255, THRESH_BINARY);
threshold(X3, X3final, 2, 255, THRESH_BINARY);
cout << "Ma tran sau khi phan nguong (voi 3 vector lon nhat)\n" << X3final << endl;
cout << "Ma tran sau khi phan nguong (voi 5 vector lon nhat)\n" << X5final << endl;
waitKey();
}
Kết quả
Kết quả Reconstruct bằng tay trùng với kết quả lập trình.
11
2. Cho hình sau:
2 3 3 7 6 1 3 5 6 8
8 2 3 4 9 2 4 5 4 6 2
4 0 0 0 10 6 7 8 5 7 3
5 0 0 0 6 3 5 9 1 12 8 2 7
8 0 0 0 10 0 5 7 9 9
6 7 8 4 6 4 6 8 3 6 7 2 4
5 7 3 8 1 10 13
9 2 14 3
Matrix (a) Matrix (b) matrix (c)
a) Sử dụng giải thuật PCA để training và nhận dạng template giống với hình nào nhất
bằng tay tương ứng với nhóm trên bài 1 (2đ)
0 2 3 3 7 6 0 a. 0 0 0 0 0 0 0 0 0 1 3 5 6 8
0 8 2 3 4 9 0 0 2 4 5 0 0 0 0 4 6 0 0 0 2
0 4 0 0 0 1 0 0 6 0 7 8 0 0 5 7 0 0 0 0 3
0 3 5 9 0 10 12 0 8 2 0 0 0 0 7
0 5 0 0 0 6 0 4 6 0 0 0 8 0 5 7 0 0 0 9 9
0 8 0 0 0 1 0 5 7 0 0 3 8 0 0 3 6 7 2 4 0
0 0 9 2 14 3 0 0 0 0 1 10 13 0 0
0 6 7 8 4 6 0 Giải thuật huấn luyện
0 0 0 0 0 0 0
Biểu diễn các ảnh dưới dạng vector Γ i
Γ1 Γ2 Γ3
0 0 0
0 0 0
0 0 5
0 3 8
0 4 5
0 5 0
0 0 0
12
2 0 0
8 2 4
4 6 7
5 5 2
8 6 7
6 7 3
0 9 0
2 0 0
… … …
0 0 7
0 0 9
0 0 0
0 0 0
Với ϕ i là vector sai số tương ứng với mỗi ảnh, khi đó:
ϕ 1=¿ 0,00 0,00 -1,66 -3,66 -3,00 -1,66 0,00 1,34… 0,00 ¿T
ϕ 2=¿ 0,00 0,00 -1,66 -0,66 1,00 3,34 0,00 -0,66 … 0,00 ¿T
ϕ 3=¿0,00 0,00 3,34 4,34 2,00 -1,66 0,00 -0,66 … 0,00 ¿T
13
Với A=[ϕ 1 ϕ 2 ϕ3 ¿
[ ]
Suy ra
0 0 0
0 0 0
−1,66 −1,66 3,34
−3,66 −0,66 4,34
−3,00 1,00 2,00
A= −1,66 3,34 −1,66
0 0 0
1,34 −0,66 −0,66
… … …
0 0 0
0 0 0
Suy ra
[ ]
330.6561 −204.2739 −126.5639
T
M = A A= −204.2739 409.7961 −205.4939
−126.5639 −205.4939 332.2161
Trị riêng và vector riêng của ma trận M: ta tiến hành nhập ma trận M vào
matlab và tiến hành tính toán Eigen Vector và Eigen Value.
14
Kết quả thu được sắp xếp Eigen Vector ( vi ¿ theo thứ tự giảm dần của Eigen
Value (λ i) là:
v1 =[ −0.4030 0.8165−0.4134 ] , λ 1=614.6752
v 2=[ 0.7099−0.0062−0.7043 ] , λ 2=457.9915
v3 =[ −0.5776−0.5773−0.5771 ] , λ3=0.0016
Với:
A=[ ϕ 1 ϕ2 ϕ 3 ]
vi : Eigen Vector
[ ]
v3 =[ −0.5776−0.5773−0.5771 ]
0 0 0
0 0 0
−1,66 −1,66 3,34
−3,66 −0,66 4,34
−3,00 1,00 2,00 T
→ u1= A v 1 = −1,66 3,34 −1,66 × [−0.4030 0.8165−0.4134 ]
T
0 0 0
1,34 −0,66 −0,66
… … …
0 0 0
0 0 0
[]
0
0
−2.0672
−0.8581
1.1987
4.0823
0
−0.8061
…
0
0
15
[]
Tương tự ta tính được
0
0
−3.5205
−5.6508
−3.5445
u2= −0.0300
0
1.4202
…
0
0
[]
0
0
−0.0104
−0.0096
0.0013
u3= −0.0114
0
−0.0121
…
0
0
Ta chuyển các vector đặc trưng ui về vector đơn vị ¿∨ui∨¿=1theo công thức:
ui
ui=
¿∨ui∨¿
Trong đó ¿∨ui∨¿=√∑ u2ij nghĩa là ¿∨ui∨¿bằng căn bậc 2 của tổng bình phương các phần
tử trong vector ui
Ta có
Suy ra
16
[]
0
0
−0.0834
−0.0346
u1 u1 0.0483
u1 = = = 0.1647
¿∨u1∨¿ 24.79
0
−0.0325
…
0
0
[]
0
0
−0.1645
−0.2640
u2 u −0.1656
u2 = = 2 = −0.0014
¿∨u2∨¿ 21.40
0
0.0664
…
0
0
[]
0
0
−0.2602
−0.2401
u3 u 0.0326
u3= = 3 = −0.2852
¿∨u3∨¿ 0.04
0
−0.3028
…
0
0
Tính vector sai số trung bình của ảnh nhận diện: ϕ temp=Γ temp −¿
Với đã tính ở trên ¿ ¿0 0 1,66 3,66 3 1,66 0 0,66 4,66 5,66 … 3 0 0 ¿T
→ ϕ temp =¿
Biểu diễn các ảnh trong không gian vector trị riêng
Ta chọn trường hợp chỉ xét theo Eigen Vector có Eigen Value lớn nhất
[]
T
Ωi=u ϕ i
0
0
−0.0834
−0.0346
0.0483
Ta có vector u có Eigen Value lớn nhất là: u1= 0.1647
0
−0.0325
…
0
0
Suy ra
Ωtemp=u T1 ϕ temp=19.0749
Ω1=u T1 ϕ 1=−9.9919
T
Ω3=u1 ϕ 2=20.2430
T
Ω3=u1 ϕ 3=−10.2499
18
Khoảng cách trong không gian cơ sở;
e r 1=||Ωtemp−Ω1||=√ ¿ ¿
e r 2=||Ωtemp −Ω2||=√ ¿ ¿
e r 3=||Ωtemp −Ω2||=√ ¿ ¿
Từ đó ta thấy giá trị của e r 2 là nhỏ nhất nên ta kết luận ảnh 2 giống template nhất.
b) Lập trình training và nhận dạng
#include <opencv2/opencv.hpp>
#include<iostream>
#include <math.h>
using namespace std;
using namespace cv;
int main()
{
//Khai bao cac ma tran anh va template
float img1[7][7] = {
0, 2, 3, 3, 7, 6, 0,
0, 8, 2, 3, 4, 9, 0,
0, 4, 0, 0, 0, 10, 0,
0, 5, 0, 0, 0, 6, 0,
0, 8, 0, 0, 0, 10, 0,
0, 6, 7, 8, 4, 6, 0,
0, 0, 0, 0, 0, 0, 0
};
float img2[7][7] = {
0, 0, 0, 0, 0, 0, 0,
0, 2, 4, 5, 0, 0, 0,
0, 6, 0, 7, 8, 0, 0,
3, 5, 9, 0, 10, 12, 0,
4, 6, 0, 0, 0, 8, 0,
5, 7, 0, 0, 3, 8, 0,
0, 9, 2, 14, 3, 0, 0
};
float img3[7][7] = {
0, 0, 1, 3, 5, 6, 8,
0, 4, 6, 0, 0, 0, 2,
5, 7, 0, 0, 0, 0, 3,
8, 2, 0, 0, 0, 0, 7,
5, 7, 0, 0, 0, 9, 9,
0, 3, 6, 7, 2, 4, 0,
0, 0, 1, 10, 13, 0, 0,
};
float temp[7][7] = {
0, 0, 0, 0, 0, 0, 0,
0, 2, 4, 5, 0, 0, 0,
0, 6, 2, 7, 8, 0, 0,
3, 5, 9, 2, 10, 12, 0,
4, 6, 2, 3, 4, 8, 0,
5, 7, 2, 3, 3, 8, 0,
0, 9, 2, 14, 3, 0, 0
};
19
float tau1[49], tau2[49], tau3[49], psi[49], tem[49], phi1[49], phi2[49],
phi3[49], phitem[49], at[49][3], a[3][49], c[3][3], u[49], uu[49];
float sum = 0, omg = 0, omg1 = 0, omg2 = 0, omg3 = 0;
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 7; j++) {
//bieu dien cac ma tran anh duoi dang vector tau_i
tau1[7 * i + j] = img1[j][i];
tau2[7 * i + j] = img2[j][i];
tau3[7 * i + j] = img3[j][i];
tem[7 * i + j] = temp[j][i];
//tinh vector trung binh psi
psi[7 * i + j] = (img1[j][i] + img2[j][i] + img3[j][i]) / 3;
//tinh sai so cua cac anh bang cach lay vector tau_i-psi
phi1[7 * i + j] = tau1[7 * i + j] - psi[7 * i + j];
phi2[7 * i + j] = tau2[7 * i + j] - psi[7 * i + j];
phi3[7 * i + j] = tau3[7 * i + j] - psi[7 * i + j];
phitem[7 * i + j] = tem[7 * i + j] - psi[7 * i + j];
//tinh ma tran a=[phi1 phi2 phi3]
a[0][7 * i + j] = phi1[7 * i + j];
a[1][7 * i + j] = phi2[7 * i + j];
a[2][7 * i + j] = phi3[7 * i + j];
//tu ma tran a ta suy ra duoc aT
at[7 * i + j][0] = phi1[7 * i + j];
at[7 * i + j][1] = phi2[7 * i + j];
at[7 * i + j][2] = phi3[7 * i + j];
}
}
cout << "Ma tran hiep phuong sai C:" << endl;
//tinh ma tran hiep phuong sai C=AT*A
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
c[i][j] = 0;
for (int k = 0; k < 49; k++) {
c[i][j] = c[i][j] + at[k][i] * a[j][k];
}
cout << c[i][j] << " ";
}
cout << endl;
}
//khai bao cac bien eigenvector va eigenvalue
Mat eivec, eival;
//chuyen ma tran c tu dang mang sang mat de dua vao ham tinh toan
Mat src(3, 3, CV_32FC1, c);
//dung ham de tinh eigen vector va eigen value
//voi src la ma tran dau vao, eival la eigen value, eivec la eigen vector
eigenNonSymmetric(src, eival, eivec);
cout << "Eigen Value: " << endl << eival << endl << "Eigen Vector: " << endl
<< eivec << endl;
vector<float> eva, eve;
//copy eigen value vua tim duoc vao mang eva
eival.col(0).copyTo(eva);
//chon eigen vector co eigen value lon nhat, sau do lay eigen vector tim duoc
copy vao mang eve
cout << "Chon Eigen Vector theo Eigen Value lon nhat" << endl;
if (eva[0] >= eva[1]) {
eivec.row(0).copyTo(eve);
cout << "Eigen Value : " << eva[0] << endl << "Eigen Vector : " <<
eve[0] << " " << eve[1] << " " << eve[2] << " " << endl;
20
}
else {
eivec.row(1).copyTo(eve);
cout << "Eigen Value : " << eva[1] << endl << "Eigen Vector : " <<
eve[0] << " " << eve[1] << " " << eve[2] << " " << endl;
}
//tim vector dat trung theo cong thuc ui=at*v_i
cout << "Vecto dac trung:" << endl << "[ ";
for (int i = 0; i < 49; i++) {
u[i] = 0;
for (int j = 0; j < 3; j++) {
u[i] = u[i] + at[i][j] * eve[j];
}
cout << u[i] << " ";
//tinh tong binh phuong cac phan tu trong vector dat trung
sum = sum + u[i] * u[i];
}
cout << " ]T" << endl;
//tinh ||u_i|| bang can bac 2 cua tong binh phuong cac phan tu
sum = sqrt(sum);
cout << "Vec to dac trung trong khong gian dac trung: " << endl << "[ ";
//bieu dien anh trong khong gian vector tri rieng theo cong thuc
omega_i=u_iT*phi_i
//trong do u_i la u_i chuyen ve vector don vi theo cong thuc u_i=u_i/||u_i||
for (int i = 0; i < 49; i++) {
cout << u[i] / sum << " ";
omg = omg + phitem[i] * u[i] / sum;
omg1 = omg1 + phi1[i] * u[i] / sum;
omg2 = omg2 + phi2[i] * u[i] / sum;
omg3 = omg3 + phi3[i] * u[i] / sum;
}
cout << " ]T" << endl;
cout << " Bieu dien anh trong khong gian vecto tri rieng:" << endl;
cout << "Omega: " << omg << endl << "Omega1: " << omg1 << endl << "Omega2: "
<< omg2 << endl << "Omega3: " << omg3 << endl;
//tinh khoang cach trong khong gian co so theo cong thuc er_i=||omega-
omgega_i||
float er1, er2, er3;
er1 = sqrt((omg - omg1) * (omg - omg1));
er2 = sqrt((omg - omg2) * (omg - omg2));
er3 = sqrt((omg - omg3) * (omg - omg3));
cout << "Khoang cach khong gian co so: " << endl;
cout << "Er1: " << er1 << endl << "Er2: " << er2 << endl << "Er3: " << er3 <<
endl;
//Ket luan anh dua tren er_i, neu er_i nao nho nhat thi giong anh goc nhat
if (er1 <= er2 && er1 <= er3) {
cout << "Hinh 1 giong hinh mau nhat" << endl;
}
else if (er2 <= er1 && er2 <= er3) {
cout << "Hinh 2 giong hinh mau nhat" << endl;
}
else {
cout << "Hinh 3 giong hinh mau nhat" << endl;
}
waitKey(0);
21
Kết quả sử dụng giải thuật PCA để training và nhận dạng template bằng tay giống với kết
quả lập trình.
22
3. Cho hình sau có tọa độ pixel như sau
7 8 9 1 1
0 1 2 3 4 5 6 0 1
1
2
3
4 1 2
1 3 4 5
5 4
1 6
6 3
1 9 8 7
7 2
1 1
8 1 0
9
1
0
1
1
a) Xoay hình bằng tay này 700 độ và dịch chuyển (u=+1,v=+2) pixel (1.5đ)
b) Giả sử sau khi xoay 700 độ và tịnh tiến ta có bộ tọa độ mới , Hãy tìm lại ma trận xoay
và tịnh tiến này dựa trên bộ data đã xoay và chưa xoay. Lập trình tính câu b sử dụng hàm
opencv (1.5đ)
Bài làm:
a. Ta có thể hiểu câu a như sau:
23
Xoay hình gồm các điểm sau: (4,4), (5,4), (6,5), (7,5), (8,5), (8,6), (8,7), (7,7), (6,7),
(5,8), (4,8), ( 4,7), (4,6), (4,5) một góc 70 độ quanh trọng tâm và tịnh tiến theo phương u
1 đơn vị và phương v 2 đơn vị :
Tìm các vùng blob sử dụng conectivity 8
Ta thực hiện quét lần lượt lên hình đề cho để tìm ra các vùng blob :
+ Lần quét đầu tiên
1 1
1 1 1 1
1 1
1 1 1 1
1 1
M 1,0=∑ ∑ i1 j 0 A i , j
i j
24
M 0,1=∑ ∑ i j A i , j
0 1
i j
M 1,1=∑ ∑ i 1 j 1 A i , j
i j
M 1,0=¿ 80
M 0,1=¿ 84
[]
Ta có ma trận biểu diễn tọa độ cho hình trên :
4 4 1
5 4 1
6 5 1
7 5 1
8 5 1
8 6 1
8 7 1
P=
7 7 1
6 7 1
5 8 1
4 8 1
4 7 1
4 6 1
4 5 1
25
[ ][ ][ ][ ]
1 0 0 cos ( 70 ° ) sin ( 70 ° ) 0 1 0 0 1 0 0
T= 0 1 0 * −sin ( 70° ) cos ( 70 ° ) 0 * 0 1 0 * 0 1 0
−5,714 −6 1 0 0 1 1 2 1 5,714 6 1
[ ]
cos ( 70 ° ) sin ( 70 ° ) 0
= −sin ( 70° ) cos ( 70 ° ) 0
10,586 0,31 1
Với :
[ ]
cos ( 70 ° ) sin ( 70 ° ) 0
- Ma trận xoay : −sin ( 70° ) cos ( 70 ° ) 0
0 0 1
[ ]
1 0 0
- Ma trận tịnh tiến : 0 1 0
1 2 1
[ ]
1 0 0
- Dời tâm quay về gốc tọa độ và đưa tâm quay về vị trí ban đầu : 0 1 0 và
−5,714 −6 1
[ ]
1 0 0
0 1 0
5,714 6 1
[] [ ]
Vậy hệ tọa độ của hình sau khi xoay và tịnh tiến :
4 4 1 8,007 5,705 1
5 4 1 8,349 6,645 1
6 5 1 7,752 7,926 1
7 5 1 8,094 8,866 1
8 5 1 8,436 9,806 1
[ ]
8 6 1 7,496 10,148 1
cos ( 70 ° ) sin ( 70 ° ) 0
8 7 1 6,556 10,498 1
P* = P * T = * −sin ( 70° ) cos ( 70 ° ) 0 =
7 7 1 6,214 9,55 1
10,586 0,31 1
6 7 1 5,872 8,611 1
5 8 1 4,591 8,013 1
4 8 1 4,249 7,073 1
4 7 1 5,188 6,731 1
4 6 1 6,218 6,389 1
4 5 1 7,068 5,047 1
b. Lập trình
26
Đầu vào : Hệ tọa độ trước và sau khi chuyển đổi, được tính ở câu a.
Đầu ra : Ma trận xoay, ma trận tịnh tiến và góc xoay.
Code :
#include <iostream>
#include <opencv2/imgproc.hpp>
#include <opencv2/core.hpp>
#include <opencv2/calib3d.hpp>
int main()
{
// Tọa độ các điểm trước và sau khi chuyển đổi
vector<Point2f> points1 = {
Point2f(4, 4),
Point2f(5, 4),
Point2f(6, 5),
Point2f(7, 5),
Point2f(8, 5),
Point2f(8, 6),
Point2f(8, 7),
Point2f(7, 7),
Point2f(6, 7),
Point2f(5, 8),
Point2f(4, 8),
Point2f(4, 7),
Point2f(4, 6),
Point2f(4, 5) };
vector<Point2f> points2 = {
Point2f(8.007, 5.705),
Point2f(8.349, 6.645),
Point2f(7.752, 7.926),
Point2f(8.094, 8.866),
Point2f(8.436, 9.806),
Point2f(7.496, 10.148),
Point2f(6.556, 10.498),
Point2f(6.214, 9.55),
Point2f(5.872, 8.611),
Point2f(4.591, 8.013),
Point2f(4.249, 7.073),
Point2f(5.188, 6.731),
Point2f(6.218, 6.389),
Point2f(7.068, 5.047) };
vector<Point2f> points1_r = { // dùng để tính ma trận xoay, vì hàm getAffineTransform chỉ lấy 3 điểm
Point2f(4, 4),
Point2f(5, 4),
Point2f(6, 5) };
vector<Point2f> points2_r = {
Point2f(8.007, 5.705),
Point2f(8.349, 6.645),
27
Point2f(7.752, 7.926) };
// Tìm tâm của các điểm trước và sau khi chuyển đổi
Scalar C1 = mean(points1);
Scalar C2 = mean(points2);
return 0;
}
28
Giải thuật:
Tính trọng tâm của template theo công thức:
Từ trọng tâm và template lập bảng R –table là vector chứa vector, trong đó vector cha là
vector index –edgde orientation trong khoảng 0 đến 2pi, vector con là cặp r và alpha được
tính theo công thức:
Từ bảng R-table, tiến hành voting các điểm pixel trong ma trận ảnh target và lưu lại dưới
dạng ma trận voting – accumalator.
29
Từ accumalator, chọn những điểm pixel có giá trị cao, được nhiều lượt vote , đó là các
điểm trọng tâm
Code:
#include "opencv2/highgui.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
#include <vector>
#include <cmath>
// ma trận tính sobel ảnh
return edge_orientation;
}
return r_table;
}
30
{
if (accum_i >= 0 && accum_i < accumulator.rows && accum_j >= 0 && accum_j < accumulator.cols) {
accumulator.at<int>(accum_i, accum_j) += 1;
}
}
}
}
}
return accumulator;
}
int main() {
}
}
31
// Trọng tâm ảnh template gốc
int sum_x = 0;
int sum_y = 0;
int count = 0;
sum_x = sum_x + j;
sum_y = sum_y + i;
count++;
}
}
}
float centroidX1 = static_cast<float>(sum_x) / static_cast<float>(count);
float centroidY1 = static_cast<float>(sum_y) / static_cast<float>(count);
circle(Template_1, Point(centroidX1, centroidY1), 5, Scalar(255, 255, 255), -1);
Point center1(centroidX1, centroidY1);
sum_x = sum_x + j;
sum_y = sum_y + i;
count++;
}
}
}
float centroidX2 = static_cast<float>(sum_x) / static_cast<float>(count);
float centroidY2 = static_cast<float>(sum_y) / static_cast<float>(count);
circle(Template_2, Point(centroidX2, centroidY2), 5, Scalar(255, 255, 255), -1);
Point center2(centroidX2, centroidY2);
// Số hàng , lấy trong khoảng từ 0 đến 360, egde orietation
int rowCount = 360;
// tạo bảng rtable, với rtable là 1 vector chứa 1 vector là 1 cặp r và alpha
vector<vector<pair<float, float>>> rTable1 = build_r_table(Template_1, center1, rowCount);
vector<vector<pair<float, float>>> rTable2 = build_r_table(Template_2, center2, rowCount);
//// Tạo ma trận để voting xc, yc
// scale là 0.5
Mat accumulatorArray1 = accumulator_mat(Target, rTable1,0.5);
Mat accumulatorArray2 = accumulator_mat(Target, rTable2, 0.5);
// phân ngưỡng voting, vẽ hình tròn điền đầy lên các điểm này
int threshold = 120;
for (int i = 0; i < accumulatorArray1.rows;i++)
32
{
for (int j = 0;j < accumulatorArray1.cols;j++)
{
if (accumulatorArray1.at<int>(i, j) > threshold)
{
Point center1(j, i);
circle(Target_result, center1, 5, Scalar(255, 255, 255), -1);
}
}
}
threshold = 100;
}
}
return 0;
}
Output:
33
34