Thị giác máy tính với OpenCV-Python Bài 5 Phần 2: So khớp đối tượng

Thị giác máy tính với OpenCV-Python Bài 5 Phần 2: So khớp đối tượng

Thị giác máy tính với OpenCV-Python Bài 5 Phần 2: So khớp đối tượng

08:30 - 18/01/2022

Trong phần này chúng ta sẽ tìm hiểu cách so khớp đối tượng sử dụng thuật toán Brute-Force và FLANN Matcher 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 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

Thuật toán Brute-Force

Đây là thuật toán so khớp những đặc điểm chính của một đối tượng ở hình ảnh thứ nhất với những mô tả đặc điểm chính trong hình ảnh thứ hai. Mỗi so sánh tạo ra một giá trị khoảng cách và kết quả phù hợp nhất được trả về trên cơ sở khoảng cách nhỏ nhất.

Để bắt đầu sử dụng thuật toán so khớp đối tượng trong OpenCV, đầu tiên chúng ta hãy bắt đầu bằng việc tải hình ảnh lên và sử dụng bộ mô tả ORB để so khớp các đặc điểm:

  1. import numpy as np
  2. import cv2
  3. import matplotlib.pyplot as plt
  4. img1 = cv2.imread('book.jpg', 0) # queryImage
  5. img2 = cv2.imread('books.jpg', 0) # trainImage
  6. # Initiate ORB detector
  7. orb = cv2.ORB_create()
  8. # find the keypoints and descriptors with ORB
  9. kp1, des1 = orb.detectAndCompute(img1, None)
  10. kp2, des2 = orb.detectAndCompute(img2, None)

Tiếp theo, chúng ta tạo một đối tượng BFMatcher với phép đo khoảng cách cv2.NORM_HAMMING (phù hợp với ORB) và crossCheck được bật để có kết quả tốt hơn. Sau đó, chúng ta sử dụng phương thức Matcher.match() để có được kết quả phù hợp nhất trong hai hình ảnh. Cần sắp xếp chúng theo thứ tự tăng dần về khoảng cách để xuất hiện những đối tượng phù hợp nhất (với khoảng cách ngắn nhất). Sau đó hiển thị 10 đặc điểm so khớp đầu tiên (Bạn có thể tăng nó lên tùy thích).

  1. # create BFMatcher object
  2. bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
  3. # Match descriptors.
  4. matches = bf.match(des1, des2)
  5. # Sort them in the order of their distance.
  6. matches = sorted(matches, key = lambda x:x.distance)
  7. # Draw first 10 matches.
  8. img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)
  9. plt.imshow(img3), plt.show()

Kết quả:

 

Kết quả so khớp đối tượng là gì?

Kết quả so khớp đối tượng “matches = bf.match(des1, des2)” là danh sách các đối tượng DMatch. Đối tượng DMatch này có các thuộc tính sau:

  • distance - Khoảng cách giữa các bộ mô tả. Càng thấp, càng tốt.
  • trainIdx - Chỉ mục của bộ mô tả trong chuỗi các bộ mô tả.
  • queryIdx - Chỉ mục của bộ mô tả trong truy vấn các bộ mô tả.
  • imgIdx - Chỉ mục của chuỗi hình ảnh.

Kết hợp Brute-Force với Bộ mô tả SIFT và Phép thử tỷ lệ

Chúng ta sẽ sử dụng BFMatcher.knnMatch() để có được k đặt điểm so khớp tốt nhất. Trong ví dụ này, chúng ta sẽ lấy k = 2 để có thể áp dụng phép thử tỷ lệ được đưa ra bởi D.Lowe:

  1. import numpy as np
  2. import cv2
  3. from matplotlib import pyplot as plt
  4. img1 = cv2.imread('book.jpg', 0) # queryImage
  5. img2 = cv2.imread('books.jpg', 0) # trainImage
  6. # Initiate SIFT detector
  7. sift = cv2.SIFT_create()
  8. # find the keypoints and descriptors with SIFT
  9. kp1, des1 = sift.detectAndCompute(img1, None)
  10. kp2, des2 = sift.detectAndCompute(img2, None)
  11. # BFMatcher with default params
  12. bf = cv2.BFMatcher()
  13. matches = bf.knnMatch(des1, des2, k=2)
  14. # Apply ratio test
  15. good = []
  16. for m,n in matches:
  17.     if m.distance < 0.75*n.distance:
  18.          good.append([m])
  19. # cv2.drawMatchesKnn expects list of lists as matches.
  20. img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, None, flags=2)
  21. plt.imshow(img3), plt.show()

Kết quả:

 

So khớp dựa trên FLANN

FLANN là viết tắt của “Fast Library for Approximate Nearest Neighbors”. Nó chứa một bộ sưu tập các thuật toán được tối ưu hóa để tìm kiếm lân cận một cách nhanh chóng trong bộ dữ liệu lớn và cho các đặc điểm chiều cao. Nó hoạt động nhanh hơn BFMatcher cho các tập dữ liệu lớn. Chúng ta sẽ xem ví dụ thứ hai với công cụ so khớp dựa trên FLANN.

Đối với trình so khớp dựa trên FLANN, chúng ta cần truyền hai từ điển chỉ định thuật toán sẽ được sử dụng và các tham số liên quan của nó. Đầu tiên là IndexParams:

index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)

Trong khi sử dụng ORB, chúng ta có thể truyền những thông số sau:

index_params= dict(algorithm = FLANN_INDEX_LSH,

                   table_number = 6, # 12

                   key_size = 12, # 20

                   multi_probe_level = 1) #2

Từ điển thứ hai là SearchParams. Nó chỉ định số lần các cây trong chỉ mục nên được duyệt đệ quy. Giá trị cao hơn mang lại độ chính xác tốt hơn, nhưng cũng mất nhiều thời gian hơn. Nếu bạn muốn thay đổi giá trị, hãy chuyển search_params = dict (checks = 100).

Dưới đây là đoạn code minh họa:

  1. import numpy as np
  2. import cv2
  3. from matplotlib import pyplot as plt
  4. img1 = cv2.imread('book.jpg', 0) # queryImage
  5. img2 = cv2.imread('books.jpg', 0) # trainImage
  6. # Initiate SIFT detector
  7. sift = cv2.SIFT_create()
  8. # find the keypoints and descriptors with SIFT
  9. kp1, des1 = sift.detectAndCompute(img1, None)
  10. kp2, des2 = sift.detectAndCompute(img2, None)
  11. # FLANN parameters
  12. FLANN_INDEX_KDTREE = 0
  13. index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
  14. search_params = dict(checks=50) # or pass empty dictionary
  15. flann = cv2.FlannBasedMatcher(index_params, search_params)
  16. matches = flann.knnMatch(des1, des2, k=2)
  17. # Need to draw only good matches, so create a mask
  18. matchesMask = [[0,0] for i in range(len(matches))]
  19. # ratio test as per Lowe's paper
  20. for i, (m,n) in enumerate(matches):
  21.      if m.distance < 0.7*n.distance:
  22.            matchesMask[i]=[1,0]
  23. draw_params = dict(matchColor = (0,255,0),
  24.              singlePointColor = (255,0,0),
  25.              matchesMask = matchesMask,
  26.              flags = 0)
  27. img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches, None, **draw_params)
  28. plt.imshow(img3, ), plt.show()

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 một bức ảnh phức tạp gồm nhiều đối tượng.

 

 (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