You are on page 1of 14

TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN

KHOA CÔNG NGHỆ THÔNG TIN

BÁO CÁO ĐỒ ÁN CÁ NHÂN


Môn: TOÁN ỨNG DỤNG VÀ THỐNG KÊ
CHO CÔNG NGHỆ THÔNG TIN
Lab02: Project01

LỚP 21CLC10
MSSV: HỌ VÀ TÊN
21127512 Nguyễn Lê Hoàng Kha

GIẢNG VIÊN HƯỚNG DẪN:


Vũ Quốc Hoàng
Nguyễn Văn Quang Huy
Ngô Đình Hy
Phan Thị Phương Uyên

Thành phố Hồ Chí Minh, Tháng 7 năm 2023

1
Contents
1/ Ý tưởng thực hiện và giải thích hàm ......................................................................................... 3
1.1. Đọc file ảnh ......................................................................................................................... 3
1.2. Chỉnh sửa kích thước mảng ................................................................................................. 4
1.3. Thuật toán Kmeans .............................................................................................................. 4
1.3.1 Tạo centroids .................................................................................................................. 5
1.3.2. Lưu trữ centroids cũ ......................................................................................................... 6
1.3.3. Tính khoảng cách từng điểm đến từng centroid ............................................................... 7
1.3.4. Tìm khoảng cách centroid ngắn nhất đến từng điểm ....................................................... 9
1.3.5. Thay đổi giá trị cho centroids ......................................................................................... 10
1.3.6. Dừng Kmeans khi giá trị centroids không đổi ............................................................... 11
1.3.7. Cập nhật giá trị cho kết quả cuối cùng ........................................................................... 11
1.4. Chỉnh sửa mảng lại đúng kích thước của ảnh ................................................................... 12
1.5. Hiển thị ảnh và lưu ảnh ..................................................................................................... 12
2/ Kết quả ..................................................................................................................................... 13
3/ Tài liệu tham khảo ................................................................................................................... 14

2
1/ Ý tưởng thực hiện và giải thích hàm

Sau khi đã cho người dùng nhập vào đầy đủ các thông tin cần thiết về tên tập tin ảnh định dạng đầu ra và
số k clusters của ảnh, ta tiến hành các bước sau:

1.1. Đọc file ảnh

a) Trong hàm main

b) Hàm chính

Đọc nội dung hình ảnh và chuyển dữ liệu thành kiểu dữ liệu ndarray bằng hàm img_as_array()

c) Giải thích

- Image.open(path) sẽ trả về giá trị của ảnh ở đường dẫn path có dạng list ba chiều.
3
- Tiến hành đồng thời đổi kiểu dữ liệu của img thành kiểu ndarray bằng hàm np.array(img) và đổi kiểu dữ
liệu của mảng thành int32 bằng hàm astype(np.int32).

-Khi này, mảng img_2d có dạng mảng ba chiều, nhưng ta xem như dạng mảng hai chiều trong đó mỗi
phần tử sẽ là thuộc kiểu list có số phần tử tùy thuộc vào số channels của tùy loại ảnh. ta gọi nó là mảng
hai chiều tượng trưng.

1.2. Chỉnh sửa kích thước mảng

a) Trong hàm main

b) Ý tưởng

- Nếu ta tiếp tục để mảng hai chiều tượng trưng thì sẽ rất khó truy cập càng phần tử phục vụ cho việc
tính toán sau này nên ta sẽ biến đổi thành mảng một chiều tượng trưng.

- Lợi ích khi biến đổi là do ta sẽ có khả năng truy cập một dòng của mảng (tọa độ điểm) bằng (a[i, :] hoặc
a[i]) dễ dàng hơn, khá giống với việc truy từng phần tử trong list một chiều.

b) Hàm chính:

Chỉnh sửa kích thước mảng hai chiều tượng trưng thành một chiều tượng trưng và lưu các giá trị
(chiều cao, chiều rộng, số lượng channel) bằng hàm scaling_img()

c) Giải thích

- shape[0], shape[1], shape[2] lần lượt tương ứng là giá trị của chiều cao, chiều rộng, số lượng channel của
mảng ba chiều ban đầu.

- Khi ta reshape(height*width, c_channels) thì mảng ba chiều trở thành mảng hai chiều với số dòng bằng
tổng số pixels của ảnh và số cột bằng số channels của ảnh  Ta xem mảng hai chiều này như là mảng
một chiều tượng trưng với số phần tử bằng tổng số pixels của ảnh và với mỗi phần tử là một mảng có số
phần tử bằng số channels của ảnh.

1.3. Thuật toán Kmeans

a) Trong hàm main

4
- Các tham số truyền vào hàm kmeans lần lượt là mảng img_1d, số k_clusters , số vòng lặp tối ta
(1000000), kiểu chọn centroids (‘random’)

b) Hàm chính

1.3.1 Tạo centroids

a) Hàm chính

5
Tạo mảng centroids có kích thước là mảng một chiều tượng trưng tương tự như trên, với tổng số phần tử
bằng k_clusters trong đó mỗi phần tử là một mảng có số phần tử bằng số channels (img_1d.shape[1])

b) Giải thích

- Trường hợp init_cluster = random:

+ Tạo một list result

+ Chạy loop k_clusters số lần với mỗi lần ta thêm vào result một list tmp tạo từ
list(np.random.choice(256, img_1d.shape[1]), trong đó np.random.choice(256, img_1d.shape[1]) tạo một
mảng có số channels(img_1d.shape[1]) phần tử với giá trị trong khoảng [0,255].

+ Nếu centroids tmp vừa tạo đã tồn tại trong result thì ta tiếp tục lặp while đến khi giá trị mới hoàn toàn
được tạo nên.

- Trường hợp init_cluster != random:

+ Ta tạo được một mảng (1) có k_clusters phần tử với giá trị trong khoảng [0, length] với
(np.random.choice(length, k_clusters, replace = False)

+ img_1d[(1)] sẽ trả về một mảng mới với các phần tử thuộc img_1d có index tương ứng với các giá trị
trong mảng [1]

1.3.2. Lưu trữ centroids cũ

a) Giải thích

Lưu trữ để sử dụng sau

6
1.3.3. Tính khoảng cách từng điểm đến từng centroid

Trong hàm main

a) Ý tưởng

- Giả sử ta có hai mảng ndarray a[n,m] và b[1,m], thì a[n,m] – b[1,m] sẽ tạo thành một mảng c[n,m] với
các dòng có giá trị lần lượt là (c[1] = a[1] – b[1] …. c[n] = a[n] – b[n]) dựa theo cơ chế broadcasting có
sẵn của phép trừ numpy array.

- Để hiểu được cơ chế broadcasting, ta xem ví dụ dưới đây:

+ Trong numpy, để có thể trừ hai ma trận được tạo nên từ các mảng, chúng phải cùng shape. Với ví dụ
trên, array_2d và array_1d không cùng shape nên cơ chế broadcasting sẽ diễn ra. Cơ chế sẽ tự động thay
đổi shape của hai ma trận để shape trở nên tương đồng.

+ Khi đó array_1d sẽ có shape tương đồng với array_2d như sau:

+ Việc còn lại của numpy là trừ từng dòng với từng dòng tương tự như toán học:

𝑎 ⋯ 𝑎 𝑏 ⋯ 𝑏 𝑎 ±𝑏 ⋯ 𝑎 ±𝑏
𝐴±𝐵 = ⋮ ⋱ ⋮ + ⋮ ⋱ ⋮ = ⋮ ⋱ ⋮
𝑎 ⋯ 𝑎 𝑏 ⋯ 𝑏 𝑎 ±𝑏 ⋯ 𝑎 ±𝑏
7
- Với ý tưởng trên, ta reshape centroids về [centroids.shape[0], 1, centroids.shape[0]] thì mảng centroids
sẽ trở thành mảng ba chiều  Nếu ta lấy mảng hai chiều img_1d trừ mảng 3 chiều centroids, mảng
img_1d sẽ broadcast thành mảng 3 chiều. Khi đó phép trừ sẽ được thực hiện.

b) Hàm chính:

Hàm trả về mảng có kích thước [img_1d.shape[0], k_clusters] với từng dòng có các cột là khoảng cách
của điểm đến từng centroids tương ứng số k_clusters.

c) Giải thích

- Với ý tưởng đã nêu trên, nếu ta lấy img_1d – centroids được reshape thành mảng ba chiều, ta có được
mảng có shape (k_clusters, img_1d.shape[0], img_1d.shape[1]) trong đó các cột trong mỗi dòng sẽ là kết
quả phép trừ của các điểm ảnh cho điểm centroids tương ứng.

- Sau khi đã có kết quả của phép trừ, ta tính khoảng cách giữa hai điểm trong không gian channels (c) số
chiều theo công thức

(𝑎 − 𝑏 )

- Giải thích **2).sum(axis=2)**0.5:

+ **2: ta bình phương tất cả các phần tử và cộng các cột tương ứng mỗi dòng lại với nhau bằng sum(axis
= 2), ta sử dụng axis = 2 vì mảng hiện tại đang là mảng ba chiều. Xem ví dụ dưới đây để hiểu rõ:

8
+ Ta lấy căn giá trị từng dòng bằng **0.5.

+ Mảng với số dòng bằng số k_clusters với số cột bằng số các phần tử của img_1d, tương ứng mỗi dòng là
khoảng cách của tất cả điểm đến centroid tương ứng với dòng đó.

+ Hàm trả về mảng được chuyển vị bằng hàm tranpose(), để mảng có số dòng bằng số các phần tử của
img_1d với số cột bằng số k_clusters, tương ứng mỗi dòng là khoảng cách của một điểm đến các
centroids.

1.3.4. Tìm khoảng cách centroid ngắn nhất đến từng điểm

a) Hàm chính

9
b) Ý tưởng

- Thư viện numpy hỗ trợ hàm argmin() dùng để tìm ra giá trị nhỏ nhất trong mảng và trả về index của giá
trị đó.

- Theo bước trên đã giải thích, mảng distances đang có kích thước [img_1d.shape[0], k_clusters] tương
ứng mỗi dòng i sẽ là khoảng cách từ điểm i đến các centroids theo các cột.

- Ta có thể sử dụng argmin() và tìm ra khoảng cách centroid nhỏ nhất theo từng dòng trong mảng
distances.

c) Giải thích

- Cú pháp np.argmin(distances, axis=1) sẽ trả về mảng một chiều có số phần tử bằng số dòng của
distances, trong đó mỗi phần tử sẽ là index của centroids nhỏ nhất đến từng điểm trong distances.

- axis = 1 có nghĩa xét argmin theo phương thẳng đứng trong distance.

1.3.5. Thay đổi giá trị cho centroids

a) Hàm chính

b) Ý tưởng

- Sau khi đã có mảng chứa index của các centroids có khoảng cách ngắn nhất đến từng điểm, chúng ta bây
giờ chỉ cần lấy trung bình của các điểm thuộc từng centroid và cập nhật giá trị cho centroids.

c) Giải thích

- Ta chạy vòng for k_cluster lần

- Giải thích cú pháp img_1d[closest == i]:

+ closest == i sẽ trả về mảng boolean một chiều có số phần từ bằng số phần tử của closest, trong đó các

10
phần tử mang giá trị True hoặc False khi so sánh giá trị các phần tử tương ứng bên closest với i (*)

+ Tương tự như vậy, img_1d[closest == i] sẽ trả về mảng một chiều tượng trưng là các phần tử của
img_1d có vị trị tương ứng với vị trí có giá trị True trong (*)

- Sau khi đã có mảng một chiều tượng trưng các điểm thuộc từng centroid, ta lấy giá trị trung bình bằng
hàm mean(axis=0) và gán giá trị đó cho từng centroid tương ứng (centroids[I, :] = )

1.3.6. Dừng Kmeans khi giá trị centroids không đổi

a) Giải thích

Sử dụng hàm np.allclose để so sánh giá trị hai mảng old_centroids và centroids, nếu giá trị hai mảng xấp
xỉ nhau, ta cho dùng vòng lặp.

1.3.7. Cập nhật giá trị cho kết quả cuối cùng

a) Giải thích

- Tạo mảng 0 có kích thước như img_1d bằng câu lệnh: result = np.zeros((img_1d.shape[0],img_1d.shape[1]))

- Gán giá trị cho result[I, :] bằng centroids có vị trí bằng closest[i].

- Hàm tổng kết thúc và trả về biến result có kiểu dữ liệu ndarray.

11
1.4. Chỉnh sửa mảng lại đúng kích thước của ảnh

a) Trong hàm main

b) Hàm chính

Trả về mảng ảnh có shape như kích thước ban đầu

1.5. Hiển thị ảnh và lưu ảnh

a) Trong hàm main

b) Hàm chính

- Giải thích:

+ Chuyển kiểu dữ liệu của mảng lại thành np.uint8 ứng với giá trị trong khoảng [0,255]

+ Chuyển đổi mảng thành kiểu dữ liệu ảnh bằng hàm fromarray() và tiến hành lưu ảnh bằng hàm save()
của thư viện Image
12
+ Chuyển đổi mảng thành kiểu dữ liệu list và dùng hàm imshow() của thư viện matplotlib.pyplot để thể
hiện ảnh.

2/ Kết quả
Số Ảnh Nhận xét
lượng
màu

Ban Ảnh mang kích thước


đầu 1600 x 900 pixels.

3 - Kiểm tra thời gian trung


bình với ba lần chạy.

+ Centroids random: 5.12


giây

+ Centroids chọn ngẫu


nhiên pixel ảnh: 8.34
giây

5 - Kiểm tra thời gian trung


bình với ba lần chạy.

+ Centroids random:
12.13 giây

+ Centroids chọn ngẫu


nhiên pixel ảnh: 15.1
giây

13
7 - Kiểm tra thời gian trung
bình với ba lần chạy.

+ Centroids random:
18.13 giây

+ Centroids chọn ngẫu


nhiên pixel ảnh: 25.1
giây

3/ Tài liệu tham khảo


https://www.youtube.com/watch?v=1Azmr-wOeU0

https://stackabuse.com/guide-to-numpy-matrix-subtraction/

https://www.geeksforgeeks.org/

14

You might also like