- vừa được xem lúc

Tuần 3: Histogram - Histogram equalization

0 0 48

Người đăng: Nguyễn Tiến Đạt

Theo Viblo Asia

Xin chào các bạn, hôm nay chúng ta sẽ cùng tìm hiểu về histogram, cân bằng biểu đô mức xám và phân loại ảnh sử dụng histogram.

Ôn lại bài tuần 2

Đâu tiên, chúng ta sẽ điểm qua các kiến thức về phép toán trên điểm ảnh trong bài viết trước.

  • Lấy mẫu, lượng tử hóa
  • Biến đổi trên điểm ảnh -> chỉnh độ sáng, độ tương phản
    • Gamma
    • Negation
  • Kết hợp ảnh
    • Tính trung bình
    • Trừ background

Histogram

1. Khái niệm

Histogram (lược đồ xám) là biểu đồ tần xuất thống kê số lần xuất hiện các mức sáng trong ảnh.

2. Cách tính histogram

  • rkr_{k} là mức xám của ảnh f(x,y)f(x,y)
  • nkn_{k} là số điểm ảnh (pixels) có giá trị rkr_{k}
  • Biểu đồ mức xám chưa chuẩn hóa (unnormalized histogram) của ff được định nghĩa như sau: h(rk)=nkh(r_{k}) = n_{k} với k=0,1,...,L1k = 0, 1,..., L-1, LL là số mức xám.
  • Biểu đồ chuẩn hoá (normalized histogram): p(rk)=h(rk)MN=nkMNp(r_{k}) = \frac{h(r_{k})}{MN} = \frac{n_{k}}{MN} với M, N là chiều dài và chiều rộng của ff hay là của ảnh

3. Ví dụ

Ta lần lượt có ảnh và histogram tương ứng với các ảnh drank, light, low-contrast và high-contrast

Ta có nhận xét

  • Với ảnh dark thì histogram có các cột tập trung vào bên trái tương ứng với màu tối
  • Với ảnh light thì histogram có tập trung vào bên phải chứa các pixel trắng
  • Với ảnh độ tương phản thấp (low-contrast) thì histogram có các cột tập trung xít nhau và ở giữa
  • Với ảnh độ tương phản cao (high-contrast) thì histogram san đều với các giá trị

4. Code

Giả sử ta có bức ảnh độ tương phản như sau:

Ta bắt đầu import thư viện và load ảnh.

import numpy as np import cv2 import matplotlib.pyplot as plt %matplotlib inline
plt.rcParams['figure.figsize'] = [10,8]
img = cv2.imread("low-exposure.jpg", 0)

Chúng ta bắt đầu thử bắt đầu code nào ?. Ta có 2 cách dùng hàm để tính histogram.

  1. Sử dụng cv2.calcHist từ thư viện OpenCV
# using cv2.calcHist()
hist = cv2.calcHist( [img], channels = [0], mask=None, # full image histSize=[256], #full scale ranges=[0,256]
)
plt.plot(hist)
  1. Sử dụng hàm numpy.histogram
#using numpy
h2 = np.histogram(img.ravel(), bins=256, range=[0,256])
print(h2[0].shape)
plt.plot(h2[0])

Và 2 cách trên đều ra kết quả như sau:

Histogram equalization (cân bằng biểu đồ mức xám)

1. Khái niệm

Phần này là phần mình giới thiệu và chứng minh công thức, nếu thấy quá dài dòng và khó hiểu bạn có thể xem luôn phần các bước làm.?

Trong trường hợp ảnh là một hàm liên tục, ta xét biến rr đại diện cho các cấp độ xám của ảnh cần được cân bằng và rr trong khoảng [0,L1][0,L-1] với r=0r = 0 đại diện cho đen và r=L1r =L-1 đại điện cho trắng. Cân bằng biểu đồ mức xám là tìm một ánh xạ s=T(r)s= T(r) khi đó mỗi điểm ảnh có giá trị rr trong ảnh ban đầu sẽ được ánh xạ tạo nên cấp độ ss trong ảnh đẩu ra.

Ta cần tìm hàm T(r)T(r) thỏa mãn các điều kiện sau:

  1. T(r)T(r) là hàm đơn vị và đơn điệu tăng trong khoảng 0rL10\leqslant r \leqslant L -1
  2. 0T(r)L10\leqslant T(r) \leqslant L -1 với 0rL10\leqslant r \leqslant L -1

Ở đây ta định nghĩa hàm pr(r)p_{r}(r)ps(s)p_{s}(s) lần lượt biểu diễn hàm mật độ xác suất của các biến ngẫu nhiên rrss. Kết quả cơ bản từ lý thuyết xác suất là nếu cho trước pr(r)p_r(r)T(r)T(r) , T1(s)T^{-1}(s) thỏa mãi điều kiện 1. thì hàm mật độ xác xuất ps(s)p_{s}(s) có thể thu được bằng cách sử dụng công thức sau:

Do đó, hàm mật độ xác suất của ss, được quyết định bởi cấp độ xám PDF của ảnh đầu vào và hàm biến đổi đã chọn. Một hàm biến đổi quan trọng trong xử lý ảnh có dạng:

Đẳng thức bên phải của phương trình trên được gọi là hàm phân phối tích lũy của biến ngẫu nhiên rr, nó đơn điệu tăng thỏa mãn điều kiện 1). Tương tự, tích phân của hàm mật độ xác suất trong khoảng [0,L1][0, L-1] cũng nằm trong khoảng [0,L1][0, L-1] nên điều kiện 2 được thỏa mãn. Ta có:

Thay kết quả này cho dsdr\frac{d_{s}}{d_{r}} cho phương trình (3 -10), và do tất cả các giá trị xác suất đều dương, ta thu được:

Ta thấy ps(s)p_{s}(s) là hàm phân bố xác suất đều, từ đó có thể kết luận rằng việc thực hiện phép biến đổi (3-14) đã sinh ra biến ngẫu nhiên ss với hàm phân bố xác suất đều.

Khi ảnh là các giá trị độ sáng rời rạc, ta làm việc với xác suất xuất hiện của từng giá trị độ sáng và phép toán tổng xác suất thay vì hàm mật độ xác suất và phép toán tích phân. Xác suất xuất hiện của mức xám rkr_{k} trong ảnh được tính xấp xỉ bằng pr(rk)=nkMNp_{r}(r_{k}) = \frac{n_{k}}{MN}. Lúc này công thức cho phép biến đổi tương tự trong phương trình (3-10) trên các giá trị rời rạc là:

Vậy sau 1 hồi dài dòng để tìm ra công thức ?, ta có các bước làm.

2. Các bước làm

  1. Tính toán histogram pr(r)p_{r}(r)
  2. Chuẩn hóa histogram cho về khoảng [0, 1] : pr(rk)=nkMNp_{r}(r_{k}) = \frac{n_{k}}{MN}
  3. Tính hàm xác suất mật độ
  4. Tính giá trị mức xám cho từng điểm ảnh: O(x, y) = round( T(I(x,y)) )

Ta có ví dụ để cho trực quan hơn. Ta có bảng phân phối cường độ và giá trị histogram cho hình ảnh kỹ thuật số 3 bit ảnh 64 * 64

Theo công thức ta sẽ tính được

L = 8

s0=T(r0)=7pr(n0)=1.33s_{0} = T(r_{0}) = 7 * p_{r} (n_{0})=1.33

Sau đó ta sẽ chuyển đổi giá trị của từng điểm ảnh như sau:

3. Code

Ta sẽ sử dụng bức ảnh bên trên để cân bằng histogram

Cách 1 ta dùng thủ công thì hàm cân bằng histogram như sau:

def hist_equalize(img): # 1. calclate hist hist = cv2.calcHist([img], [0], None, [256], [0, 256]) # 2. normalize hist h, w = img.shape[:2] hist = hist/(h*w) # 3. calculate CDF cdf = np.cumsum(hist) s_k = (255 * cdf - 0.5).astype("uint8") return s_k

Tiếp theo ta phải ánh xạ mức xám đầu vào với s_k:


s_k = hist_equalize(img)
equalized_img = cv2.LUT(img, s_k)
plot_img_and_hist(equalized_img)

Cách 2 ta sẽ dùng hàm của OpenCv như sau:

img_equalized = cv2.equalizeHist(img)
plot_img_and_hist(img_equalized)

Và kết quả ta sẽ được như sau, bên trai là ảnh đẩu ra và bên phải là histogram và cdf tương ứng.

Tài liệu tham khảo

  1. Xử lý ảnh - Lê Thanh Hà
  2. R. C. Gonzalez, R. E. Woods, “Digital Image Processing,” 4th edition, Pearson, 2018.
  3. Slide
  4. Code github: here

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 525

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 396

- vừa được xem lúc

Đặt tên commit message sao cho "tình nghĩa anh em chắc chắn bền lâu"????

. Lời mở đầu. .

1 1 737

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 358

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 449

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 433