Professional Documents
Culture Documents
Đồ án 2: Image processing
Author
1
Toán ứng dụng và thống kê cho Công nghệ thông tin
Mục lục
1 Lời mở đầu 3
2 Mô tả chương trình 3
2.1 Ý tưởng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Mô tả hàm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2.1 Các thư viện được sử dụng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2.2 Các hàm Input/Ouput hình ảnh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2.3 Hàm thay đổi độ sáng của ảnh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2.4 Thay đổi độ tương phản của ảnh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2.5 Lật ảnh (dọc/ngang) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2.6 Chuyển hình ảnh thành Grayscale/Sepia . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.7 Làm mờ / sắc nét ảnh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2.8 Cắt ảnh theo kích thước . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.9 Cắt ảnh theo khung hình tròn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.10 Cắt ảnh theo 2 khung hình elip chéo nhau . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.11 Hàm main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1 Lời mở đầu
Em tên là Nguyễn Việt Kim, MSSV 21127333 đang là học sinh lớp 21CLC08 thuộc khoa Công nghệ
thông tin chương trình chất lượng cao, Đại học Khoa Học Tự Nhiên, Đại học quốc gia thành phố Hồ
Chí Minh
Sau đây là báo cáo về Đồ án 2 - Image Processing sử dụng các phép toán với ma trận và các phép
toán về hình học để xử lí màu RGB bằng ma trận và lưu hình ảnh sau khi xử lí. Đồ án được viết bằng
ngôn ngữ lập trình Python và sử dụng các thư viện toán học và xử lí hình ảnh có sẵn trong Python,
bao gồm matplotlib và numpy.
2 Mô tả chương trình
2.1 Ý tưởng
Hình ảnh là ma trận 2 chiều gồm các điểm ảnh là các ma trận con với kích thước là 3 dùng để lưu trữ
hệ màu RGB dưới dạng các số thể hiện cho các chỉ số Red(đỏ), Green(xanh lá) và Blue(xanh lam).
Bằng cách thay đổi các chỉ số đó (riêng lẻ hoặc theo ma trận) ta sẽ được hình ảnh được xử lí theo yêu
cầu. Chương trình sẽ sử dụng các phép toán với số, theo hình học hoặc theo ma trận để thực hiện xử
lí hình ảnh.
2.2 Mô tả hàm
Trong phần này, các hàm sẽ được mô tả cách thức và chức năng trong chương trình.
Các chức năng đã hoàn thành:
Đoạn chương trình sau đây là các thư viện được sử dụng trong Python dùng cho các thuật toán và
xử lí input/output của các hình ảnh.
1 import numpy as np
2 import matplotlib as mpl
Hàm read_image() sử dụng thư viện Image của PIL để đọc hình ảnh và sau đó định dạng ảnh từ các
hệ màu khác thành hệ màu RGB và chuyển về thành dạng array của numpy để sử dụng cho việc xử
lí hình ảnh. Ảnh được chuyển đổi dưới dạng mảng 2 chiều các pixel theo kích thước của ảnh. Mỗi
pixel là một mảng để lưu trữ 3 giá trị thể hiện cho 3 chỉ số của hệ màu RGB theo thứ tự là Red(đỏ),
Green(xanh lá) và Blue(xanh lam).
1 # Read image
2 def read_image () :
3 filename = input ( " Enter name of the file : " )
4
9 return img
Hàm sau sẽ cho người dùng thực hiện lưu ảnh với tên file đã định sẵn dưới định dạng ảnh .png:
1 def export_image ( img , filename ) :
2 img = Image . fromarray ( img )
3 img . save ( filename + " . png " )
Brightness là độ sáng của ảnh. Độ sáng của ảnh được thay đổi bởi sự thay đổi chung của tất cả các
pixel trên ảnh. Điều này được thực hiện bởi việc cộng từng chỉ số màu của từng pixel với độ sáng
tương ứng. Ta có thể giảm độ sáng hoặc tăng độ sáng với hệ số màu thỏa mãn luôn lớn hơn 0 và nhỏ
hơn 255.
1 def chan ge_brightness ( img , brightness ) :
2 new_img = np . zeros ( img . shape , img . dtype )
3
9 return new_img
Khác với độ sáng của ảnh, độ tương phản (contrast) là độ chênh lệch (sự khác nhau) giữa các màu
sáng và tối trong hình ảnh. Điều này có được bằng cách tăng độ sáng của các màu sáng và giảm độ
tối của các màu tối hơn theo độ tương phản được yêu cầu.
Công thức tính độ sáng mới của điểm ảnh như sau:
i − i mi n
i p = 255 ×
i max − i mi n
Với ip là độ sáng mới (new luminosity) của điểm ảnh, i (luminosity) là độ sáng hiện lại của ảnh được
tính với công thức i = R+G+B
3 , trong đó R G B là các màu cơ bản của pixel, imin và imax lần lượt là độ
sáng nhỏ nhất là lớn nhất (min luminosity, max luminosity).
Màu mới của điểm ảnh sẽ được tính dựa trên công thức sau:
ip
x=x×
i
Đoạn code để thay đổi độ tương phản của bức ảnh như sau:
1 def change_contrast ( img , intensity ) :
2 new_img = np . zeros ( img . shape , img . dtype )
3 luminosity = np . zeros (( img . shape [0] , img . shape [1]) , img . dtype )
4 intensity = intensity / 100 + 1
5
20 return new_img
Vì ảnh là mảng 2 chiều của các điểm ảnh thể hiện cho từng màu của điểm ảnh, ảnh có thể được lật
bằng cách đổi chỗ các điểm ảnh với nhau (đổi giá trị màu giữa các điểm ảnh).
Người dùng sẽ nhập từ bàn phím lựa chọn ’h’ (horizontal) hoặc ’v’ (vertical) để thực hiện lật ảnh
theo chiều ngang hoặc chiều dọc. Chương trình sẽ thực hiện đổi chiều của mảng dựa trên yêu cầu từ
người dùng.
Chuyển hình ảnh từ màu RGB thành grayscale được thực viện bằng cách nhân 2 ma trận sau với
nhau:
h i 0.299 0.299 0.299
R G B ×
0.587 0.587 0.587
0.114 0.114 0.114
7 Avg = ( R + G + B )
8
Đối với chuyển ảnh từ RGB thành sepia, công thức để sử dụng chuyển đổi này là nhân 2 ma trận sau
với nhau:
h i 0.393 0.349 0.272
R G B ×
0.769 0.686 0.534
0.189 0.168 0.131
15 return new_img
Bằng cách nhân ma trận kernel và ma trận được tạo bởi các ô xung quanh ô được chọn thỏa ô được
chọn là ô ở giữa và kích thước của ma trận được chọn bằng với kích thước của ma trận kernel, ta sẽ
được ô mới tại vị trí đã chọn.
7 # sharpening kernel
8 sharp ening_kernel = [[ 0 , -.5 , 0 ],
9 [ -.5 , 3 , -.5 ] ,
10 [ 0 , -.5 , 0 ]]
11
28 new_img [ y ][ x ] = [R ,G , B ]
29
30 return new_img
Ảnh được cắt theo hình chữ nhật với kích thước được người dùng nhập trước. Bằng cách khởi tạo với
kích thước đã nhập từ người dùng, chương trình sẽ tạo một ma trận với kích thước mới với giá trị
màu được lấy từ trung tâm của hình cũ.
11 return new_img
Listing 10: Hàm cắt ảnh từ trung tâm theo hình chữ nhật
Người dùng sẽ được nhập bán kính của khung hình tròn và bằng thuật toán Euclidean tính khoảng
các điểm trong tọa độ mặt phẳng, những điểm ảnh nằm trong bán kính đường tròn sẽ được gán giá
trị màu cho ma trận mới. Các điểm khác sẽ được gán màu đen (0, 0, 0).
10 else :
11 new_img [ y ][ x ] = [0 , 0 , 0]
12
13 return new_img
Ý tưởng giống như cắt ảnh theo hình tròn, các điểm ảnh nằm trong khu vực của hình elip sẽ được
gán giá trị cho ma trận ảnh mới. Các điểm ảnh được chọn dựa thỏa bất phương trình sau:
A × x 2 + B × x × y +C × y 2 ≤ 1
Với:
cos(α)2 si n(α)2
A= +
a2 b2
1 1
B = 2 × cos(α) × si n(α) × ( − )
a2 b2
si n(α)2 cos(α)2
C= +
a2 b2
Trong đó a là độ dài nửa trục chính của hình elip, b là độ dài của nửa trục phụ của elip, α là góc xoay
của trục chính so với mặt phẳng Ox trong hệ tọa độ Oxy. Trục chính của 2 hình elip là đường thẳng
từ tâm hình đến 2 góc trên thuộc mặt phẳng thứ I và thứ IV của hình theo trục tọa độ Oxy với tâm O
là tâm của hình. Khi đó sin và cos của góc α sẽ được tính bằng hàm sau:
1 def sin (A , B ) :
2 return ( np . abs ( B [1] - A [1]) / Euclidean (A , B ) )
3
4 def cos (A , B ) :
5 return ( np . abs ( B [0] - A [0]) / Euclidean (A , B ) )
4 # Main axis = 2 a
5 # Minor axis = 2 b
6 # Distance between a focus point and centre
7 # In this crop , it ’s best to choose b = a / 2
8 centre = [ int ( img . shape [1] / 2) , int ( img . shape [0] / 2) ]
9 a_square = int (( size / 100) * ( pow ( img . shape [0] , 2) + pow ( img . shape [1] , 2) ) / 4)
10 b_square = int ( a_square / 4)
11
17 #
18 A1 = pow ( cos_axis1 , 2) / a_square + pow ( sin_axis1 , 2) / b_square
19 B1 = 2 * cos_axis1 * sin_axis1 * (1 / a_square - 1 / b_square )
33
34 return new_img
Listing 14: Hàm cắt ảnh theo 2 khung hình elip chéo nhau
Hàm executing_mode() sẽ thực hiện các yêu cầu của người dùng nhập vào với số từ 1-10 ứng với
từng chức năng và trả về ma trận hình ảnh sau khi được xử lí:
1 def executing_mode ( img , mode ) :
2 # Change brightness of the image
3 if mode == 1:
4 # Input brightness percentage
5 # The brightness comes in range ( -100 , 100) with negative for darken and
positive for brighten the image
6 brightness = int ( input ( " Choose brightness between -100 to 100: " ) )
7 while ( brightness < 0 or brightness > 100) :
8 brightness = int ( input ( " Invalid input ! Brightness should be within -100
to +100 " ) )
9
21 # Flip image
22 elif mode == 3:
23 return ( flip_image ( img ) )
24
28
33 # Blur image
34 elif mode == 6:
35 return ( blur_sharpening ( img , box_kernel ) )
36
37 # Sharpening image
38 elif mode == 7:
39 return ( blur_sharpening ( img , sharpening_kernel ) )
40
Hàm main() sẽ gọi đến hàm read_image() và cho người dùng nhập tên file ảnh muốn chỉnh sửa. Sau
đó người dùng sẽ được nhập mode ứng với từng chức năng từ 0-10. Với mode = 0, chương trình sẽ
thực hiện tất cả chức năng và lưu dưới dạng file ảnh .png. Với các mode khác, chương trình sẽ hiện
ảnh cho người dùng thấy được.
1 if __name__ == " __main__ " :
2 """
3 Choose from 0 to 10 for each feature :
4 0 - Do all the below functions and save into files
5 1 - Change brightness
6 2 - Change contrast
7 3 - Flip image
8 4 - Convert to grayscale
9 5 - Convert to sepia
10 6 - Blur image
11 7 - Sharpen image
12 8 - Crop image in square shape
13 9 - Crop image in circle shape
14 10 - Crop image in 2 ellipses
15 """
16 # Read the image
17 img = read_image ()
18
19 mode = int ( input ( " Choose mode for image modifying : " ) )
20 while ( mode < 0 or mode > 10) :
21 mode = int ( input ( " Please enter valid choice of mode " ) )
22
23 if mode == 0:
24 for i in range (1 , 11) :
25 if i == 1:
26 mode_name = " brightness "
27 elif i == 2:
28 mode_name = " contrast "
29 elif i == 3:
30 mode_name = " flip "
31 elif i == 4:
32 mode_name = " grayscale "
33 elif i == 5:
34 mode_name = " sepia "
35 elif i == 6:
36 mode_name = " blur "
37 elif i == 7:
38 mode_name = " sharpening "
39 elif i == 8:
40 mode_name = " crop_square "
41 elif i == 9:
42 mode_name = " crop_circle "
43 elif i == 10:
44 mode_name = " crop_ellipses "
45 export_image ( executing_mode ( img , i ) , mode_name )
46 else :
47 plt . imshow ( executing_mode ( img , mode ) )
Hình 3: test.jpg
Hình 4: brightness.png
Hình 5: contrast.png
Hình 6: flip.png
Hình 7: grayscale.png
Hình 8: sepia.png
Hình 9: blur.png
Ảnh được cắt theo hình chữ nhật kích thước 300 × 300
Ảnh được cắt theo khung hình tròn với bán kính 300: