Thị giác máy tính với OpenCV-Python Bài 4, Phần 11: Chiếu ngược biểu đồ

Thị giác máy tính với OpenCV-Python Bài 4, Phần 11: Chiếu ngược biểu đồ

Thị giác máy tính với OpenCV-Python Bài 4, Phần 11: Chiếu ngược biểu đồ

16:49 - 06/01/2022

Trong phần này, chúng ta sẽ tìm hiểu về phép chiếu ngược biểu đồ để trích xuất ra đối tượng mong muốn.

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 2: Phép trừ nền
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

Lý thuyết

Thuật toán chiếu ngược biểu đồ được đề xuất bởi Michael J. Swain, Dana H. Ballard trong bài báo của họ mang tựa đề “Lập chỉ mục thông qua biểu đồ màu”.

Thuật toán được sử dụng để phân đoạn hình ảnh hoặc tìm kiếm các đối tượng quan tâm trong một hình ảnh. Nói theo cách đơn giản, nó tạo ra một hình ảnh có cùng kích thước (nhưng đơn kênh) như hình ảnh đầu vào, trong đó mỗi pixel tương ứng với xác suất pixel đó thuộc đối tượng đang quan tâm.

Thuật toán hoạt động như thế nào? Đầu tiên chúng ta tạo biểu đồ của một hình ảnh chứa đối tượng đang quan tâm. Biểu đồ màu được ưa thích hơn biểu đồ thang độ xám, bởi vì màu sắc của đối tượng là cách xác định đối tượng tốt hơn so với cường độ thang độ xám. Sau đó, chúng ta “chiếu ngược” biểu đồ này lên hình ảnh thử nghiệm nơi chúng ta cần tìm đối tượng, tức là chúng ta tính xác suất của mọi pixel thuộc về đối tượng cần tìm và hiển thị nó. Kết quả đầu ra trên ngưỡng thích hợp cung cấp cho chúng ta vùng đối tượng đang cần.

Thuật toán trong Numpy

Đầu tiên, chúng ta cần tính toán biểu đồ màu của cả đối tượng cần tìm (đặt nó là 'M') và hình ảnh mà chúng ta sẽ tìm kiếm (đặt nó là 'I'):

  1. import cv2
  2. import numpy as np
  3. from matplotlib import pyplot as plt
  4. #roi is the object or region of object we need to find
  5. roi = cv2.imread('rose_red.png')
  6. hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
  7. #target is the image we search in
  8. target = cv2.imread('rose.png')
  9. hsvt = cv2.cvtColor(target, cv2.COLOR_BGR2HSV)
  10. # Find the histograms using calcHist. Can be done with np.histogram2d also
  11. M = cv2.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
  12. I = cv2.calcHist([hsvt], [0, 1], None, [180, 256], [0, 180, 0, 256])

Tìm tỷ lệ R = M/I. Sau đó sử dụng R làm bảng màu và tạo một hình ảnh mới với mọi pixel là xác suất mục tiêu tương ứng của nó, tức là B (x, y) = R[h (x, y), s(x, y)], trong đó h là màu và s là độ bão hòa của pixel tại (x, y). Sau đó áp dụng điều kiện B( x, y) = min[B (x, y), 1].

  1. h,s,v = cv2.split(hsvt)
  2. B = R[h.ravel(), ravel()]
  3. B = np.minimum(B, 1)
  4. B = B.reshape(hsvt.shape[:2])

Bây giờ áp dụng một phép chập với một đĩa tròn, B = D∗B, trong đó D là nhân đĩa.

  1. disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
  2. filter2D(B, -1, disc, B)
  3. B = np.uint8(B)
  4. normalize(B, B, 0, 255, cv2.NORM_MINMAX)

Bây giờ vị trí của cường độ cực đại cho chúng ta vị trí của đối tượng. Nếu chúng ta đang mong đợi một vùng trong hình ảnh, thì việc đặt ngưỡng cho một giá trị phù hợp sẽ cho kết quả tốt.

  1. ret, thresh = cv2.threshold(B, 50, 255, 0)

Phép chiếu ngược trong OpenCV

OpenCV cung cấp một hàm có sẵn cv2.calcBackProject(). Các tham số của nó gần giống như hàm cv2.calcHist(). Một trong những tham số của nó là histogram - biểu đồ của đối tượng và chúng ta cần tìm ra nó. Ngoài ra, biểu đồ đối tượng nên được chuẩn hóa trước khi truyền vào hàm. Nó trả về hình ảnh xác suất. Sau đó, chúng ta chuyển đổi hình ảnh với một nhân đĩa và áp dụng ngưỡng. Dưới đây là đoạn code minh họa việc trích xuất đối tượng giống với mẫu trong hình chữ nhật màu đen:

  1. import cv2
  2. import numpy as np
  3. roi = cv2.imread('roi.jpg')
  4. hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
  5. target = cv2.imread('lampard.jpg')
  6. hsvt = cv2.cvtColor(target, cv2.COLOR_BGR2HSV)
  7. # calculating object histogram
  8. roihist = cv2.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
  9. # normalize histogram and apply backprojection
  10. cv2.normalize(roihist, roihist, 0, 255, cv2.NORM_MINMAX)
  11. dst = cv2.calcBackProject([hsvt], [0,1], roihist, [0,180,0,256], 1)
  12. # Now convolute with circular disc
  13. disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
  14. cv2.filter2D(dst, -1, disc, dst)
  15. # threshold and binary AND
  16. ret, thresh = cv2.threshold(dst, 50, 255, 0)
  17. thresh = cv2.merge((thresh, thresh, thresh))
  18. res = cv2.bitwise_and(target, thresh)
  19. res = np.vstack((target, thresh, res))
  20. cv2.imwrite('res.jpg', res)

Kết quả:

 

 

Ở phần tiếp theo chúng ta sẽ cùng tìm hiểu cách tìm đối tượng trong ảnh bằng phương pháp đối sánh mẫu.

 

(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