Clahe là gì

In this section,

  • We will learn the concepts of histogram equalization and use it to improve the contrast of our images.

Theory

Consider an image whose pixel values are confined to some specific range of values only. For eg, brighter image will have all pixels confined to high values. But a good image will have pixels from all regions of the image. So you need to stretch this histogram to either ends [as given in below image, from wikipedia] and that is what Histogram Equalization does [in simple words]. This normally improves the contrast of the image.

image

I would recommend you to read the wikipedia page on Histogram Equalization for more details about it. It has a very good explanation with worked out examples, so that you would understand almost everything after reading that. Instead, here we will see its Numpy implementation. After that, we will see OpenCV function.

import numpy as np

import cv2 as cv

from matplotlib import pyplot as plt

img = cv.imread['wiki.jpg',0]

hist,bins = np.histogram[img.flatten[],256,[0,256]]

cdf = hist.cumsum[]

cdf_normalized = cdf * float[hist.max[]] / cdf.max[]

plt.plot[cdf_normalized, color = 'b']

plt.hist[img.flatten[],256,[0,256], color = 'r']

plt.xlim[[0,256]]

plt.legend[['cdf','histogram'], loc = 'upper left']

plt.show[]

image

You can see histogram lies in brighter region. We need the full spectrum. For that, we need a transformation function which maps the input pixels in brighter region to output pixels in full region. That is what histogram equalization does.

Now we find the minimum histogram value [excluding 0] and apply the histogram equalization equation as given in wiki page. But I have used here, the masked array concept array from Numpy. For masked array, all operations are performed on non-masked elements. You can read more about it from Numpy docs on masked arrays.

cdf_m = np.ma.masked_equal[cdf,0]

cdf_m = [cdf_m - cdf_m.min[]]*255/[cdf_m.max[]-cdf_m.min[]]

cdf = np.ma.filled[cdf_m,0].astype['uint8']

Now we have the look-up table that gives us the information on what is the output pixel value for every input pixel value. So we just apply the transform.

Now we calculate its histogram and cdf as before [ you do it] and result looks like below :

image

Another important feature is that, even if the image was a darker image [instead of a brighter one we used], after equalization we will get almost the same image as we got. As a result, this is used as a "reference tool" to make all images with same lighting conditions. This is useful in many cases. For example, in face recognition, before training the face data, the images of faces are histogram equalized to make them all with same lighting conditions.

Histograms Equalization in OpenCV

OpenCV has a function to do this, cv.equalizeHist[]. Its input is just grayscale image and output is our histogram equalized image.

Below is a simple code snippet showing its usage for same image we used :

image

So now you can take different images with different light conditions, equalize it and check the results.

Histogram equalization is good when histogram of the image is confined to a particular region. It won't work good in places where there is large intensity variations where histogram covers a large region, ie both bright and dark pixels are present. Please check the SOF links in Additional Resources.

CLAHE [Contrast Limited Adaptive Histogram Equalization]

The first histogram equalization we just saw, considers the global contrast of the image. In many cases, it is not a good idea. For example, below image shows an input image and its result after global histogram equalization.

image

It is true that the background contrast has improved after histogram equalization. But compare the face of statue in both images. We lost most of the information there due to over-brightness. It is because its histogram is not confined to a particular region as we saw in previous cases [Try to plot histogram of input image, you will get more intuition].

So to solve this problem, adaptive histogram equalization is used. In this, image is divided into small blocks called "tiles" [tileSize is 8x8 by default in OpenCV]. Then each of these blocks are histogram equalized as usual. So in a small area, histogram would confine to a small region [unless there is noise]. If noise is there, it will be amplified. To avoid this, contrast limiting is applied. If any histogram bin is above the specified contrast limit [by default 40 in OpenCV], those pixels are clipped and distributed uniformly to other bins before applying histogram equalization. After equalization, to remove artifacts in tile borders, bilinear interpolation is applied.

Below code snippet shows how to apply CLAHE in OpenCV:

import numpy as np

import cv2 as cv

img = cv.imread['tsukuba_l.png',0]

clahe = cv.createCLAHE[clipLimit=2.0, tileGridSize=[8,8]]

cl1 = clahe.apply[img]

cv.imwrite['clahe_2.jpg',cl1]

See the result below and compare it with results above, especially the statue region:

image

Additional Resources

  1. Wikipedia page on Histogram Equalization
  2. Masked Arrays in Numpy

Also check these SOF questions regarding contrast adjustment:

Exercises

Mình đang mò mẫn nghiên cứu mấy cái giải thuật xử lý ảnh, đến đoạn Histogram Equalization thì tìm trên google cũng khá dễ hiểu, nhưng mức cao cấp hơn là Adaptive Histogram Equalization và Contrast Limited Adaptive Histogram Equalization thì bí hẳn.
Mọi người, ai có kinh nghiệm trong lĩnh vực này có thể giúp mình được không?

2 Likes

Cân bằng biểu đồ là một kỹ thuật đơn giản để nâng cao hình ảnh kỹ thuật số. Nó là một công cụ tiêu chuẩn trong các ứng dụng xử lý hình ảnh kỹ thuật số và thị giác máy tính. Nó đặc biệt hiệu quả trong việc cải thiện chất lượng hình ảnh của hình ảnh thang độ xám. Ví dụ, cân bằng biểu đồ đã được áp dụng rộng rãi trong hình ảnh y tế để cải thiện độ tương phản của hình ảnh X-quang và MRI. Cải tiến như vậy cho phép chẩn đoán y tế chính xác hơn.

Trong bài viết này, tôi sẽ giới thiệu khái niệm cơ bản về cân bằng biểu đồ. Chúng ta cũng sẽ xem xét thuật toán và cách triển khai trong Python. Vì lợi ích của những người không quen thuộc với miền này, tôi đã bao gồm một tổng quan ngắn gọn về hình ảnh kỹ thuật số và biểu đồ.

Đề cương

  1. Hình ảnh kỹ thuật số. Tổng quan nhanh về biểu diễn hình ảnh kỹ thuật số.
  2. Biểu đồ là gì? Giới thiệu về biểu đồ và tính toán của nó.
  3. Biểu đồ của hình ảnh có độ tương phản thấp. Kiểm tra biểu đồ của các hình ảnh có độ tương phản thấp, để hiểu vai trò của cân bằng biểu đồ.
  4. Biểu đồ cân bằng. Khái niệm cơ bản để nâng cao độ tương phản của hình ảnh.
  5. Thuật toán cốt lõi.
  6. Triển khai Python. Một triển khai đơn giản của việc cân bằng biểu đồ từ đầu với các thư viện NumPy và Pillow.
  7. Các kết quả. Chúng tôi đã thực hiện cân bằng biểu đồ với mã Python của mình và kiểm tra kết quả.

Giả sử bạn muốn vẽ một sinh vật màu vàng, một mắt, mặc quần áo màu xanh da trời, gọi là minion. Bạn sẽ vẽ chỉ bằng các chấm màu . Bạn bắt đầu vẽ bằng cách tạo những chấm nhỏ bằng bút màu trên một tờ giấy. Các chấm màu được sắp xếp để tạo thành hình ảnh của một minion mà bạn muốn hình dung. Hình ảnh kết quả có thể trông giống như hình dưới đây. Điều này tương tự như cách hình ảnh được hiển thị bởi màn hình máy tính.

Hình ảnh kỹ thuật số bao gồm các phần tử rời rạc được gọi là pixel . Mỗi pixel được biểu diễn bằng [các] giá trị cường độ và chiếm một vị trí duy nhất trong mặt phẳng hình ảnh 2D. Trong hình ảnh thang độ xám, mỗi pixel được biểu thị bằng một giá trị cường độ duy nhất nằm trong khoảng từ 0 đến 255. Các pixel có giá trị cường độ tối thiểu sẽ xuất hiện dưới dạng pixel đen. Khi giá trị cường độ tăng lên, pixel sẽ sáng hơn với các sắc thái xám khác nhau. Các điểm ảnh có giá trị cường độ tối đa xuất hiện dưới dạng các điểm ảnh màu trắng.

Hình ảnh màu phức tạp hơn một chút. Mỗi pixel được biểu thị bằng ba giá trị cường độ thể hiện cường độ của các thành phần màu: đỏ, lục và lam. Thay đổi tỷ lệ và cường độ của các màu cơ bản này cho phép thể hiện các màu khác nhau trong pixel.

2. Biểu đồ là gì?

Biểu đồ thể hiện sự phân bố tần suất của dữ liệu. Nó thường được hình dung như một biểu đồ thanh. Tôi sẽ sử dụng hình ảnh minion ở trên để minh họa những điểm này. Kích thước của hình ảnh là 22x37 pixel, cho tổng số 814 pixel. Giả sử chúng ta đang sống trong một thế giới chỉ có năm màu có thể có: đen, xám, trắng, vàng và xanh lam. Để có được biểu đồ, chúng ta có thể đếm số lượng pixel cho mỗi màu có thể:

  • đen - 34 pixel
  • xám - 12 pixel
  • trắng - 646 điểm ảnh
  • màu vàng - 76 điểm ảnh
  • xanh lam - 46 pixel

3. Biểu đồ của hình ảnh có độ tương phản thấp

Để hiểu vai trò của cân bằng biểu đồ, chúng ta sẽ xem xét hai trường hợp ảnh có độ tương phản thấp. Đối với mỗi hình ảnh, biểu đồ [biểu đồ màu xanh lam] và biểu đồ tích lũy [ biểu đồ màu cam] được hiển thị. Biểu đồ tích lũy chỉ đơn giản là tổng đang chạy của tần suất biểu đồ từ thùng đầu tiên đến thùng cuối cùng. Biểu đồ tích lũy được thu nhỏ lại, để có thể vẽ biểu đồ theo cùng tỷ lệ với biểu đồ.

Trường hợp 1: Hình ảnh xuất hiện quá sáng

Hình ảnh dưới đây trông tươi sáng nhưng bị mờ. Lời giải thích có thể được tìm thấy trong biểu đồ. Các cường độ điểm ảnh tập trung ở vùng trên của dải, khoảng từ 125 đến 200. Trong vùng này, các điểm ảnh được tô bóng nhẹ do đó xuất hiện sáng. Do phạm vi cường độ hẹp, các điểm ảnh có sắc thái rất giống nhau, dẫn đến sự xuất hiện mờ nhạt. Trong vùng hẹp này, biểu đồ tích lũy đang tăng với độ dốc lớn trong khi bằng phẳng ở những nơi khác.

Trường hợp 2: Hình ảnh xuất hiện quá tối

Hình ảnh dưới đây trông khá tối và u ám. Nhìn vào biểu đồ, các cường độ tập trung ở vùng thấp hơn của phạm vi, khoảng từ 5 đến 95. Trong vùng này, các điểm ảnh có sắc thái tối hơn. Cũng có thể quan sát thấy rằng biểu đồ tích lũy đang tăng mạnh ở vùng này và bằng phẳng ở nơi khác.

Trong cả hai trường hợp, phân tích biểu đồ cho thấy rằng trong các hình ảnh có độ tương phản thấp:

  • cường độ pixel được tập trung trong một vùng hẹp dẫn đến các pixel có sắc thái tương tự, làm cho hình ảnh có vẻ mờ nhạt và
  • biểu đồ tích lũy tăng với độ dốc lớn trong một vùng hẹp và bằng phẳng ở những nơi khác.

Độ tương phản của hình ảnh được nâng cao khi các sắc thái khác nhau trong hình ảnh trở nên rõ ràng hơn. Chúng ta có thể làm như vậy bằng cách làm tối các sắc độ của các điểm ảnh tối hơn và ngược lại. Điều này tương đương với việc mở rộng phạm vi cường độ pixel. Để có độ tương phản tốt, cần có các đặc điểm biểu đồ sau:

  • các cường độ pixel được phân phối đồng đều trên toàn bộ phạm vi giá trị [mỗi giá trị cường độ đều có thể xảy ra như nhau] và
  • biểu đồ tích lũy đang tăng tuyến tính trên toàn dải cường độ.

5. Thuật toán cốt lõi

Đầu tiên, chúng tôi tính toán biểu đồ chuẩn hóa của hình ảnh. Quá trình chuẩn hóa được thực hiện bằng cách chia tần số của mỗi bin cho tổng số pixel trong ảnh. Do đó, giá trị lớn nhất của biểu đồ tích lũy là 1. Hình dưới đây cho thấy biểu đồ tích lũy chuẩn hóa của cùng một hình ảnh có độ tương phản thấp được trình bày như Trường hợp 1 trong Phần 3.

Bước 2: Tìm bảng tra cứu ánh xạ cường độ

Tiếp theo, chúng tôi lấy một bảng tra cứu ánh xạ cường độ pixel để đạt được đặc điểm biểu đồ cân bằng. Nhớ lại rằng biểu đồ tích lũy cân bằng đang tăng tuyến tính trên toàn bộ dải cường độ. Đối với mỗi mức cường độ rời rạc i , giá trị pixel được ánh xạ được tính từ biểu đồ tích lũy chuẩn hóa theo:

mapped_pixel_value [i] = [L-1] * normalized_cummental_histogram [i]

trong đó L = 256 cho biểu diễn số nguyên không dấu 8 bit điển hình của cường độ pixel.

Như một trực giác về cách ánh xạ hoạt động, hãy tham khảo biểu đồ tích lũy chuẩn hóa được hiển thị trong hình trên. Giá trị cường độ pixel tối thiểu là 125 được chuyển thành 0,0. Giá trị cường độ pixel tối đa là 200 được chuyển đổi thành 1,0. Tất cả các giá trị ở giữa được ánh xạ tương ứng giữa hai giá trị này. Sau khi nhân với giá trị cường độ tối đa có thể có [255], các cường độ pixel thu được hiện được phân phối trên toàn dải cường độ.

Bước 3: Chuyển đổi cường độ pixel của ảnh gốc bằng bảng tra cứu

Khi bảng tra cứu được bắt nguồn, cường độ của tất cả các pixel trong hình ảnh được ánh xạ tới các giá trị mới. Kết quả là một hình ảnh cân bằng.

6. Triển khai Python

Cân bằng biểu đồ có sẵn như hoạt động tiêu chuẩn trong các thư viện xử lý hình ảnh khác nhau, chẳng hạn như openCV và Pillow. Tuy nhiên, chúng tôi sẽ thực hiện thao tác này từ đầu. Chúng ta sẽ cần hai thư viện Python: NumPy để tính toán số và Pillow cho I / O hình ảnh. Cách dễ nhất để cài đặt các thư viện này là thông qua trình cài đặt gói Python . Nhập các lệnh sau trên thiết bị đầu cuối của bạn và bạn đã sẵn sàng! pip

pip install numpy pip install pillow

I / O hình ảnh

Để đọc và ghi vào tệp hình ảnh, chúng tôi sẽ sử dụng thư viện Pillow. Nó đọc các tệp hình ảnh dưới dạng Imageđối tượng. Các đối tượng này có thể được chuyển đổi dễ dàng sang mảng NumPy và viceversa. Các hoạt động I / O bắt buộc được mã hóa như sau. Để đơn giản, hãy để tên tệp hình ảnh là input_image.jpg nằm trong cùng thư mục với tập lệnh Python.

import numpy as np from PIL import Image img_filename = 'input_image.jpg' save_filename = 'output_image.jpg' #load file as pillow Image img = Image.open[img_filename] # convert to grayscale imgray = img.convert[mode='L'] #convert to NumPy array img_array = np.asarray[imgray] #PERFORM HISTOGRAM EQUALIZATION AND ASSIGN OUTPUT TO eq_img_array #convert NumPy array to pillow Image and write to file eq_img = Image.fromarray[eq_img_array, mode='L'] eq_img.save[save_filename]

Thuật toán chính chỉ có thể được thực hiện trong một số dòng mã. Trong ví dụ này, bảng tra cứu ánh xạ cường độ được triển khai dưới dạng danh sách 1D trong đó chỉ mục đại diện cho cường độ pixel hình ảnh gốc. Phần tử ở mỗi chỉ mục là giá trị được biến đổi tương ứng. Cuối cùng, có nhiều cách khác nhau để thực hiện ánh xạ cường độ pixel. Tôi đã sử dụng khả năng hiểu danh sách bằng cách làm phẳng và định hình lại mảng hình ảnh 2D trước và sau khi ánh xạ.

""" STEP 1: Normalized cumulative histogram """ #flatten image array and calculate histogram via binning histogram_array = np.bincount[img_array.flatten[], minlength=256] #normalize num_pixels = np.sum[histogram_array] histogram_array = histogram_array/num_pixels #cumulative histogram chistogram_array = np.cumsum[histogram_array] """ STEP 2: Pixel mapping lookup table """ transform_map = np.floor[255 * chistogram_array].astype[np.uint8] """ STEP 3: Transformation """ # flatten image array into 1D list img_list = list[img_array.flatten[]] # transform pixel values to equalize eq_img_list = [transform_map[p] for p in img_list] # reshape and write back into img_array eq_img_array = np.reshape[np.asarray[eq_img_list], img_array.shape]

Hãy xem kết quả cân bằng biểu đồ cho hai hình ảnh được trình bày trong Phần 3. Đối với mỗi kết quả, hai hình ảnh trên hiển thị hình ảnh gốc và hình ảnh cân bằng. Sự cải thiện độ tương phản được quan sát rõ ràng. Hai hình ảnh phía dưới hiển thị biểu đồ và biểu đồ tích lũy, so sánh các hình ảnh gốc và đã cân bằng. Sau khi cân bằng biểu đồ, cường độ pixel được phân phối trên toàn bộ phạm vi cường độ. Biểu đồ tích lũy đang tăng tuyến tính như mong đợi, đồng thời thể hiện mô hình cầu thang. Điều này được mong đợi vì cường độ pixel của hình ảnh gốc được kéo dài ra một phạm vi rộng hơn. Điều này tạo ra khoảng trống của các thùng có tần suất bằng không giữa các thùng khác 0 liền kề, xuất hiện dưới dạng đường phẳng trong biểu đồ tích lũy.

Trường hợp 1: Không cân bằng_Hawkes_Bay_NZ.jpg

Trường hợp 2: lena_dark.png

Kết luận

Trong bài viết này, chúng ta đã xem xét thuật toán cân bằng biểu đồ cơ bản và cách triển khai. Vì nó được thực hiện dựa trên biểu đồ của toàn bộ hình ảnh, nó thường được gọi là cân bằng biểu đồ toàn cục . Nó là một công cụ đơn giản và hiệu quả để tăng độ tương phản toàn cầu của hình ảnh. Tuy nhiên, nếu hình ảnh có tiếng ồn, chúng cũng sẽ được khuếch đại. Có một số biến thể thuật toán để giải quyết vấn đề này, chẳng hạn như cân bằng biểu đồ thích ứng [AHE] và cân bằng biểu đồ thích ứng có giới hạn tương phản [ CLAHE ]. Tuy nhiên, đây là những chủ đề cho một bài báo khác!

Video liên quan

Chủ Đề