Hình ảnh, một trong những dữ liệu quen thuộc chúng ta gặp hàng ngày. Dữ liệu hình ảnh số tồn tại khắp nơi xung quanh ta. Từ những tấm hình selfie, những video tiktok, những chiếc meme, cho đến những thước phim CGI, những bản vẽ khoa học, hay những bức tranh do AI sáng tạo. Dữ liệu ảnh còn là nền tảng quan trọng trong sự phát triển của công nghệ tiên tiến, như công nghệ chẩn đoán bệnh sớm qua ảnh chụp MRI hay công nghệ tự hành cho robot và ô tô. Vậy nhưng máy tính nhìn thấy hình ảnh như nào? Máy tính lưu trữ và xử lý hình ảnh để cho ra những tấm hình đẹp ra sao? Hãy cùng tìm hiểu nhé!
RGB viết tắt của red (đỏ), green (xanh lục), blue (xanh lam), là ba màu chính của ánh sáng khi tách ra từ lăng kính. Khi trộn ba màu trên theo tỉ lệ nhất định có thể tạo thành các màu khác nhau. Với mỗi bộ 3 số r, g, b nguyên trong khoảng [0, 255] sẽ cho ra một màu khác nhau. Nếu bộ 3 số r, g, b được biểu diễn là (r, g, b) thì mỗi (r, g, b) chính là một pixel (hay điểm ảnh). Ảnh chính là tập hợp của các pixel ấy. Ví dụ với bức ảnh 800×600 thì sẽ có 800*600= 480,000 pixel. Đối với ảnh xám, mỗi pixel chỉ cần biểu diễn bằng một giá trị nguyên trong khoảng từ [0,255] thay vì (r,g,b) như trong ảnh màu.
Với mỗi bức ảnh màu, chúng ta sẽ chia từng kênh màu (color channel) thành một ma trận riêng có kích thước bằng kích thước ảnh. Sau đó tổ chức dưới dạng một ma trận 3 chiều. Ví dụ một bức ảnh màu Full HD 1920 * 1080, ta có thể lưu nó thành một tensor (dạng dữ liệu có từ 3 chiều trở lên) kích thước 1920 * 1080 * 3, với số 3 chính là 3 kênh màu đỏ, lục, lam.
Ở phần này, mình sẽ giới thiệu một số kỹ thuật xử lý ảnh cơ bản:
– Chỉnh độ sáng: Trong ảnh thì màu tối nhất là màu đen [0, 0, 0], và sáng nhất là màu trắng [255, 255, 255]. Để thay đổi độ sáng, ta tăng giảm giá trị của từng pixel trong ảnh bằng phép cộng trừ đơn giản.
– Chỉnh độ tương phản: Đối với tương phản ta sẽ chia dải màu thành 2 nửa, một nửa thiên sáng và một nửa thiên tối. Để tăng tương phản, chúng ta sẽ khiến 2 dải màu khác biệt nhau hơn, nửa sáng sáng hơn, nửa tối tối hơn. Để giảm tương phản thì ngược lại, nửa tối sáng hơn, nửa sáng tối hơn.
– Grayscale: Như mình đã đề cập ở trên, ảnh đen trắng (grayscale) là ảnh chỉ có 1 kênh màu đen trắng thay vì 3 kênh. Để chuyển ảnh màu về đen trắng, ta sẽ dùng 3 giá trị của pixel gốc để tính giá trị của pixel mới. Công thức là: grayscale = 0.299R + 0.587G + 0.114B.
– Crop: Chúng ta chọn một vùng trên ảnh bằng cách xác định tọa độ 2 điểm, 2 điểm này là 2 góc của vùng hình chữ nhật. Sau đó thì ta “cắt” vùng hình chữ nhật ấy ra tạo thành một bức ảnh mới.
– Tịnh tiến (Translate): Tịnh tiến ảnh là di chuyển bức ảnh đi một đoạn. Ta xác định vector dời t = (tx, ty), sau đó ta lấy tọa độ từng điểm cộng với vector dời. Các pixel có tọa độ vượt ra khỏi kích thước sẽ bị loại bỏ, những vị trí mà không có pixel nào dời đến sẽ được đặt bằng một giá trị khác (ví dụ màu đen).
– Co dãn (Scale): Ta có thể tăng hoặc giảm kích thước của ảnh bằng cách xác định các hệ số dãn của mỗi chiều. Sau đó lấy ảnh gốc nhân với hệ số dãn để tạo thành bức ảnh mới.
– Xoay (Rotate): Để xoay ảnh, ta cần xác định được góc xoay θ. Vị trí mới của pixel được tính bởi công thức:
– Shear: Phép biến đổi này sẽ biến dạng ảnh thành một hình thang. Ta xác định hệ số shear Shx và Shy, tọa độ mới của điểm ảnh được tính bởi công thức:
– Biến đổi phối cảnh (Perspective transform): Đây là phép thay đổi vị trí 4 góc của ảnh. Khá giống với khi bạn chụp tài liệu, có thể chọn 4 góc trong ảnh để kéo dãn phẳng chúng ra. Dựa trên sự thay đổi của 4 điểm góc trước và sau khi biến đổi, ta tìm ra ma trận biến đổi H. Sau đó ta tính tọa độ và kích thước mới của từng pixel bằng cách nhân ma trận tọa độ gốc với ma trận biến đổi H.
# Phép tính tích chập – convolution
Để thực hiện phép tích chập, ta sẽ dùng 1 cửa sổ trượt (Sliding Window) hay còn gọi là kernel để “trượt” qua toàn bộ bức ảnh, từ đó thu được bức ảnh khác có kích thước nhỏ hơn.
Trong phép tính tích chập cho ảnh, chúng ta sẽ có một vài tham số như kích thước kernel (k), stride (s) và padding (p).
Kích thước kernel có thể thay đổi, ví dụ như với k = 5 thì có kernel 5 * 5. Đối với ảnh có màu, kernel có thể là tensor, ví dụ 3 * 3 * 3 (với k = 3) hay 5 * 5 * 3 (với k = 5).
Bạn có thể “nhảy cóc” và bỏ qua các pixel giữa các lần nhảy bằng cách thay đổi stride.
Khi áp kernel lên các pixel ở cạnh biên, chúng sẽ không có đủ pixel xung quanh để tính. Khi này hoặc là bỏ qua chúng, hoặc là thêm một số pixel “viền” xung quanh ảnh, phần pixel được thêm vào được gọi là padding. Ví dụ với p = 1, chúng ta sẽ thêm phần viền với độ dày 1 pixel. Giá trị phần viền thường là giá trị của pixel biên, một hằng số (ví dụ: tất cả = 128), hoặc có thể quy định riêng.
Các tham số trên sẽ ảnh hưởng tới kích thước của ảnh output, bạn có thể tính độ dài mỗi chiều của ảnh mới với công thức:
Với n là độ dài ban đầu của chiều đang xét, k là độ dài kernel chiều tương ứng, p là padding, s là stride.
Mỗi kernel khác nhau thì sẽ phép tính convolution sẽ có ý nghĩa khác nhau. Có thể kể đến như làm nét ảnh (sharpen), làm mờ ảnh (blur), tìm viền của các vùng trong ảnh (edge detection), …
Các bạn có thể thử một số kernel và hiệu ứng của chúng lên ảnh tại link sau: https://setosa.io/ev/image-kernels/
Các phương pháp xử lý ảnh trên, ngoài ứng dụng trong việc làm đẹp những tấm hình chúng ta chụp thường ngày, còn có rất nhiều ứng dụng quan trọng khác trong khoa học kỹ thuật. Các cách xử lý ảnh ở trên cũng chính là một phương pháp giúp tăng số lượng ảnh đầu vào cho các mô hình máy học, hay còn được biết đến là tăng cường dữ liệu (data augumentation). Hi vọng bài viết này có thể cung cấp cho bạn một cái nhìn sơ qua về thị giác máy tính, và giúp ích cho quá trình phát triển kỹ năng của bạn sau này.