1.Thế nào là ảnh kĩ thuật số?
Một hình ảnh trong máy vi tính được định nghĩa với hàm hai chiều, $f(x,y)$ trong đó $x$ và $y$ là tọa độ không gian (mặt phẳng) và biên độ của $f$ tại bất kỳ cặp tọa độ $(x,y)$ nào được gọi là cường độ hoặc mức xám của hình ảnh tại điểm đó. Khi $x$, $y$ và các giá trị cường độ của $f$ đều là các đại lượng hữu hạn, rời rạc, chúng ta gọi hình ảnh là hình ảnh kỹ thuật số (hay hình ảnh số). Một hình ảnh kỹ thuật số bao gồm một lượng hữu hạn các thành phần, mỗi thành phần có một vị trí và giá trị cụ thể. Các thành phần này được gọi là điểm ảnh (pixel). Hình 1 dưới đây minh họa giá trị của một vùng ảnh kỹ thuật số theo khái niệm này. Lĩnh vực xử lý hình ảnh kỹ thuật số chú trọng vào việc xử lý hình ảnh kỹ thuật số bằng máy vi tính. Định nghĩa này sẽ được trình bày theo các thuật ngữ một cách cụ thể hơn trong các phần sau.
Đang xem: Một vài khái niệm cơ bản về Ảnh số là gì, Ảnh số là gì
Hình 1 – Giá trị mức xám của một vùng ảnh kỹ thuật số binary.2. Biểu diễn hình ảnh dưới dạng một hàm số:
Như đã đề cập ở phần trước, giá trị mức xám một hình ảnh số thường được biểu diễn bởi một hàm số $f(x, y)$ cho một mặt phẳng lưới chứa M hàng và N cột, trong đó x và y là tọa độ nguyên rời rạc. Thông thường, giá trị nguyên sẽ được sử dụng để biểu diễn cho các tọa độ rời rạc này với $x=0, 1, 2, ldots,left(M-1
ight)$ và $y=0, 1, 2, ldots,left(N-1
ight)$. Ví dụ, giá trị mức xám của hình ảnh số tại điểm gốc là $f(0, 0)$ và giá trị tại tọa độ tiếp theo theo hàng dọc đầu tiên là $f(0, 1)$. Nếu xem 1 hình ảnh số là một ma trận, giá trị mức xám của ảnh sẽ được biểu diễn dưới dạng một ma trận có giá trị nguyên rời rạc như dưới đây:
$$fleft(x,y
ight)=left<egin{matrix}f(0, 0)& f(0, 1) &cdots& f(0, N-1) \f(1, 0)&f(1, 1)&cdots&f(1, N-1)\vdots&vdots& &vdots\f(M-1, 0)&f(M-1, 1)&cdots&f(M-1, N-1)\end{matrix}
ight> $$
Hình 2 dưới đây minh họa ba cách biểu diễn một ảnh đơn sắc (còn gọi là ảnh trắng đen) trong các dạng không gian và kiểu giá trị khác nhau.
Hình 2 – Ba cách biểu diễn một hình ảnh số.3. Các không gian màu
Ta có thể hình dung rằng, ứng với mỗi vị trí (x, y) thì f(x, y) là hàm số được biểu diễn là một véc-tơ có số thuộc tính tương ứng với số kênh màu. Từ đó ta có thể thấy hình 2 biểu diễn hình đen trắng với f(x, y) là véc-tơ với 1 thuộc tính. Thế nếu có nhiều hơn một kênh màu thì sao?
3.1. Không gian màu RGB
Từ ba màu cơ bản: đỏ (Red), xanh lục (Green) và xanh lam (Blue), chúng ta có thể tạo ra tất cả các phổ màu nhìn thấy được với một tỷ lệ cường độ trộn màu khác nhau. Dựa trên tiền đề đó, trong không gian màu RGB, các màu được biểu diễn với các thành phần phổ chính của nó là đỏ $(R)$, xanh lục $(G)$, xanh lam $(B)$. Mô hình này được thể hiện trên một hệ tọa độ Descartes. Như được minh họa ở Hình 3, các giá trị chính đỏ $(R)$, xanh lục $(G)$, xanh lam $(B)$ nằm ở ba góc; các màu thứ cấp lục lam, đỏ tươi và vàng nằm ở ba góc khác; màu đen là ở gốc; và màu trắng là ở góc xa nhất từ gốc.
Nếu chúng ta xem mỗi trục màu có kích thước 8 bit, mỗi pixel màu RGB được biểu diễn với mỗi bộ ba giá trị $left
ight)^3=16 777 216$ màu. Do đó, giá trị màu tại mỗi điểm trong không gian RBG này chính là tọa độ ba chiều $left
Hình 3 – Không gian màu RGB trên hệ trục tọa độ Descartes
Vậy từ ba màu cơ bản: đỏ (Red), xanh lục (Green) và xanh lam (Blue), chúng ta có thể tạo ra một hình ảnh với hàm là $f(x, y) =
3.2. Không gian màu HSV
Không gian màu RGB không phải là một mô hình màu đặc trưng phù hợp cho việc đặc tả màu sắc. Một ví dụ đó là giả sử chúng muốn tạo ra màu tím đậm. Theo RGB, màu tím là màu kết hợp từ màu đỏ và màu xanh lam. Như vậy, rõ ràng là chúng ta không biết được chính xác tỉ lệ của 2 màu cơ bản này để trộn ra được độ đậm nhạt của màu tím mà chúng ta mong muốn. Do đó, mô hình màu HSV ra đời để giúp chúng ta có được câu trả lời về màu sắc mà không cần quan tâm đến sự pha trộn của ba màu cơ bản đỏ, lục và lam.
Hình 4 – Minh họa mô hình màu HSV với ba thành phần cơ bản màu sắc (Hue), độ bão hòa (Saturation) và giá trị (Value)
HSV là một mô hình màu được mô tả bởi một không gian ba chiều hình trụ, ánh xạ lại các màu cơ bản RGB thành ba trục mang các tính chất đặc trưng của màu sắc đó là: màu sắc (Hue), độ bão hòa (Saturation) và giá trị (Value). Trong đó:
Hue chỉ định góc của màu trên một mặt tròn. Ứng với mỗi góc đo, chúng ta có được các màu sắc khác nhau như trình bày ở bảng dưới đây:
Hình 5 – Bảng tóm tắt thông tin màu sắc ở khi xét ở trục Hue trong không gian HSVĐộ bão hòa (Saturation) biểu thị mức độ tinh khiết của màu sắc trong không gian màu. Độ bão hòa màu nằm trong khoảng từ 0 đến 100% (Trong một số tài liệu, thang đo này có giá trị thực nằm trong khoảng 0-1). Tương ứng với các giá trị, một màu với độ bão hòa 100% sẽ là màu tinh khiết nhất có thể, trong khi với độ bão hòa 0% màu sắc có sắc xám, màu nhạt là do mức bão hòa thấp hơn.
Hình 6 – Bảng tóm tắt thông tin màu sắc khi xét ở trục hai trục Saturation và Value với màu đỏ (nguồn learn.leighcotnoir.com).Giá trị (Value) kiểm soát độ sáng tối của màu sắc. Độ sáng tối của màu nằm trong khoảng từ 0 đến 100% (Trong một số tài liệu, thang đo này có giá trị thực nằm trong khoảng 0-1). Một màu có giá trị 0% là màu đen thuần khiết, trong khi màu có độ sáng 100% là màu sáng nhất có thể của màu đó, ứng với độ bão hòa.
Không gian màu HSV khá giống với cách con người cảm nhận màu sắc. Mô hình màu HSV thường được sử dụng khi chúng ta cần chọn một màu với một thang đo chính xác vì HSV đặc tả màu sắc tốt hơn nhưng thang đo khác liên quan đến màu sắc như mô hình màu RGB.
Biểu diễn một hình ảnh ở không gian màu HSV cũng không quá khác RGB đối với một ảnh. Lúc này ta có hàm là $f(x, y) =
3.3. Các không gian khác
Ngoài ra chúng ta còn có khác không gian màu khác như grayscale, CIE, CMYK tùy thuộc cho nhiều tình huống khác nhau.
Hình không gian màu CIE (nguồn Chandler Abraham ở medium.com)4. Thao tác cơ bản với ảnh
4.1. Thiết lập “khu vực quan tâm”:
Khi được cho một ảnh, ta có thể cắt các vùng gọi là “khu vực quan tâm” ra khỏi ảnh, chọn các một miền giá trị thuộc miền ban đầu.
Trước hết ta cần phải nhớ hệ tọa độ đối với một ảnh là hệ Oxy với điểm khác: Ox tia hướng xuống và Oy hướng sang phải (Hình 6):
Hình 7
Thế nên, giả sử ta có hình:
Hình 8 – Ảnh Lenna với diện tích 512×512
Nếu ta chọn vùng chữ nhật với thông số
Hình 9 – Khu vực quan tâm
Thao tác này rất hữu dụng để thực hiện thay đổi chỉ một hay một số vùng ảnh nhất định và áp lại vào ảnh ban đầu hay ảnh khác.
Các bạn có thể thử với code Python sau với ảnh của mình:
import cv2# Lấy ảnh ban đầuimg = cv2.imread(“name.png”)# Các tọa độx=130y=130h=250w=250# Cắt “Khu vực quan tâm”subimg = img
4.2. Chia kênh màu:
Nếu một ảnh có nhiều kênh màu thì có thể chia hẳn các kênh màu ấy ra thành các ảnh riêng biệt.
Xem thêm: Vulgar Là Gì – Nghĩa Của Từ Vulgar
Tiếp tục với ảnh Lenna, ta có thể cắt ảnh đó ra thành:
Hình 10
Nếu các bạn để ý thì sắc đỏ của ảnh màu Lenna (hình 7) rất đậm, và khi cắt ra thì tương ứng kênh màu đỏ rất sáng.
Các bạn có thể thử với code Python sau với ảnh của mình:
import cv2# Lấy ảnh ban đầuimg = cv2.imread(“name.png”)# Chia ảnh ra ba kênh màu Lam, Lục, Đỏb, g, r = cv2.split(img)# Chiếu ảnhcv2.imshow(“Blue channel”, b)cv2.imshow(“Green channel”, g)cv2.imshow(“Red channel”, r)cv2.waitKey(0)cv2.destroyAllWindows()5. Ảnh là một hàm so61:
5.1. Độ sáng & tương phản
$$ gleft(x,y
ight)=alphaast fleft(x,y
ight)+eta $$Với $f$ là hàm ảnh ban đầu và $alpha$, $eta$ là hai hằng số thực bất kì thì g sẽ là hàm ảnh kết quả tương ứng cho từng vị trí $(x, y)$, tức $f(x, y)$ là giá trị màu tại pixel $(x, y)$, với $alpha$, $eta$ được gọi là các hằng số gain, bias.
Ta có thể xem đó là việc thay đổi mức năng lượng của ảnh, và nó rất hữu dụng trong việc làm rõ ảnh cho mắt người để nhìn thấy những chi tiết khi ảnh hơi tối.
Hình 11 – Ảnh do Visem
Các bạn có thể thử với code Python sau với ảnh của mình:
import cv2import numpy as np# Lấy ảnh ban đầuimg = cv2.imread(“name.png”)# Các biến số cần thiếtalpha = 1.5beta = 2# Các thao tácnimg = np.round(alpha * img + beta) # Phải làm tròn để chỉ giữ số nguyênnimg = np.maximum(nimg, 0) # Số thấp nhất không được bé hơn 0nimg = np.minimum(nimg, 255) # Số lớn nhất không được lớn hơn 255nimg = nimg.astype(np.uint8) # Cuối cùng, các số của ma trận ảnh thuộc đoạn <0, 255># Chiếu ảnhcv2.imshow(“New image”, nimg)cv2.waitKey(0)cv2.destroyAllWindows()
5.2. Phối màu
$$gleft(x,y
ight)=left(1-alpha
ight)ast f_0left(x,y
ight)+alphaast f_1left(x,y
ight)$$
Với $f_0$, $f_1$ là những hàm ảnh cho trước và $alphainleft<0,1 ight>$ là hằng số thực thì $g$ sẽ là hàm ảnh kết quả tương ứng cho từng vị trí $(x, y)$.
Ta có thể thấy nếu tăng $alpha$ từ 0 đến 1 thì những giá trị của $f_0$ sẽ không còn ảnh hưởng tới kết quả $g$, $f_0$ ‘’rã’’ dần và $f_1$ hiện lên. Hiệu ứng sẽ ngược lại nếu giảm $alpha$. Hiệu ảnh phối ảnh được dùng rất nhiều trong phim ảnh.
Hình 12 – Ảnh Lenna và Richard Feynman được phối dần.
Các bạn có thể thử với code Python sau với ảnh của mình:
import numpy as npimport cv2# Lấy các ảnh ban đầulenna = cv2.imread(“name_1.png”)feynman = cv2.imread(“name_2.png”)# Các thông số cần thiếtalpha = 1dec = 0.02# Với nhiều giá trị alpha khác nhau từ 1 xuống 0:while alpha >= 0.0: # Phối ảnh img = (lenna * alpha + feynman * (1 – alpha)).astype(np.uint8) # Chiếu ảnh đã được phối cv2.imshow(“Frame”, img) cv2.waitKey(100) # Tiếp tục vòng lặp với một alpha khác alpha = alpha – deccv2.destroyAllWindows()
5.3. Nhiễu
$$gleft(x,y
ight)=fleft(x,y
ight)+etaleft(x,y
ight)$$
Với $f$ là hàm ảnh được thu và $eta$ là hàm ảnh gây nhiễu tạo bởi thiết bị ghi tín hiệu thì $g$ là ảnh thực mà ta có.
Tùy phương pháp và thiết bị ghi hình thì có thể xuất hiện các loại nhiễu:
Nhiễu gauss:
Hình 13 – Ảnh nhiễu Gauss.Nhiễu sạn:
Hình 14 – Ảnh nhiễu “salt-pepper” từ Wikipedia.Nhiễu có chu kì:
Hình 15 – Ảnh nhiễu có chu kì từ Wikipedia.
Để thử tương tác với nhiễu, các bạn có thể thí nghiệm với đoạn code tạo nhiễu Gauss sau đây bằng Python:
import numpy as npimport cv2# Lấy ảnh ban đầuimg = cv2.imread(“name.png”)# Tạo nhiễu Gaussgauss = np.random.normal(0,1,img.size)gauss = gauss.reshape(img.shape<0>,img.shape<1>,img.shape<2>).astype(“uint8”)# Ảnh sau khi đã thêm nhiễuimg_gauss = cv2.add(img, gauss)# Chiếu các ảnhcv2.imshow(“Noise”, gauss) # Phần nhiễucv2.imshow(“Noisy Image”, img_gauss) # Ảnh đã thêm phần nhiễucv2.waitKey(0)cv2.destroyAllWindows()
5.4. Khác biệt giữa các ảnh
$$gleft(x,y
ight)=mid f_{0left(x,y
ight)}-f_{1left(x,y
ight)}mid$$
Với $f_0$, $f_1$ là những hàm ảnh cho trước g sẽ là hàm ảnh kết quả tương ứng cho khác biệt giữa 2 ảnh ở từng vị trí $(x, y)$.
Hình 16 – Tìm khác biệt giữa 2 ảnh (nguồn pysource.com).
Tìm kiếm sự khác biệt giữa 2 ảnh được ứng dụng nhiều trong việc tìm “vật chuyển động” bằng cách so sánh khác biệt giữa ảnh thật và ảnh nền (Hình 17).
Xem thêm: ” Điêu Ngoa Là Gì ? Nói Điêu Là Sao? Nghĩa Của Từ Điêu Ngoa
Hình 17 – Khử phông nền với khác biệt ảnh (nguồn OpenCV.org).
Các bạn có thể thử với code Python sau với các ảnh của mình:
import cv2# Lấy các ảnh ban đầuimg_1 = cv2.imread(“name_1.png”)img_2 = cv2.imread(“name_2.png”)# Khác biệt ảnhdiff = cv2.subtract(img_1, img_2)# Chiếu ảnhcv2.imshow(“Diff Frame”, diff)cv2.waitKey(0)cv2.destroyAllWindows()6. ReferencesSách Digital Image Processing – Rafael C. Gonzalez, Richard E. Woods
https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65a
https://docs.opencv.org/3.4/d3/dc1/tutorial_basic_linear_transform.html
https://docs.opencv.org/3.4/d1/dc5/tutorial_background_subtraction.html