Thị giác máy tính với OpenCV-Python Bài 6 Phần 2: Phép trừ nền

Thị giác máy tính với OpenCV-Python Bài 6 Phần 2: Phép trừ nền

Thị giác máy tính với OpenCV-Python Bài 6 Phần 2: Phép trừ nền

13:26 - 25/01/2022

Trong phần này chúng ta sẽ cùng làm quen với các phương pháp trừ nền (Background subtraction) có sẵn trong OpenCV.

Thị giác máy tính với OpenCV-Python Bài 7 Phần 3: Nhận diện khuôn mặt
Thị giác máy tính với OpenCV-Python Bài 7 Phần 2: Phát hiện người đi bộ trong video
Thị giác máy tính với OpenCV-Python Bài 7 Phần 1: Phát hiện người đi bộ trong hình ảnh
Thị giác máy tính với OpenCV-Python Bài 6 Phần 1: Bắt bám đối tượng với Meanshift và Camshift
Thị giác máy tính với OpenCV-Python Bài 5 Phần 3: Tìm đối tượng thông qua so khớp và phép chiếu hình học

Khái niệm cơ bản

Trừ nền là một bước tiền xử lý chính trong nhiều ứng dụng dựa trên thị giác. Lấy ví dụ: hãy xem xét các trường hợp như cần đếm số lượng khách ra vào quầy qua camera hoặc camera giao thông trích xuất thông tin về các phương tiện,... Trong tất cả các trường hợp này, trước tiên chúng ta cần trích xuất được riêng hình ảnh người hoặc phương tiện. Về mặt kỹ thuật, chúng ta cần trích xuất phần hình ảnh chuyển động từ nền tĩnh.

Nếu chỉ có một hình ảnh nền, chẳng hạn như hình ảnh của căn phòng không có khách, hình ảnh của con đường không có xe cộ,... đó là một việc dễ dàng: chỉ cần trừ hình ảnh mới khỏi nền thì sẽ thu được các đối tượng tiền cảnh. Nhưng trong hầu hết các trường hợp, hình nền có thể phức tạp hơn nhiều, vì vậy chúng ta cần trích xuất nền từ bất kỳ hình ảnh nào. Mọi thứ còn trở nên phức tạp hơn khi có bóng của các phương tiện. Vì bóng cũng đang chuyển động, nên phép trừ đơn giản cũng sẽ đánh dấu bóng đó là tiền cảnh.

OpenCV cung cấp 3 cách triển khai thuật toán này một cách rất dễ sử dụng. Chúng ta sẽ xem từng cách một.

BackgroundSubtractorMOG

Đây là một thuật toán phân chia nền/tiền cảnh được giới thiệu bởi P. KadewTraKuPong và R. Bowden vào năm 2001. Nó sử dụng một phương pháp để lập mô hình từng pixel nền bằng hỗn hợp các phân bố K Gaussian (K = 3 đến 5). Trọng số của hỗn hợp thể hiện tỷ lệ thời gian mà những màu đó ở trong cảnh. Màu nền là những màu tồn tại lâu hơn và tĩnh hơn.

Để thực thi đoạn code, chúng ta cần tạo một đối tượng nền bằng cách sử dụng hàm cv2.createBackgroundSubtractorMOG(). Hàm này có một vài tham số tùy chọn như độ dài lịch sử, số lượng hỗn hợp gaussian, ngưỡng,... Tất cả đều được đặt thành một số giá trị mặc định. Sau đó, bên trong vòng lặp video, sử dụng phương thức backgroundsubtractor.apply() để lấy mặt nạ tiền cảnh.

Xem một ví dụ đơn giản dưới đây:

  1. import numpy as np
  2. import cv2
  3. cap = cv2.VideoCapture('cars.mp4')
  4. fgbg = cv2.bgsegm.createBackgroundSubtractorMOG()
  5. while(1):
  6.     ret, frame = cap.read()
  7.     fgmask = fgbg.apply(frame)
  8.     cv2.imshow('frame', fgmask)
  9.     k = cv2.waitKey(30) & 0xff
  10.     if k == 27:
  11.     break
  12. cap.release()
  13. cv2.destroyAllWindows()

BackgroundSubtractorMOG chỉ được hỗ trợ trong python2, do dó cần thêm đường dẫn “.bgsegm” để gọi hàm. Trong python3, hàm tương ứng được hỗ trợ là BackgroundSubtractorMOG2.

BackgroundSubtractorMOG2

Đây cũng là một thuật toán phân nền/tiền cảnh dựa trên Gaussian. Một tính năng quan trọng của thuật toán này là nó chọn số lượng phân phối gaussian thích hợp cho mỗi pixel (chú ý rằng, ở trên chúng ta đã lấy phân phối K gaussian cho cả thuật toán). Cách triển khai này cung cấp khả năng thích ứng tốt hơn với các cảnh khác nhau do thay đổi ánh sáng,...

Như trong trường hợp trước, chúng ta phải tạo một đối tượng dấu trừ nền. Tại đây, bạn có một tùy chọn xem bóng có được phát hiện hay không. Nếu DetShadows = True (theo mặc định), nó sẽ phát hiện và đánh dấu bóng, nhưng sẽ làm giảm tốc độ. Bóng sẽ được đánh dấu bằng màu xám.

  1. import numpy as np
  2. import cv2
  3. cap = cv2.VideoCapture('cars.mp4')
  4. fgbg = cv2.createBackgroundSubtractorMOG2()
  5. while(1):
  6.     ret, frame = cap.read()
  7.     fgmask = fgbg.apply(frame)
  8.     cv2.imshow('frame', fgmask)
  9.     k = cv2.waitKey(30) & 0xff
  10.     if k == 27:
  11.     break
  12. cap.release()
  13. cv2.destroyAllWindows()

BackgroundSubtractorGMG

Thuật toán này kết hợp ước tính hình ảnh nền thống kê và phân đoạn Bayes trên mỗi pixel. Nó sử dụng một vài khung hình đầu tiên (120 theo mặc định) để tạo mô hình nền và sử dụng thuật toán phân đoạn tiền cảnh xác suất để xác định các đối tượng tiền cảnh có thể có bằng cách sử dụng suy luận Bayes. Các quan sát mới hơn có trọng số lớn hơn các quan sát cũ để thích ứng với khả năng chiếu sáng thay đổi. Một số hoạt động lọc hình thái học như đóng và mở được thực hiện để loại bỏ nhiễu không mong muốn. Bạn sẽ nhận được một cửa sổ màu đen trong một vài khung hình đầu tiên. Xem đoạn code minh họa:

  1. import numpy as np
  2. import cv2
  3. cap = cv2.VideoCapture('cars.mp4')
  4. kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
  5. fgbg = cv2.bgsegm.createBackgroundSubtractorGMG()
  6. while(1):
  7.     ret, frame = cap.read()
  8.     fgmask = fgbg.apply(frame)
  9.     fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
  10.     cv2.imshow('frame', fgmask)
  11.     k = cv2.waitKey(30) & 0xff
  12.     if k == 27:
  13.     break
  14. cap.release()
  15. cv2.destroyAllWindows()

Các kết quả:

 

Hình 1. Khung hình gốc (hình ảnh cắt ra từ 1 khung hình của video)

 

Hình 2. Kết quả của BackgroundSubtractorMOG

 

Hình 3. Kết quả của BackgroundSubtractorMOG2 (Vùng màu xám hiển thị vùng bóng tối)

 

Hình 4. Kết quả của BackgroundSubtractorGMG (Nhiễu được loại bỏ với hình thái mở)

Ở phần tiếp theo chúng ta sẽ cùng tìm hiểu cách phát hiện người đi bộ trong hình ảnh sử dụng kỹ thuật HOG.

 

 (Sưu tầm)
VIỆN IMC
Tòa nhà IMC Tower, Số 176 Trường Chinh, Phường Khương
Thượng, Quận Đống Đa, Thành phố Hà Nội, Việt Nam
Tel/Fax : (+84) 24 3566 6232 / 24 3566 6234
Email: contact@imc.org.vn   Website: https://imc.org.vn