Để nhận diện hình ảnh chính xác thì input cần phải chuẩn, càng giống với ảnh được học thì càng tốt. Việc xác định ảnh sáng tối là bước tiền xử lý trước khi đưa vào phân lớp/dự đoán (classification/predict).
Sau khi xác định được ảnh quá tối hoặc quá sáng thì tùy bài toán mà xử lý phù hợp:
- Loại bỏ ảnh, không nhận diện ảnh không đáp ứng đúng yêu cầu
- Áp dụng thuật toán cân bằng sáng để khắc phục, đưa ảnh về độ sáng đúng chuẩn
Lý thuyết về độ sáng ảnh
Dựa vào bài viết về quang đồ (histogram) thì ảnh bị thiếu sáng là ảnh có quang đồ lệch về bên trái. Ảnh dư sáng là ảnh có quang đồ lệch về bên phải, còn ảnh đủ sáng là quang đồ phân bố đều.
Có cách khác là dùng Photoshop để xem quang đồ, VD bên dưới là quang đồ của 1 ảnh chụp ban đêm (Ấn Crl + L trong photoshop)
Hình trên quang đồ lệch về bên trái, để khắc phục thì chỉnh như hình dưới để về đúng sáng
Xác định ảnh thiếu sáng bằng thuật toán OpenCV
Nguyên lý để xác định là đếm số pixel thiếu sáng và pixel dư sáng trên tổng số pixel. Như hình dưới là quang đồ được chia thành 3 khoảng, nếu số pixel nằm trong vùng tối nhiều hơn thì suy ra thiếu sáng.
Tùy theo bài toán mà các bạn có thể điều chỉnh khoảng cho phù hợp nhất. Để dễ dàng tính toán ta sử dụng hệ màu HSV để tính giá trị dễ dàng vì kênh màu V thể hiện độ sáng của ảnh.
Code python phát hiện ảnh thiếu sáng
[bg_collapse view=”button-orange” color=”#4a4949″ expand_text=”expand” collapse_text=”collapse” ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
def CheckBright(frame): hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) hist = cv2.calcHist([hsv], [2], None, [256], [0, 256]) sum = np.sum(hist) dark = 0 bright = 0 for i in range(0, 65): dark += hist[i, 0] for i in range(230, 255): bright += hist[i, 0] dark_per = dark / sum bright_per = bright / sum # Compare to THRESHOLD if dark_per > 0.40: result = 'Dark' mean = dark_per elif bright_per > 0.40: result = 'Bright' mean = bright_per else: result = 'Ok' mean = dark_per return result, mean |
Xử lý ảnh thiếu sáng
Cách phổ biến đó là dùng hàm cv2.equalizeHist() => kết quả nhìn chán òm, mất đi contrast khá nhiều nên mình không giới thiệu cách này.
Cách mà mình giới thiệu đó là thay đổi giá trị contrast và brightness của ảnh, mình ưng ý kết quả này
Code python thay đổi độ sáng ảnh
[bg_collapse view=”button-orange” color=”#4a4949″ expand_text=”expand” collapse_text=”collapse” ]
1 2 3 4 5 6 7 8 9 10 11 12 |
import cv2 from matplotlib import pyplot as plt image = cv2.imread("test.jpg") alpha = 2 # Contrast control (1.0-3.0) beta = 0 # Brightness control (0-100) cv2.putText(image, "alpha: " + str(alpha), (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 255), 2, cv2.LINE_AA) cv2.putText(image, "beta: " + str(beta), (0, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 255), 2, cv2.LINE_AA) img_output = cv2.convertScaleAbs(image, alpha=alpha, beta=beta) plt.imshow(cv2.cvtColor(img_output, cv2.COLOR_BGR2RGB)) cv2.imwrite("output.jpg", img_output) |
Kết luận
Đây là 1 cách khá hiệu quả và dễ sử dụng, các bạn có thể dùng cho các bài toán không yêu cầu độ chính xác quá cao. Code có tích hợp vào TGMTpython để các bạn test thử