Thị giác máy tính với OpenCV-Python Bài 4, Phần 5: Độ dốc và cạnh của hình ảnh
13:24 - 30/12/2021
Trong phần này chúng ta sẽ tìm hiểu cách tìm độ dốc và cạnh hình ảnh thông qua các hàm sau: cv2.Sobel(), cv2.Scharr() và cv2.Laplacian().
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
OpenCV cung cấp ba loại bộ lọc độ dốc (hoặc bộ lọc thông cao) gồm: Sobel, Scharr và Laplacian. Chúng ta sẽ xem xét từng loại trong số chúng.
1. Sobel và Scharr
Các toán tử Sobel là một phép làm mịn Gausssian chung kết hợp với phép lấy đạo hàm, cho khả năng chống nhiễu tốt hơn. Có thể chỉ định hướng của các đạo hàm được lấy, theo chiều dọc hoặc chiều ngang (theo các đối số, theo trục x và y). Cũng có thể chỉ định kích thước của hạt nhân bằng đối số “ksize”. Nếu ksize = -1, bộ lọc 3x3 Scharr được sử dụng cho kết quả tốt hơn bộ lọc 3x3 Sobel.
Đoạn mã dưới đây hiển thị tất cả các toán tử trong một sơ đồ duy nhất. Tất cả các nhân có kích thước 5x5. Độ sâu của hình ảnh đầu ra được chuyển -1 để nhận kết quả ở kiểu np.uint8.
- import cv2
- import numpy as np
- from matplotlib import pyplot as plt
- img = cv2.imread('dave.jpg', 0)
- laplacian = cv2.Laplacian(img, cv2.CV_64F)
- sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
- sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
- plt.subplot(2, 2, 1), plt.imshow(img, cmap = 'gray')
- plt.title('Original'), plt.xticks([ ]), plt.yticks([ ])
- plt.subplot(2, 2, 2), plt.imshow(laplacian, cmap = 'gray')
- plt.title('Laplacian'), plt.xticks([ ]), plt.yticks([ ])
- plt.subplot(2, 2, 3), plt.imshow(sobelx, cmap = 'gray')
- plt.title('Sobel X'), plt.xticks([ ]), plt.yticks([ ])
- plt.subplot(2, 2, 4), plt.imshow(sobely, cmap = 'gray')
- plt.title('Sobel Y'), plt.xticks([ ]), plt.yticks([ ])
- plt.show()
Kết quả:
2. Một vấn đề quan trọng
Trong ví dụ trên, kiểu dữ liệu đầu ra là cv2.CV_8U hoặc np.uint8. Nhưng có một vấn đề nhỏ với điều đó. Chuyển đổi Đen sang Trắng được coi là độ dốc Dương (nó có giá trị dương) trong khi chuyển đổi Trắng sang Đen được coi là độ dốc Âm (Nó có giá trị âm). Vì vậy, khi chuyển đổi dữ liệu thành np.uint8, tất cả các độ dốc âm đều bằng không. Nói một cách đơn giản, các cạnh đó bị mất.
Nếu muốn phát hiện cả hai cạnh, tùy chọn tốt hơn là giữ kiểu dữ liệu đầu ra ở một số dạng cao hơn, như cv2.CV_16S, cv2.CV_64F, v.v., lấy giá trị tuyệt đối của nó và sau đó chuyển đổi trở lại cv2.CV_8U. Đoạn mã dưới đây trình bày quy trình này cho bộ lọc Sobel ngang và sự khác biệt trong kết quả.
- import cv2
- import numpy as np
- from matplotlib import pyplot as plt
- img = cv2.imread('box.png', 0)
- # Output dtype = cv2.CV_8U
- sobelx8u = cv2.Sobel(img, cv2.CV_8U, 1, 0, ksize=5)
- # Output dtype = cv2.CV_64F. Then take its absolute and convert to cv2.CV_8U
- sobelx64f = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
- abs_sobel64f = np.absolute(sobelx64f)
- sobel_8u = np.uint8(abs_sobel64f)
- plt.subplot(1, 3, 1), plt.imshow(img, cmap = 'gray')
- plt.title('Original'), plt.xticks([ ]), plt.yticks([ ])
- plt.subplot(1, 3, 2), plt.imshow(sobelx8u, cmap = 'gray')
- plt.title('Sobel CV_8U'), plt.xticks([ ]), plt.yticks([ ])
- plt.subplot(1, 3, 3), plt.imshow(sobel_8u, cmap = 'gray')
- plt.title('Sobel abs(CV_64F)'), plt.xticks([ ]), plt.yticks([ ])
- plt.show()
Kết quả:
Ở phần tiếp theo chúng ta sẽ tìm hiểu cách tìm cạnh trong hình ảnh qua thuật toán Canny.
(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