Ta sẽ nhắc lại các kiến thức đã học ở bài tuần 1:
- Ảnh số là một hàm với mảng 2 chiều f(x,y)f(x,y)f(x,y)
- Có nhiều loại ảnh số: chụp dùng cảm ứng ánh sáng, hoặc các loại sóng, hoặc hàm tùy chỉnh
- Và chúng ta cũng biết cài đặt thư viện: OpenCV, Python, Jupyter Notebook
- Định nghĩa: số hóa ảnh là biến đổi một ảnh (hay một hàm) liên tục trong không gian cũng như theo giá trị thành dạng số rời rạc.
- Có 2 bước:
- Lấy mẫu (sampling): đo giá trị trong các khoảng không gian
- Lượng tử hóa (quantization): ánh xạ cường độ (hoặc giá trị) đo được thành một số hữu hạn các mức rời rạc Để cho trực quan hơn, ta có thể xem ví dụ dưới đây:

Hình 2.16 a là hình ảnh một đối tượng ảnh liên tục mà ta muốn chuyển đổi sang dạng ảnh số gọi là ảnh gốc.
Hình 2.16 b thể hiện các giá trị độ lớn của ảnh gốc dọc theo đoạn thẳng AB.
Để lấy mẫu hàm này, ta sẽ chiếu đoạn AB lên một máy ảnh, với mỗi vạch là chỗ nhận điểm ảnh, (các bạn cứ coi như 1 tâm pin mặt trời nhận năng lượng mặt trời (nếu cường độ cao sẽ là 1 nếu không có sẽ là 0) như hình 2.16 c. Tập hợp các vị trí rời rạc đó cho ta một hàm đã được lấy mẫu.
Hình bên phải của 2.16 c là cho biết miền giá trị của cường độ chia thành 8 khoảng rời rạc hay còn gọi là số trạng thái điểm ảnh (trong máy tính được biểu diễn được tính ra là bit biểu diễn nên số trạng thái sẽ là bội của 2, ở trong trường hợp này là 8 – tương ứng là 3 bit). Lượng tử hóa bằng các thực hiện làm tròn giá trị cường độ vào 1 trong 8 khoảng rời rạc đó.
Sau khi thực hiện lấy mẫu và lượng tử hóa, ta có kết quả như sau:
Mức độ lượng tử hóa: Số lượng mức xám được yêu cầu trên một bức ảnh số tương ứng với số lượng bits trên mỗi pixel
Ảnh số thường được lượng tử hoá thành 256 mức xám
Nhận biết bước xám (Tonal level perception)
Nếu mức xám dùng 8 bit nó sẽ là dải liên tục. 
Biến đổi gamma
vout=vinγv_{out} = v_{in}^gammavout=vinγ
vinv_{in}vin : độ sáng thực tế (actual luminance value)
voutv_{out}vout: độ sáng cảm nhận (output luminance value) 
Ta sẽ có các ví dụ sau:
Cho dải màu xám 16 mức, với gamma = 1 thì nó sẽ giữ nguyên như sau:
Link code : here
# Không điều chỉnh gamma (no adjustment) draw_quantization_img( adjust_gamma(gray_16, gamma=1), height=2 )
Với gamma > 1, ta thấy nếu giá trị đầu vào là tối (thấp) thì đẩu ra là tối hơn, ví dụ đầu vào là giá trị 17 thì đầu ra là giá trị 0:
Link code: here
#with gamma >1, the levels are shifted toward the the darker end of the spectrum draw_quantization_img( adjust_gamma(gray_16, gamma=2.2), height=2 )
Với gamma < 1, các giá trị đầu vào là thấp thì đẩu ra sáng hơn, ví dụ đầu vào là 17 đầu ra là giá trị 74:
Link code: here
#with gamma < 1, lighter draw_quantization_img( adjust_gamma(gray_16, gamma=1/2.2, debug=True), height=2 )

Sử dụng gamma để điều chỉnh độ tương phản
1. Độ tương phản thấp (Low exposure)
Ví dụ ảnh vào là một ảnh tối như sau:
Thì ta cần chỉnh độ sáng lên thì cần gamma < 1:
def adjust_image_gamma(image, gamma = 1.0): image = np.power(image, gamma) max_val = np.max(image.ravel()) image = image/max_val * 255 image = image.astype(np.uint8) return image
Link: here
Ta thử với 1 số giá trị. Với gamma = 0.45
low_adjusted = adjust_image_gamma(low, 0.45) plt.imshow(low_adjusted[:,:,::-1])
Kết quả sẽ như sau, nhìn trông tốt hơn trước : 
Nếu như gamma quá nhỏ thì sao?
Link code: here
# what if gamma is too low? low_adjusted = adjust_image_gamma(low, 0.1) plt.imshow(low_adjusted[:,:,::-1])
Kết quả thì nó quá sáng: 
Ta thử đo thời gian với hàm adjust_image_gamma:
%timeit low_adjusted = adjust_image_gamma(low, 0.1) # kq: 1 loop, best of 3: 2.51 s per loop
Nó rất tốn thời gian, có cách nào nhanh hơn không ?. Thật ra là có . Nó sẽ như sau:
Link code: here
#faster way to compute #reference: https://www.pyimagesearch.com/2015/10/05/opencv-gamma-correction/ def adjust_image_gamma_lookuptable(image, gamma=1.0): # build a lookup table mapping the pixel values [0, 255] to # their adjusted gamma values table = np.array([((i / 255.0) ** gamma) * 255 for i in np.arange(0, 256)]).astype(“uint8”) # apply gamma correction using the lookup table return cv2.LUT(image, table)
Ý tưởng ở đây là dùng bảng chuyển look-up table (LUT) sử dụng hàm cv2.LUT().
Thời gian chạy với hàm này sẽ là :
%timeit adjust_image_gamma_lookuptable(low, 0.45) #kq: 10 loops, best of 3: 27.6 ms per loop
Tốc độ rất nhanh ( 27.6 ms >> 2.51s)
2. Độ tương phản cao (Overexposure)
Với trường hợp này thì ta cần giảm độ sáng xuống, hay tăng độ tối. Vì vậy, sử dụng gamma > 1:
Cho ảnh đầu vào :
Ở đây sử dụng gamma = 4.
adjusted_high = adjust_image_gamma_lookuptable(high, 4) plt.imshow(adjusted_high[:,:,::-1])
Kết quả đẩu ra:
Correct using pixel transform
Reference: https://docs.opencv.org/3.4/d3/dc1/tutorial_basic_linear_transform.html
Dùng phép toán nhân và cộng g(x)=αf(x)+βg(x) = alpha f(x) + betag(x)=αf(x)+β
αalphaα và βbetaβ còn được gọi là tham số gain và bias, hoặc tham số để điều chỉnh contrast (độ tương phản) và brightness (độ sáng)
Với ảnh số: g(i,j)=α⋅f(i,j)+βg(i, j) = alpha cdot f(i, j) + betag(i,j)=α⋅f(i,j)+β
Đầu vào vẫn là ảnh Overexposure. Link code: here
def pixel_transform(image, alpha = 1.0, beta = 0): ”’ out[pixel] = alpha * image[pixel] + beta ”’ output = np.zeros(image.shape, image.dtype) h, w, ch = image.shape for y in range(h): for x in range(w): for c in range(ch): output[y,x,c] = np.clip(alpha*image[y,x,c] + beta, 0, 255) return output transformed_high = pixel_transform(high, 0.5, 20) plt.imshow(transformed_high[:,:,::-1])
Kết quả đầu ra sẽ là :
Có một cách dùng thư viện của opencv để nhanh hơn:
#anyway, a faster transformed_high = cv2.convertScaleAbs(high, 20, 0.5) plt.imshow(transformed_high[:,:,::-1])
Image negatives
Ta có thể chuyển từ ảnh bên trái sang bên phải ( đổi đen thành trắng và trắng thành đen )

Nghĩ có về khó khăn nhưng thật ra rất đơn giản:
negation = 255 – xray plt.imshow(negation, cmap=’gray’)
Combining images
1. Combination of different exposures for high-dynamic range imaging
Ta có 4 ảnh với 4 độ sáng khác nhau:
Ta sẽ kết hợp tính giá trị trung bình để tạo ra 1 ảnh mới đẹp hơn.
Link code: here
#Averaging to enhance contrast hdr = np.mean(stack, axis=0) hdr = hdr.astype(np.uint8) plt.rcParams[‘figure.figsize’] = [8, 8] plt.imshow(hdr[:,:,::-1])
Kết quả sẽ ra như sau: 
2. Phép trừ ảnh:
Để tìm ra sự khác biệt giữa 2 ảnh với nhau. Đâu tiên ta sẽ trừ 2 ảnh sau đó tăng độ tương phản để nhìn rõ sự khac nhau hơn: 
3. Video background subtraction
Từ phép trừ ảnh, ta ứng dụng váo video để tìm sự khác biệt khung hình trước và sau:
Github: here
Colab: Here
Slide: Here
Intensity Transformation Operations on Images
Bài viết đến đây đã dài, nếu có thắc mắc hoặc sai sót gì các bạn có thể comment xuống dưới. Bài Tiếp theo chúng ta tìm hiểu Histogram. Xin chào và hẹn gặp lại các ban.
