Xử lý ảnh - OpenCV ảnh nhị phân
OpenCV - tut 5: kỹ thuật Thresholding, Adaptive Thresholding
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ý (bài viết sử dụng ảnh img_5.jpg, xem bên dưới)
Bạn có thể download ảnh mẫu về: img_5.jpg
Ảnh nhị phân là gì?
Ảnh nhị phân (hay còn gọi là binary image trong tiếng Anh) là ảnh đen trắng chỉ có 2 giá trị là 0 và 255 (miền số nguyên) hoặc 0 và 1 (miền số thực / đối với ROI).
Minh họa ảnh nhị phân bạn sẽ thấy ở các ảnh demo các phần bên dưới.
Công dụng ảnh nhị phân
- Ảnh nhị phân thường được dùng cho phân đoạn ảnh (segmentation). Ví dụ: phân đoạn ảnh lá cây (những pixel nào là của cái lá), ta được ảnh nhị phân từ ảnh gốc (ảnh màu hoặc ảnh xám), từ đó ta biết trích xuất được thông tin "diện tích" lá.
- Nhị phân hóa ảnh là bước tiền xử lý rất hữu ích cho các giải thuật nhận dạng chữ viết / ký tự (OCR: Optical Character Recognition).
- Nhị phân hóa ảnh để tạo mặt nạ region of interest: xem bài post Tut 4: OpenCV vùng quan tâm (ROI) là gì? (code Python). Từ đó ta có thể áp dụng các phép biến đổi xử lý ảnh chỉ trên vùng ROI (thường thấy trong Photoshop).
- Trong Photoshop ta thường nhị phân hóa ảnh để loại bỏ nền (ví dụ như nền trắng) tạo ảnh có độ trong suốt (transparent) file ảnh có đuôi .png.
Các bước nhị phân hóa ảnh
- Biến đổi ảnh màu (color) sang ảnh xám (grayscale) hoặc đọc ảnh lên bằng cờ ảnh xám.
- Thiết lập ngưỡng (threshold) để nhị phân hóa ảnh.
- Áp dụng ngưỡng vào ảnh xám để tạo ảnh nhị phân hoặc áp dụng giải thuật nhị phân hóa ảnh. Các pixel có giá trị lớn hơn ngưỡng ta thiết lập bằng 255 (hoặc 1), nhỏ hơn ngưỡng ta thiết lập bằng 0.
Thực hành tạo ảnh nhị phân từ ảnh màu
Kỹ thuật Thresholding
- Đọc ảnh xám, dùng cờ cv2.IMREAD_GRAYSCALE.
- Thiết lập ngưỡng là 100 (hoặc ngưỡng giá trị khác bạn có thể sửa code lại).
- Áp dụng ngưỡng vào ảnh bằng hàm cv2.threshold của OpenCV.
Chạy lệnh:
$ python color2binary.py img_5.jpg
color2binary.py
import os, sys
import cv2
def convert_to_binary(img_grayscale, thresh=100):
thresh, img_binary = cv2.threshold(img_grayscale, thresh, maxval=255, type=cv2.THRESH_BINARY)
return img_binary
if __name__ == "__main__":
assert len(sys.argv) == 2, '[USAGE] $ python color2binary.py img_5.jpg'
input_image_path = sys.argv[1]
assert os.path.isfile(input_image_path), 'Image not found @ %s' % input_image_path
# read color image with grayscale flag: "cv2.IMREAD_GRAYSCALE"
img_grayscale = cv2.imread(input_image_path, cv2.IMREAD_GRAYSCALE) # shape: (960, 960)
# print grayscale image
cv2.imwrite('grey_%s' % input_image_path, img_grayscale)
print('Saved grayscale image @ grey_%s' % input_image_path)
img_binary = convert_to_binary(img_grayscale, thresh=100)
cv2.imwrite('binary_%s' % input_image_path, img_binary)
print('Saved binary image @ binary_%s' % input_image_path)
binary_img_5.jpg
Giải thuật Adaptive Thresholding
Đôi khi giải thuật Thresholding đơn giản phía trên chưa cho ra kết quả tốt. Lúc này ta cần xem xét đến các giải thuật nhị phân hóa hình ảnh mạnh mẽ hơn như là Adaptive Thresholding. Adaptive Thresholding lựa chọn ngưỡng (threshold) động trong vùng lân cận (neighborhood). Cụ thể giải thuật nó sẽ làm như sau:
- Đối với mỗi pixel ảnh, ta xét vùng ảnh con có blockSize x blockSize (blockSize là số lẻ) với pixel đang xét là trung tâm của vùng ảnh con này.
- Các mức sáng trong vùng ảnh con blockSize x blockSize -> ta tính giá trị trung bình M (đối với phương pháp adaptive "cv2.ADAPTIVE_THRESH_MEAN_C") -> threshold áp dụng cho pixel đang xét: threshold = M - C (C là hằng số xác định trước).
- Như vậy độ tốt của Adaptive Thresholding phụ thuộc vào 3 siêu tham số (hyper parameter):
- adaptiveMethod: cv2.ADAPTIVE_THRESH_MEAN_C / cv2.ADAPTIVE_THRESH_GAUSSIAN_C
- blockSize: kích thước vùng lân cận
- C: hằng số mà ta sẽ trừ đi (C có thể là số dương, số âm hay bằng 0)
adaptive_thresholding.py
import os, sys
import cv2
def convert_to_binary(img_grayscale):
# adaptiveMethod=cv2.ADAPTIVE_THRESH_MEAN_C or cv2.ADAPTIVE_THRESH_GAUSSIAN_C
img_binary = cv2.adaptiveThreshold(img_grayscale,
maxValue=255,
adaptiveMethod=cv2.ADAPTIVE_THRESH_MEAN_C,
thresholdType=cv2.THRESH_BINARY,
blockSize=15,
C=8)
return img_binary
if __name__ == "__main__":
assert len(sys.argv) == 2, '[USAGE] $ python adaptive_thresholding.py img_5.jpg'
input_image_path = sys.argv[1]
assert os.path.isfile(input_image_path), 'Image not found @ %s' % input_image_path
# read color image with grayscale flag: "cv2.IMREAD_GRAYSCALE"
img_grayscale = cv2.imread(input_image_path, cv2.IMREAD_GRAYSCALE) # shape: (960, 960)
# print grayscale image
cv2.imwrite('grey_%s' % input_image_path, img_grayscale)
print('Saved grayscale image @ grey_%s' % input_image_path)
img_binary = convert_to_binary(img_grayscale)
cv2.imwrite('adaptive_%s' % input_image_path, img_binary)
print('Saved binary image @ adaptive_%s' % input_image_path)
adaptive_img_5.jpg
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