Hướng dẫn local histogram equalization python

Môi trường làm việc với OpenCV

  • Linux (bài viết sử dụng Ubuntu 16.04)
  • OpenCV (bài viết sử dụng OpenCV 3.4.1)
  • Python (bài viết sử dụng Python 3.5.5)
  • Ảnh mẫu để xử lý: img_6.jpg

Bạn có thể download ảnh mẫu về:

Nội dung chính

  • Môi trường làm việc với OpenCV
  • Cân bằng sáng là gì?
  • Công dụng của cân bằng sáng
  • Giải thuật cân bằng sáng
  • Hiện thực Histogram Equalization
  • Histogram Equalization trong OpenCV

img_6.jpg (Nguồn: ảnh lụm từ FB Trang Đoàn)

Hướng dẫn local histogram equalization python

Cân bằng sáng là gì?

Cân bằng sáng (histogram equalization) là sự điều chỉnh histogram của ảnh về mức cân bằng.

Vậy, histogram của ảnh là gì? Hãy xem mục dưới nhé.

Histogram

Histogram của ảnh (intensity histogram) là biểu đồ cột thống kê số lần xuất hiện của các mức sáng trong ảnh.

  • Nói cách khác, histogram là biểu đồ thống kê tần suất xuất hiện của mức sáng.
  • Histogram thường được chuẩn hóa bằng cách: lấy mỗi cột chia cho giá trị tổng –> sau khi chuẩn hóa, tổng các giá trị cột trong histogram sẽ bằng 1.
  • Histogram đã chuẩn hóa mang ý nghĩa xác suất xuất hiện của các mức sáng trong ảnh.

Ví dụ histogram của 1 ảnh vẽ bằng MATLAB (trục x là mức sáng [0, 255] - intensity, trục y là số lần xuất hiện của mức sáng đó trong ảnh - frequency):

Công dụng của cân bằng sáng

Tác dụng của histogram equalization thường được dùng:

  • Cân bằng sáng thường được dùng ở bước tiền xử lý.
  • Nhằm giảm sự ảnh hưởng do chiếu sáng (chói), thiếu ánh sáng (ảnh tối), …
  • Ta có thể hiểu cân bằng sáng giúp ta "chuẩn hóa" ảnh đầu vào trước khi tiến hành xử lý.
  • Các giải thuật xử lý ảnh thường nhạy cảm với ánh sáng, cùng nội dung ảnh nhưng với các điều kiện ánh sáng khác nhau có thể làm sai lệch kết quả xử lý (giả sử trong bài toán phát hiện đối tượng, bài toán nhận dạng, bài toán đếm đối tượng, …). Do đó, cân bằng sáng ở bước tiền xử lý là một trong những cách giúp làm giảm các ảnh hưởng này.

Giải thuật cân bằng sáng

Link giải thuật cân bằng sáng trong OpenCV:

https://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.html#how-does-it-work

Giải thuật cân bằng sáng:

  1. Thống kê histogram cho ảnh: \(H(i)\).
  2. Áp dụng hàm biến đổi: \(H'(i) = \sum_{j=0}^{i} H(j)\).
  3. Chuẩn hóa histogram mới vừa biến đổi (\(H'(i)\)) về [0, 255].
  4. Mapping mức sáng ảnh kết quả theo \(H'\): \(I'(x,y) = H'(I(x,y))\). Với \(I(x,y)\) là ảnh gốc, \(I'(x,y)\) là ảnh đã cân bằng sáng.

Hiện thực Histogram Equalization

Chương trình bên dưới là mình đã hiện thực giải thuật Histogram Equalization từ đầu. Tính năng chương trình bao gồm:

  • Tạo image histogram từ ảnh img_6.jpg.
  • Trực quan hóa histogram bằng biểu đồ cột dùng thư viện seaborn. Các bạn cài đặt seaborn bằng lệnh: $ pip install seaborn.
  • Hiện thực giải thuật cân bằng sáng.
  • In ảnh đã cân bằng sáng.
  • Các bạn có thể thử với ảnh khác bằng cách thay img_6.jpg trong lệnh chạy bằng đường dẫn đến ảnh bạn muốn.
  • Lệnh thực thi chương trình: $ python hist_eq.py img_6.jpg

hist_eq.py

import os, sys
import cv2
import numpy as np

try:
    import seaborn as sns
    import pandas as pd
except:
    raise Exception('Seaborn or Pandas packages not found. Installation: $ pip install seaborn pandas')
    
def create_histogram(img):
    assert len(img.shape) == 2 # check grayscale image
    histogram = [0] * 256 # list of intensity frequencies, 256 zero values
    for row in range(img.shape[0]): # traverse by row (y-axis)
        for col in range(img.shape[1]): # traverse by column (x-axis)
            histogram[img[row, col]] += 1
    return histogram

def visualize_histogram(histogram, output='histogram.png'):
    hist_data = pd.DataFrame({'intensity': list(range(256)), 'frequency': histogram})
    sns_hist = sns.barplot(x='intensity', y='frequency', data=hist_data, color='blue')
    sns_hist.set(xticks=[]) # hide x ticks
    
    fig = sns_hist.get_figure()
    fig.savefig(output)
    return output

def equalize_histogram(img, histogram):
    # build H', cumsum
    new_H = [0] * 257
    for i in range(0, len(new_H)):
        new_H[i] = sum(histogram[:i])
    new_H = new_H[1:]
       
    # normalize H'
    #max_H = max(new_H)
    #max_hist = max(histogram)
    #new_H = [(f/max_H)*max_hist for f in new_H]
    
    # scale H' to [0, 255]
    max_value = max(new_H)
    min_value = min(new_H)
    new_H = [int(((f-min_value)/(max_value-min_value))*255) for f in new_H]
    
    print("H':", new_H)
    
    # apply H' to img
    for row in range(img.shape[0]): # traverse by row (y-axis)
        for col in range(img.shape[1]): # traverse by column (x-axis)
            img[row, col] = new_H[img[row, col]]
    return img

if __name__ == "__main__":
    assert len(sys.argv) == 2, '[USAGE] $ python %s img_6.jpg' % (os.path.basename(__file__), INPUT)
    INPUT = sys.argv[1]
    assert os.path.isfile(INPUT), '%s not found' % INPUT
    
    # read color image with grayscale flag: "cv2.IMREAD_GRAYSCALE"
    img = cv2.imread(INPUT, cv2.IMREAD_GRAYSCALE)
    # print grayscale image
    cv2.imwrite('grey_%s' % INPUT, img)
    print('Saved grayscale image @ grey_%s' % INPUT)
    
    # create histogram from image
    histogram = create_histogram(img)
    print('histogram:', histogram)
    
    hist_img_path = visualize_histogram(histogram)
    print('Saved histogram @ %s' % hist_img_path)
    
    equalized_img = equalize_histogram(img, histogram)
    cv2.imwrite('equalized_%s' % INPUT, equalized_img)
    print('Saved equalized image @ equalized_%s' % INPUT)
    
    new_histogram = create_histogram(equalized_img)
    print('new_histogram:', new_histogram)
    hist_img_path = visualize_histogram(new_histogram, output='histogram_eq.png')
    print('Saved new histogram @ %s' % hist_img_path)
    
    print('Done Tut 6: Histogram Equalization. Welcome to minhng.info')
    

Histogram trước khi cân bằng sáng:

Histogram sau khi cân bằng sáng:

Ảnh sau khi cân bằng sáng:

Histogram Equalization trong OpenCV

Trong OpenCV bạn chỉ cần gọi hàm để thực hiện cân bằng sáng: cv2.equalizeHist. Đoạn chương trình sau giúp ta cân bằng sáng ảnh (không in ra histogram).

$ python opencv_histeq.py đường_dẫn_đến_file_ảnh.jpg
$ python opencv_histeq.py img_6.jpg

opencv_histeq.py

import os, sys
import cv2

if __name__ == "__main__":
    assert len(sys.argv) == 2, '[USAGE] $ python %s img_6.jpg' % (os.path.basename(__file__), INPUT)
    INPUT = sys.argv[1]
    assert os.path.isfile(INPUT), '%s not found' % INPUT
    
    # read color image with grayscale flag: "cv2.IMREAD_GRAYSCALE"
    img = cv2.imread(INPUT, cv2.IMREAD_GRAYSCALE)       # shape: (960, 960)
    # print grayscale image
    cv2.imwrite('grey_%s' % INPUT, img)
    print('Saved grayscale image @ grey_%s' % INPUT)
    
    equalized_img = cv2.equalizeHist(img)
    cv2.imwrite('equalized_%s' % INPUT, equalized_img)
    print('Saved equalized image @ equalized_%s' % INPUT)
    
    print('Done Tut 6: Histogram Equalization. Welcome to minhng.info')
    

Cảm ơn bạn đã theo dõi bài viết. Hãy kết nối với tớ nhé!

  • Minh: https://www.facebook.com/minhng.info
  • Khám phá xử lý ảnh - GVGroup: https://www.facebook.com/groups/ip.gvgroup
Khám phá xử lý ảnh - GVGroup

Danh sách bài viết series OpenCV:

  • Hashtag #OpenCV
  • Tut 1: Xử lý ảnh - OpenCV đọc ghi hình ảnh (code Python và C++)
  • Tut 1.1: Xử lý ảnh - Cấu trúc dữ liệu ảnh trong OpenCV. Pixel là gì?
  • Tut 1.2: Xử lý ảnh - Chuyển đổi ảnh OpenCV sang Pillow và ngược lại
  • Tut 2: Xử lý ảnh - OpenCV resize, crop và padding hình ảnh (code Python và C++)
  • Tut 3: Xử lý ảnh - OpenCV biến đổi mức sáng hình ảnh (code Python)
  • Tut 4: Xử lý ảnh - OpenCV vùng quan tâm (ROI) là gì? (code Python)
  • Tut 4.1: Xử lý ảnh - OpenCV: vẽ văn bản, đường thẳng, mũi tên, hình chữ nhật, hình tròn, ellipse, đa giác
  • Tut 4.2: Xử lý ảnh - Pha trộn ảnh trong OpenCV (blending)
  • Tut 5: Xử lý ảnh - OpenCV ảnh nhị phân
  • Tut 6: Xử lý ảnh - OpenCV cân bằng sáng (histogram equalization)
  • Tut 7: Xử lý ảnh - OpenCV kỹ thuật cửa sổ trượt (sliding window)
  • Tut 8: Xử lý ảnh - Convolution là gì?
  • Tut 9: Xử lý ảnh - Làm mờ ảnh (blur)
  • Tut 10: Xử lý ảnh - Gradient của ảnh là gì?
  • Tut 11: Xử lý ảnh - Phát hiện cạnh Canny (Canny Edge Detection)
  • Tut 12: Xử lý ảnh - Phát hiện đường thẳng bằng Hough Transform (Hough Line)
  • Tut 13: Xử lý ảnh - Hiện thực phát hiện đoạn thẳng dùng Hough Transform (Hough Line)
  • Tut 14: Xử lý ảnh - Giải thuật phân vùng Region Growing trên ảnh màu
  • Tut 15: Xử lý ảnh - Giải thuật Background Subtraction trên ảnh màu
  • Tut 16: Xử lý ảnh - Frame Subtraction để phát hiện chuyển động trong video
  • Tut 17: Xử lý ảnh - HOG - Histograms of Oriented Gradients
  • Tut 18: Xử lý ảnh - HOG - Huấn luyện mô hình phân loại người
  • Tut 19: Xử lý ảnh - HOG - Phát hiện người
  • Tut 20: Xử lý ảnh - Tổng hợp kinh nghiệm xử lý ảnh (End)
  • Tut 21: Xử lý ảnh - Hiện thực trích đặc trưng Local Binary Patterns (LBP)
  • Tut 22: Xử lý ảnh - Trích đặc trưng Gabor filters