Thị giác máy tính với OpenCV-Python Bài 3, Phần 3: Đánh giá hiệu suất đoạn code trong OpenCV

Thị giác máy tính với OpenCV-Python Bài 3, Phần 3: Đánh giá hiệu suất đoạn code trong OpenCV

Thị giác máy tính với OpenCV-Python Bài 3, Phần 3: Đánh giá hiệu suất đoạn code trong OpenCV

14:46 - 14/12/2021

Trong phần này chúng ta sẽ tìm hiểu cách đo lường và cải thiện hiệu suất đoạn code thông qua các hàm cv2.getTickCount , cv2.getTickFrequency, ...

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

Trong xử lý hình ảnh, thường phải xử lý số lượng lớn các thao tác mỗi giây, do đó, yêu cầu đối với đoạn code không chỉ cung cấp giải pháp chính xác mà còn phải theo cách nhanh nhất.

Ngoài OpenCV, Python cũng cung cấp những công cụ hữu ích trong việc đo thời gian thực thi, báo cáo chi tiết về đoạn code, như thời gian chạy mỗi hàm trong đoạn code, số lần hàm được gọi, ... Nếu sử dụng IPython, tất cả các tính năng này đều được tích hợp một cách tiện lợi đối với người dùng.

Đo lường hiệu suất với OpenCV

Hàm cv2.getTickCount trả về số chu kỳ đồng hồ sau một sự kiện tham chiếu (như thời điểm thiết bị được BẬT) cho đến thời điểm hàm này được gọi. Vì vậy, nếu thực hiện gọi nó trước và sau khi thực thi hàm, chúng ta sẽ nhận được số chu kỳ đồng hồ được sử dụng để thực thi một hàm.

Hàm cv2.getTickFrequency trả về tần số của chu kỳ đồng hồ hoặc số chu kỳ đồng hồ trên giây. Vì vậy, để tìm thời gian thực hiện tính bằng giây, chúng ta có thể làm như sau:

  1. e1 = cv2.getTickCount()
  2. # your code execution
  3. e2 = cv2.getTickCount()
  4. time = (e2 - e1)/ cv2.getTickFrequency()

Xem ví dụ minh họa bên dưới để hiểu rõ hơn:

  1. img1 = cv2.imread('messi.jpg')
  2. e1 = cv2.getTickCount()
  3. for i in range(5, 49, 2):
  4. img1 = cv2.medianBlur(img1, i)
  5. e2 = cv2.getTickCount()
  6. t = (e2 - e1)/cv2.getTickFrequency()
  7. print(t)
  8. # Result is 0.6345106 seconds

Ghi chú:

Chúng ta có thể làm tương tự với các mô-đun thời gian. Thay vì cv2.getTickCount, hãy sử dụng hàm time.time(), sau đó lấy chênh lệch của hai lần đo.

Tối ưu hóa mặc định trong OpenCV

Nhiều hàm trong OpenCV được tối ưu hóa bằng cách sử dụng SSE2, AVX, ... Chúng được bật theo mặc định trong khi biên dịch. Vì vậy, OpenCV chạy code được tối ưu hóa nếu nó được kích hoạt, nếu không nó sẽ chạy code chưa được tối ưu hóa. Bạn có thể sử dụng cv2.useOptimized() để kiểm tra xem nó có được bật / tắt hay không và cv2.setUseOptimized() để bật/tắt nó. Hãy xem một ví dụ đơn giản:

  1. # check if optimization is enabled
  2. Print(cv2.useOptimized())
  3. // True
  4. %timeit res = cv2.medianBlur(img, 49)
  5. // 10 loops, best of 3: 34.9 ms per loop
  6. # Disable it
  7. cv2.setUseOptimized(False)
  8. print(cv2.useOptimized())
  9. False
  10. %timeit res = cv2.medianBlur(img, 49)
  11. // 10 loops, best of 3: 64.1 ms per loop

Hãy để ý, hàm cv2.medianBlur được tối ưu hóa đã thực hiện nhanh hơn gấp 2 lần so với phiên bản chưa được tối ưu hóa. Nếu kiểm tra mã nguồn, chúng ta có thể thấy hàm này được tối ưu hóa bằng SIMD.

Đo lường hiệu suất trong IPython

Đôi khi bạn có thể cần so sánh hiệu suất của hai hoạt động tương tự. IPython cung cấp công cụ cho bạn thực hiện việc này. Nó chạy đoạn code nhiều lần để có kết quả chính xác hơn và thích hợp để đo các dòng code đơn.

Lấy ví dụ, bạn có biết phép toán cộng nào sau đây tốt hơn không, x = 5; y = x**2, x = 5; y = x*x, x = np.uint8 ([5]); y = x*x hay y = np.square (x)? Chúng ta sẽ có câu trả lời với timeit trong Ipython:

  1. x = 5
  2. %timeit y=x**2
  3. // 10000000 loops, best of 3: 73 ns per loop
  4. %timeit y=x*x
  5. // 10000000 loops, best of 3: 58.3 ns per loop
  6. z = np.uint8([5])
  7. %timeit y=z*z
  8. // 1000000 loops, best of 3: 1.25 us per loop
  9. %timeit y=np.square(z)
  10. // 1000000 loops, best of 3: 1.16 us per loop

Kết quả cho thấy, x = 5; y = x*x là nhanh nhất và nhanh hơn khoảng 20 lần so với Numpy. Nếu xem xét việc tạo mảng, nó có thể nhanh hơn tới 100 lần.

Ghi chú:

Các phép toán vô hướng trong Python nhanh hơn các phép toán vô hướng trong Numpy. Vì vậy, đối với các hoạt động bao gồm một hoặc hai phần tử, tính vô hướng của Python tốt hơn so với mảng Numpy. Numpy tận dụng lợi thế khi kích thước của mảng lớn hơn một chút.

Hãy thử một ví dụ nữa. Lần này, chúng ta sẽ so sánh hiệu suất của cv2.countNonZero() và np.count_nonzero() cho cùng một hình ảnh.

  1. %timeit z = cv2.countNonZero(img)
  2. // 100000 loops, best of 3: 15.8 us per loop
  3. %timeit z = np.count_nonzero(img)
  4. // 1000 loops, best of 3: 370 us per loop

Hãy xem kết quả, hàm OpenCV nhanh hơn gần 25 lần so với hàm Numpy.

Ghi chú:

Thông thường, các hàm OpenCV nhanh hơn các hàm Numpy. Vì vậy, đối với cùng một hoạt động, các chức năng OpenCV được ưu tiên hơn.

Cách tối ưu hóa hiệu suất

Có một số kỹ thuật và phương pháp viết code để khai thác hiệu suất tối đa của Python và Numpy. Điều quan trọng cần lưu ý ở đây là, trước tiên hãy cố gắng triển khai thuật toán một cách đơn giản. Khi nó đang hoạt động, hãy tìm ra những điểm nghẽn và tối ưu hóa chúng:

- Tránh sử dụng các vòng lặp trong Python càng xa càng tốt, đặc biệt là các vòng lặp kép/ba, ... vì chúng vốn rất chậm.

- Vectơ hóa thuật toán/code ở mức tối đa có thể vì Numpy và OpenCV được tối ưu hóa cho các hoạt động vectơ.

- Khai thác tính liên kết của bộ nhớ cache.

- Không tạo bản sao của mảng trừ khi nó là cần thiết. Hãy thử sử dụng các lượt xem để thay thế. Sao chép mảng là một hoạt động tốn kém thời gian.

Ngay cả sau khi thực hiện tất cả các thao tác này, nếu đoạn code vẫn chậm hoặc không thể tránh khỏi việc sử dụng các vòng lặp lớn, hãy sử dụng các thư viện bổ sung như Cython để làm cho nó nhanh hơn.

Ở phần tiếp theo chúng ta sẽ tìm hiểu cách chuyển đổi không gian màu của hình ảnh.

 

(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