Xử lý ảnh - Làm mờ ảnh (blur)

  Apr 5, 2019      2m
   

OpenCV - tut 9: Blur

Xử lý ảnh - Làm mờ ảnh (blur)

Môi trường "hành sự"

  • 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ý: girl_luv.jpg

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

girl_luv.jpg (Nguồn: bí mật không thể bật mí :v)

girl luv

Ảnh gốc rõ lắm, nhưng mình cố tình tạo thử thách bằng cách thêm nhiễu để có cái để làm cho mấy bộ làm mờ chứ :P

add noise

Hiệu ứng làm mờ ảnh

Khi nhắc đến việc làm mờ hình ảnh, bạn sẽ nghĩ ngay đến việc tại mình phải làm điều đó? Ảnh đang rõ vậy làm mờ chi cho khó nhìn ta?!

Thực ra trong xử lý ảnh, phép làm mờ ảnh được dùng rất nhiều và có nhiều vai trò quan trọng. Hiệu ứng làm mờ mang lại (áp dụng trong các trường hợp):

  • Giảm nhiễu (noise) trong ảnh
  • Làm trơn ảnh (smooth). Việc làm trơn ảnh sẽ giảm sắc nét của cạnh, thay vào đó, vùng trơn sẽ lan ra

Trong các bài báo về xử lý ảnh, ở bước tiền xử lý họ hay dùng 2 phép biến đổi sau:

  • Cân bằng sáng
  • Làm mờ

Kích thước cửa sổ của các bộ lọc làm thường là SỐ LẺ NGUYÊN DƯƠNG (3, 5, 7, 9, …). Chính vì kích thước lẻ nên ta sẽ chỉ có 1 pixel ở trung tâm kernel, điều này tránh việc ta phải phân vân nên lấy pixel trái hay phải làm pixel trung tâm NẾU kích thước bộ lọc là số chẵn!

Việc chọn kích thước bộ lọc thường dựa vào kích thước ảnh đầu vào và kinh nghiệm. Kernel thường được thiết kế hình vuông (tức width = height)

Tính toán xử lý cho phép biến đổi làm mờ ảnh chính là dùng toán tử convolution để áp cửa sổ / bộ lọc lên ảnh gốc.

Tiếp theo, mình sẽ giới thiệu 3 bộ làm mờ giảm nhiễu phổ biến: Box Filter, Gaussian Filter và Median Filter

Bộ lọc mờ trung bình (Box Filter)

  • Bộ lọc làm mờ trung bình được thiết kế bằng cách thiết lập mỗi giá trị trên bộ lọc bằng: 1/(W*H).
  • Tức là nếu Width và Height của bộ lọc bằng 3. Thì giá trị trên cửa sổ convolve sẽ là: 1/9.

box_blur.py

import os
import cv2

INPUT = 'girl_luv.jpg'
KERNEL_WIDTH = 3
KERNEL_HEIGHT = 3

if not os.path.isfile(INPUT):
    raise Exception('File not found @ %s' % INPUT)

img = cv2.imread(INPUT)


blur_img = cv2.blur(img, ksize=(KERNEL_WIDTH, KERNEL_HEIGHT)) # or cv2.boxFilter

cv2.imwrite('box_blur_%s_%d_%d.jpg' % (os.path.splitext(os.path.basename(INPUT))[0], KERNEL_WIDTH, KERNEL_HEIGHT), blur_img)

box blur

Hãy thử thay đổi các hằng số trong code để trải nghiệm các mức độ làm mờ khác nhau nhé:

  • KERNEL_WIDTH
  • KERNEL_HEIGHT

Bộ lọc làm mờ Gaussian (Gaussian Filter)

gaussian_blur.py

import os
import cv2

INPUT = 'girl_luv.jpg'
KERNEL_WIDTH = 9
KERNEL_HEIGHT = 9
SIGMA_X = 4
SIGMA_Y = 4

if not os.path.isfile(INPUT):
    raise Exception('File not found @ %s' % INPUT)

img = cv2.imread(INPUT)


blur_img = cv2.GaussianBlur(img, ksize=(KERNEL_WIDTH, KERNEL_HEIGHT), sigmaX=SIGMA_X, sigmaY=SIGMA_Y)

cv2.imwrite('gaussian_blur_%s_%d_%d_%d_%d.jpg' % (os.path.splitext(os.path.basename(INPUT))[0], KERNEL_WIDTH, KERNEL_HEIGHT, SIGMA_X, SIGMA_Y), blur_img)

gaussian blur

Hãy thử thay đổi các hằng số trong code để trải nghiệm các mức độ làm mờ khác nhau nhé:

  • KERNEL_WIDTH
  • KERNEL_HEIGHT
  • SIGMA_X
  • SIGMA_Y

Bộ lọc làm mờ trung vị (Median Filter)

  • Trung vị (median) là ta lấy ra giá trị trung vị sau khi sắp thứ tự dãy số. Ví dụ: median([6, 8, 11, 4, 1]) = 6. Giải: sau khi sắp thứ tự dãy [6, 8, 11, 4, 1], ta được [1, 4, 6, 8, 11] => số ở giữa dãy đã sắp thứ tự là 6.
  • Rất hiệu quả với nhiễu muối tiêu (tức nhiễu các hạt nhỏ trong ảnh).
  • Trong OpenCV, tham số cho bộ lọc trung vị chỉ có KERNEL_SIZE (không cho đặc tả Width / Height) và phải là số lẻ.

median_blur.py

import os
import cv2

INPUT = 'girl_luv.jpg'
KERNEL_SIZE = 9

if not os.path.isfile(INPUT):
    raise Exception('File not found @ %s' % INPUT)

img = cv2.imread(INPUT)


blur_img = cv2.medianBlur(img, KERNEL_SIZE)

cv2.imwrite('median_blur_%s_%d.jpg' % (os.path.splitext(os.path.basename(INPUT))[0], KERNEL_SIZE), blur_img)

median blur

Hãy thử thay đổi các hằng số trong code để trải nghiệm các mức độ làm mờ khác nhau nhé:

  • KERNEL_SIZE

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


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